Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
M
mnp-rs
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Package Registry
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Yunxiang Li
mnp-rs
Commits
12e578eb
Commit
12e578eb
authored
Dec 16, 2019
by
tleydxdy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
use more rust features
parent
c9eced8e
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
255 additions
and
105 deletions
+255
-105
src/lib.rs
src/lib.rs
+255
-105
No files found.
src/lib.rs
View file @
12e578eb
...
...
@@ -16,102 +16,251 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
pub
trait
Cost
{
fn
cost
(
&
self
)
->
usize
;
}
impl
Cost
for
usize
{
fn
cost
(
&
self
)
->
usize
{
*
self
}
}
pub
mod
CGA
{
use
super
::
Cost
;
use
std
::
cmp
::
Ordering
;
use
std
::
collections
::
btree_set
::
Iter
;
use
std
::
collections
::
BTreeSet
;
fn
get_cost
(
sol
:
&
BTreeSet
<
(
usize
,
usize
,
Vec
<
usize
>
)
>
)
->
usize
{
#[derive(Debug)]
struct
Solution
<
'a
,
T
:
Cost
>
(
BTreeSet
<
Bin
<
'a
,
T
>>
);
impl
<
'a
,
T
>
Solution
<
'a
,
T
>
where
T
:
Cost
,
{
fn
new
(
item
:
&
'a
T
)
->
Self
{
let
mut
set
=
BTreeSet
::
new
();
set
.insert
(
Bin
::
new
(
0
,
item
));
Self
(
set
)
}
fn
insert
(
&
mut
self
,
bin
:
Bin
<
'a
,
T
>
)
->
bool
{
self
.0
.insert
(
bin
)
}
fn
insert_into
(
&
mut
self
,
bin
:
&
Bin
<
'a
,
T
>
,
item
:
&
'a
T
)
->
bool
{
let
mut
bin
=
self
.0
.take
(
bin
)
.unwrap
();
bin
.push
(
item
);
self
.0
.insert
(
bin
)
}
fn
len
(
&
self
)
->
usize
{
self
.0
.len
()
}
fn
iter
(
&
self
)
->
Iter
<
Bin
<
'a
,
T
>>
{
self
.0
.iter
()
}
}
impl
<
'a
,
T
>
Cost
for
Solution
<
'a
,
T
>
where
T
:
Cost
,
{
// The cost of the biggest bin is the cost of the solution
fn
cost
(
&
self
)
->
usize
{
self
.iter
()
.next_back
()
.unwrap
()
.cost
()
}
}
impl
<
'a
,
T
>
Clone
for
Solution
<
'a
,
T
>
where
T
:
Cost
,
{
// The cost of the biggest bin is the cost of the solution
sol
.iter
()
.next_back
()
.unwrap
()
.0
fn
clone
(
&
self
)
->
Self
{
Self
(
self
.0
.clone
())
}
}
fn
is_perfect
(
k
:
usize
,
total
:
usize
,
sol
:
&
BTreeSet
<
(
usize
,
usize
,
Vec
<
usize
>
)
>
)
->
bool
{
// perfect partitions are either all the same, or the difference are 1
get_cost
(
sol
)
*
k
<=
total
+
k
#[derive(Debug)]
struct
Bin
<
'a
,
T
:
Cost
>
{
id
:
usize
,
cost
:
usize
,
vec
:
Vec
<&
'a
T
>
,
}
fn
_
solve
(
impl
<
'a
,
T
>
Bin
<
'a
,
T
>
where
T
:
Cost
,
{
fn
new
(
id
:
usize
,
item
:
&
T
)
->
Bin
<
T
>
{
Bin
{
id
,
cost
:
item
.cost
(),
vec
:
vec!
[
item
],
}
}
fn
push
(
&
mut
self
,
item
:
&
'a
T
)
{
self
.cost
+=
item
.cost
();
self
.vec
.push
(
item
);
}
}
impl
<
'a
,
T
>
Cost
for
Bin
<
'a
,
T
>
where
T
:
Cost
,
{
fn
cost
(
&
self
)
->
usize
{
self
.cost
}
}
impl
<
'a
,
T
>
Clone
for
Bin
<
'a
,
T
>
where
T
:
Cost
,
{
fn
clone
(
&
self
)
->
Self
{
Self
{
id
:
self
.id
,
cost
:
self
.cost
,
vec
:
self
.vec
.clone
(),
}
}
}
impl
<
'a
,
T
>
Ord
for
Bin
<
'a
,
T
>
where
T
:
Cost
,
{
fn
cmp
(
&
self
,
other
:
&
Self
)
->
Ordering
{
match
self
.cost
.cmp
(
&
other
.cost
)
{
Ordering
::
Equal
=>
self
.id
.cmp
(
&
other
.id
),
r
@
_
=>
r
,
}
}
}
impl
<
'a
,
T
>
PartialOrd
for
Bin
<
'a
,
T
>
where
T
:
Cost
,
{
fn
partial_cmp
(
&
self
,
other
:
&
Self
)
->
Option
<
Ordering
>
{
Some
(
self
.cmp
(
other
))
}
}
impl
<
'a
,
T
>
Eq
for
Bin
<
'a
,
T
>
where
T
:
Cost
{}
impl
<
'a
,
T
>
PartialEq
for
Bin
<
'a
,
T
>
where
T
:
Cost
,
{
fn
eq
(
&
self
,
other
:
&
Self
)
->
bool
{
self
.cost
==
other
.cost
&&
self
.id
==
other
.id
}
}
// perfect partitions are either all the same, or the difference are 1
fn
is_perfect
<
T
>
(
k
:
usize
,
total
:
usize
,
sol
:
&
Option
<
Solution
<
T
>>
)
->
bool
where
T
:
Cost
,
{
match
sol
.as_ref
()
{
Some
(
s
)
=>
s
.cost
()
*
k
<=
total
+
k
,
None
=>
false
,
}
}
fn
update_best
<
T
>
(
old_best
:
usize
,
potential
:
&
Option
<
Solution
<
T
>>
)
->
usize
where
T
:
Cost
,
{
potential
.as_ref
()
.map_or
(
old_best
,
|
x
|
x
.cost
())
}
fn
_
solve
<
'a
,
T
>
(
k
:
usize
,
mut
input
:
Vec
<
usize
>
,
mut
input
:
Vec
<
&
'a
T
>
,
total
:
usize
,
mut
part
:
BTreeSet
<
(
usize
,
usize
,
Vec
<
usize
>
)
>
,
mut
best
:
usize
,
)
->
Option
<
BTreeSet
<
(
usize
,
usize
,
Vec
<
usize
>
)
>>
{
mut
part
:
Solution
<
'a
,
T
>
,
best
:
&
mut
Option
<
Solution
<
'a
,
T
>>
,
)
->
bool
where
T
:
Cost
,
{
match
input
.pop
()
{
Some
(
n
)
=>
{
let
mut
result
=
None
;
Some
(
item
)
=>
{
let
mut
found
=
false
;
let
mut
cur_best
=
update_best
(
total
,
best
);
// If there's still empty bins,
use
the empty bin first.
// If there's still empty bins,
try
the empty bin first.
if
part
.len
()
<
k
{
let
mut
new_part
=
part
.clone
();
new_part
.insert
((
n
,
part
.len
(),
vec!
[
n
]));
match
_
solve
(
k
,
input
.clone
(),
total
,
new_part
,
best
)
{
Some
(
sol
)
=>
{
if
is_perfect
(
k
,
total
,
&
sol
)
{
return
Some
(
sol
);
}
best
=
get_cost
(
&
sol
);
result
=
Some
(
sol
);
let
mut
part
=
part
.clone
();
part
.insert
(
Bin
::
new
(
part
.len
(),
item
));
if
_
solve
(
k
,
input
.clone
(),
total
,
part
,
best
)
{
if
is_perfect
(
k
,
total
,
best
)
{
return
true
;
}
None
=>
(),
found
=
true
;
cur_best
=
update_best
(
cur_best
,
best
);
}
}
let
mut
first_bin
=
part
.iter
()
.next
()
.cloned
()
.unwrap
();
let
cur_max
=
get_cost
(
&
part
);
let
cur_max
=
part
.cost
();
// If all the bins are the same, just use the first one.
if
first_bin
.0
==
cur_max
&&
first_bin
.0
+
n
<
best
{
part
.remove
(
&
first_bin
);
first_bin
.0
+=
n
;
first_bin
.2
.push
(
n
);
part
.insert
(
first_bin
);
return
_
solve
(
k
,
input
.clone
(),
total
,
part
,
best
);
}
// If even if we perfect partition the rest of the k-1 bins we
// still won't lower the best, we can stop.
// Proceed if lowering the best is possible.
// Use ((a - 1) / b) + 1 for always round up division.
if
((
total
-
cur_max
-
1
)
/
k
)
+
1
<
best
{
// Try putting the next item in all the bins one by one,
// for the last i item they only need to be put in the last
// i smallest bins.
if
((
total
-
cur_max
-
1
)
/
k
)
+
1
<
cur_best
{
// If all the bins are the same, just use the first one.
let
first_bin
=
part
.iter
()
.next
()
.unwrap
();
let
cur_min
=
first_bin
.cost
();
if
cur_min
==
cur_max
&&
cur_min
+
item
.cost
()
<
cur_best
{
let
first_bin
=
first_bin
.clone
();
part
.insert_into
(
&
first_bin
,
item
);
return
_
solve
(
k
,
input
.clone
(),
total
,
part
,
best
);
}
// Try all the bins one by one,
for
(
i
,
bin
)
in
part
.iter
()
.enumerate
()
{
// for the last i item they only need to be put in the
// i smallest bins.
if
input
.len
()
<
i
{
break
;
}
// If improving the best is even possible
if
bin
.0
+
n
<
best
{
let
mut
new_part
=
part
.clone
();
let
mut
new_bin
=
new_part
.take
(
&
bin
)
.unwrap
();
new_bin
.0
+=
n
;
new_bin
.2
.push
(
n
);
new_part
.insert
(
new_bin
);
match
_
solve
(
k
,
input
.clone
(),
total
,
new_part
,
best
)
{
Some
(
sol
)
=>
{
if
is_perfect
(
k
,
total
,
&
sol
)
{
return
Some
(
sol
);
}
best
=
get_cost
(
&
sol
);
result
=
Some
(
sol
);
if
bin
.cost
()
+
item
.cost
()
<
cur_best
{
let
mut
part
=
part
.clone
();
part
.insert_into
(
bin
,
item
);
if
_
solve
(
k
,
input
.clone
(),
total
,
part
,
best
)
{
if
is_perfect
(
k
,
total
,
best
)
{
return
true
;
}
None
=>
(),
found
=
true
;
cur_best
=
update_best
(
cur_best
,
best
);
}
}
}
}
// Return the best result
we found in the sub-tree
.
return
result
;
// Return the best result
from the childs
.
return
found
;
}
// Leaf node,
we are done
.
// Leaf node,
nothing to do
.
None
=>
{
return
Some
(
part
);
*
best
=
Some
(
part
);
return
true
;
}
}
}
pub
fn
solve
(
k
:
usize
,
mut
input
:
Vec
<
usize
>
)
->
Vec
<
Vec
<
usize
>>
{
pub
fn
solve
<
T
>
(
k
:
usize
,
mut
input
:
Vec
<&
T
>
)
->
Vec
<
Vec
<&
T
>>
where
T
:
Cost
,
{
// Deal with dumb inputs.
let
total
=
input
.iter
()
.sum
();
let
total
=
input
.iter
()
.
map
(|
x
|
x
.cost
())
.
sum
();
if
k
==
1
||
total
==
0
{
return
vec!
[
input
];
}
else
if
input
.len
()
<=
k
{
...
...
@@ -119,18 +268,14 @@ pub mod CGA {
}
// Sort by increasing order, so pop() gives decreasing number.
input
.sort_unstable
(
);
input
.sort_unstable
_by_key
(|
x
|
x
.cost
()
);
// First number always goes in the "first" bin, so don't need to search a tree.
let
mut
part
=
BTreeSet
::
new
();
let
n
=
input
.pop
()
.unwrap
();
part
.insert
((
n
,
0
,
vec!
[
n
]));
let
part
=
Solution
::
new
(
input
.pop
()
.unwrap
());
_
solve
(
k
,
input
,
total
,
part
,
total
)
.unwrap
()
.iter
()
.map
(|
bin
|
bin
.2
.clone
())
.collect
()
let
mut
result
=
None
;
_
solve
(
k
,
input
,
total
,
part
,
&
mut
result
);
result
.unwrap
()
.iter
()
.map
(|
bin
|
bin
.vec
.clone
())
.collect
()
}
}
...
...
@@ -140,23 +285,26 @@ mod tests {
#[test]
fn
test_cga
()
{
assert_eq!
(
CGA
::
solve
(
1
,
vec!
[
1
,
3
,
2
]),
vec!
[
vec!
[
1
,
3
,
2
]]);
assert_eq!
(
CGA
::
solve
(
2
,
vec!
[
1
,
3
,
2
]),
vec!
[
vec!
[
3
],
vec!
[
2
,
1
]]);
assert_eq!
(
CGA
::
solve
(
1
,
vec!
[
&
1
,
&
3
,
&
2
]),
vec!
[
vec!
[
&
1
,
&
3
,
&
2
]]);
assert_eq!
(
CGA
::
solve
(
2
,
vec!
[
&
1
,
&
3
,
&
2
]),
vec!
[
vec!
[
&
3
],
vec!
[
&
2
,
&
1
]]
);
assert_eq!
(
CGA
::
solve
(
3
,
vec!
[
1
,
3
,
2
]),
vec!
[
vec!
[
1
],
vec!
[
3
],
vec!
[
2
]]
CGA
::
solve
(
3
,
vec!
[
&
1
,
&
3
,
&
2
]),
vec!
[
vec!
[
&
1
],
vec!
[
&
3
],
vec!
[
&
2
]]
);
assert_eq!
(
CGA
::
solve
(
4
,
vec!
[
1
,
3
,
2
]),
vec!
[
vec!
[
1
],
vec!
[
3
],
vec!
[
2
]]
CGA
::
solve
(
4
,
vec!
[
&
1
,
&
3
,
&
2
]),
vec!
[
vec!
[
&
1
],
vec!
[
&
3
],
vec!
[
&
2
]]
);
assert_eq!
(
CGA
::
solve
(
3
,
vec!
[
8
,
4
,
7
,
5
,
6
]),
vec!
[
vec!
[
8
],
vec!
[
7
,
4
],
vec!
[
6
,
5
]]
CGA
::
solve
(
3
,
vec!
[
&
8
,
&
4
,
&
7
,
&
5
,
&
6
]),
vec!
[
vec!
[
&
8
],
vec!
[
&
7
,
&
4
],
vec!
[
&
6
,
&
5
]]
);
assert_eq!
(
CGA
::
solve
(
4
,
vec!
[
8
,
4
,
7
,
5
,
6
]),
vec!
[
vec!
[
6
],
vec!
[
7
],
vec!
[
8
],
vec!
[
5
,
4
]]
CGA
::
solve
(
4
,
vec!
[
&
8
,
&
4
,
&
7
,
&
5
,
&
6
]),
vec!
[
vec!
[
&
6
],
vec!
[
&
7
],
vec!
[
&
8
],
vec!
[
&
5
,
&
4
]]
);
}
...
...
@@ -167,20 +315,20 @@ mod tests {
CGA
::
solve
(
8
,
vec!
[
32525
,
17303
,
7084
,
24185
,
2233
,
23788
,
20717
,
25841
,
14545
,
14807
,
30030
,
23001
,
310
,
10096
,
27283
,
8125
,
28625
,
21273
,
19109
,
25831
,
3628
,
25627
,
15169
,
26692
,
&
32525
,
&
17303
,
&
7084
,
&
24185
,
&
2233
,
&
23788
,
&
20717
,
&
25841
,
&
14545
,
&
14807
,
&
30030
,
&
23001
,
&
310
,
&
10096
,
&
27283
,
&
8125
,
&
28625
,
&
21273
,
&
19109
,
&
25831
,
&
3628
,
&
25627
,
&
15169
,
&
26692
,
]
),
vec!
[
vec!
[
25841
,
15169
,
14807
],
vec!
[
26692
,
19109
,
10096
],
vec!
[
25831
,
23001
,
7084
],
vec!
[
30030
,
25627
,
310
],
vec!
[
32525
,
21273
,
2233
],
vec!
[
24185
,
17303
,
14545
],
vec!
[
28625
,
23788
,
3628
],
vec!
[
27283
,
20717
,
8125
]
vec!
[
&
25841
,
&
15169
,
&
14807
],
vec!
[
&
26692
,
&
19109
,
&
10096
],
vec!
[
&
25831
,
&
23001
,
&
7084
],
vec!
[
&
30030
,
&
25627
,
&
310
],
vec!
[
&
32525
,
&
21273
,
&
2233
],
vec!
[
&
24185
,
&
17303
,
&
14545
],
vec!
[
&
28625
,
&
23788
,
&
3628
],
vec!
[
&
27283
,
&
20717
,
&
8125
]
]
);
// random small numbers, realistic in some applications
...
...
@@ -188,23 +336,25 @@ mod tests {
CGA
::
solve
(
8
,
vec!
[
13
,
151
,
172
,
121
,
185
,
236
,
237
,
241
,
209
,
215
,
78
,
217
,
54
,
112
,
147
,
189
,
209
,
25
,
165
,
231
,
44
,
27
,
65
,
68
,
150
,
127
,
241
,
129
,
235
,
85
,
49
,
248
,
236
,
220
,
112
,
164
,
199
,
92
,
148
,
152
,
50
,
225
,
112
,
103
,
80
,
2
,
36
,
32
,
26
,
200
,
6
,
70
,
227
,
71
,
137
,
120
,
197
,
122
,
248
,
175
,
206
,
40
,
166
,
185
,
3
,
22
,
92
,
201
,
113
,
239
,
96
,
163
,
208
,
207
,
9
,
31
,
208
,
44
,
63
,
234
,
244
,
68
,
47
,
214
,
138
,
183
,
77
,
78
,
48
,
68
,
253
,
254
,
107
,
162
,
182
,
109
,
183
,
18
,
53
,
40
,
&
13
,
&
151
,
&
172
,
&
121
,
&
185
,
&
236
,
&
237
,
&
241
,
&
209
,
&
215
,
&
78
,
&
217
,
&
54
,
&
112
,
&
147
,
&
189
,
&
209
,
&
25
,
&
165
,
&
231
,
&
44
,
&
27
,
&
65
,
&
68
,
&
150
,
&
127
,
&
241
,
&
129
,
&
235
,
&
85
,
&
49
,
&
248
,
&
236
,
&
220
,
&
112
,
&
164
,
&
199
,
&
92
,
&
148
,
&
152
,
&
50
,
&
225
,
&
112
,
&
103
,
&
80
,
&
2
,
&
36
,
&
32
,
&
26
,
&
200
,
&
6
,
&
70
,
&
227
,
&
71
,
&
137
,
&
120
,
&
197
,
&
122
,
&
248
,
&
175
,
&
206
,
&
40
,
&
166
,
&
185
,
&
3
,
&
22
,
&
92
,
&
201
,
&
113
,
&
239
,
&
96
,
&
163
,
&
208
,
&
207
,
&
9
,
&
31
,
&
208
,
&
44
,
&
63
,
&
234
,
&
244
,
&
68
,
&
47
,
&
214
,
&
138
,
&
183
,
&
77
,
&
78
,
&
48
,
&
68
,
&
253
,
&
254
,
&
107
,
&
162
,
&
182
,
&
109
,
&
183
,
&
18
,
&
53
,
&
40
,
]
),
vec!
[
vec!
[
248
,
231
,
209
,
206
,
166
,
163
,
121
,
109
,
78
,
54
,
49
,
27
],
vec!
[
241
,
236
,
217
,
189
,
183
,
151
,
129
,
103
,
85
,
53
,
48
,
26
],
vec!
[
241
,
236
,
215
,
199
,
172
,
162
,
113
,
112
,
78
,
68
,
40
,
25
],
vec!
[
254
,
225
,
214
,
197
,
182
,
148
,
122
,
112
,
71
,
68
,
47
,
13
,
9
],
vec!
[
253
,
227
,
208
,
207
,
165
,
164
,
120
,
112
,
70
,
68
,
44
,
18
,
6
],
vec!
[
248
,
234
,
208
,
200
,
175
,
152
,
137
,
96
,
80
,
65
,
36
,
31
],
vec!
[
244
,
235
,
209
,
201
,
183
,
147
,
127
,
107
,
77
,
63
,
44
,
22
,
3
],
vec!
[
239
,
237
,
220
,
185
,
185
,
150
,
138
,
92
,
92
,
50
,
40
,
32
,
2
]
vec!
[
&
248
,
&
231
,
&
209
,
&
206
,
&
166
,
&
163
,
&
121
,
&
109
,
&
78
,
&
54
,
&
49
,
&
27
],
vec!
[
&
241
,
&
236
,
&
217
,
&
189
,
&
183
,
&
151
,
&
129
,
&
103
,
&
85
,
&
53
,
&
48
,
&
26
],
vec!
[
&
241
,
&
236
,
&
215
,
&
199
,
&
172
,
&
162
,
&
113
,
&
112
,
&
78
,
&
68
,
&
40
,
&
25
],
vec!
[
&
254
,
&
225
,
&
214
,
&
197
,
&
182
,
&
148
,
&
122
,
&
112
,
&
71
,
&
68
,
&
47
,
&
13
,
&
9
],
vec!
[
&
253
,
&
227
,
&
208
,
&
207
,
&
165
,
&
164
,
&
120
,
&
112
,
&
70
,
&
68
,
&
44
,
&
18
,
&
6
],
vec!
[
&
248
,
&
234
,
&
208
,
&
200
,
&
175
,
&
152
,
&
137
,
&
96
,
&
80
,
&
65
,
&
36
,
&
31
],
vec!
[
&
244
,
&
235
,
&
209
,
&
201
,
&
183
,
&
147
,
&
127
,
&
107
,
&
77
,
&
63
,
&
44
,
&
22
,
&
3
],
vec!
[
&
239
,
&
237
,
&
220
,
&
185
,
&
185
,
&
150
,
&
138
,
&
92
,
&
92
,
&
50
,
&
40
,
&
32
,
&
2
]
]
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment