@@ -29,18 +29,20 @@ where
2929 let ( min_load, mut max_load) = part_loads. iter ( ) . cloned ( ) . minmax ( ) . into_option ( ) . unwrap ( ) ;
3030 let mut imbalance = max_load. clone ( ) - min_load;
3131
32- let mut i = weights . len ( ) ;
32+ let mut i = 0 ;
3333 let mut i_last = 0 ;
3434 let mut algo_iterations = 0 ;
35- while i != i_last {
36- i = ( i + 1 ) % weights. len ( ) ;
37-
35+ loop {
3836 // loop through the weights.
3937 let p = partition[ i] ;
4038
4139 if part_loads[ p] < max_load {
4240 // weight #i is not in the heaviest partition, and thus the move
4341 // will not reduce the max imbalance.
42+ i = ( i + 1 ) % weights. len ( ) ;
43+ if i == i_last {
44+ break ;
45+ }
4446 continue ;
4547 }
4648
@@ -56,129 +58,23 @@ where
5658 let ( new_min_load, new_max_load) =
5759 part_loads. iter ( ) . cloned ( ) . minmax ( ) . into_option ( ) . unwrap ( ) ;
5860 let new_imbalance = new_max_load. clone ( ) - new_min_load. clone ( ) ;
59- if imbalance < new_imbalance {
61+ if new_imbalance <= imbalance {
62+ // The move decreases the partition imbalance.
63+ imbalance = new_imbalance;
64+ max_load = new_max_load;
65+ partition[ i] = q;
66+ i_last = i;
67+ } else {
6068 // The move does not decrease the partition imbalance.
6169 part_loads[ p] += weights[ i] . clone ( ) ;
6270 part_loads[ q] = part_loads[ p] . clone ( ) - weights[ i] . clone ( ) ;
6371 continue ;
6472 }
65- imbalance = new_imbalance;
66- max_load = new_max_load;
67- partition[ i] = q;
68- i_last = i;
69- }
70-
71- algo_iterations += 1 ;
72- }
73-
74- algo_iterations
75- }
76-
77- #[ allow( dead_code) ]
78- pub fn vn_first < const C : usize , T > (
79- partition : & mut [ usize ] ,
80- criteria : & [ [ T ; C ] ] ,
81- num_parts : usize ,
82- ) -> usize
83- where
84- T : AddAssign + SubAssign + Sub < Output = T > + Sum ,
85- T : Zero + One + FromPrimitive ,
86- T : Copy + Ord ,
87- {
88- if num_parts < 2 || criteria. is_empty ( ) || C == 0 {
89- return 0 ;
90- }
91-
92- assert_eq ! ( criteria. len( ) , partition. len( ) ) ;
93-
94- let mut part_loads_per_criterion = {
95- let mut loads = vec ! [ [ T :: zero( ) ; C ] ; num_parts] ;
96- for ( w, weight) in criteria. iter ( ) . enumerate ( ) {
97- for ( part_load, criterion) in loads[ partition[ w] ] . iter_mut ( ) . zip ( weight) {
98- * part_load += * criterion;
99- }
100- }
101- loads
102- } ;
103- let total_weight_per_criterion = {
104- // TODO replace with .collect() once [_; C] implements FromIterator.
105- let mut ws = [ T :: zero ( ) ; C ] ;
106- for c in 0 ..C {
107- ws[ c] = part_loads_per_criterion[ c] . iter ( ) . cloned ( ) . sum ( ) ;
108- }
109- ws
110- } ;
111- if total_weight_per_criterion. contains ( & T :: zero ( ) ) {
112- return 0 ;
113- }
114-
115- let min_max_loads = |part_loads_per_criterion : & Vec < [ T ; C ] > | -> [ ( T , T ) ; C ] {
116- // TODO replace with .collect() once [_; C] implements FromIterator.
117- let mut imbs = [ ( T :: zero ( ) , T :: zero ( ) ) ; C ] ;
118- for c in 0 ..C {
119- imbs[ c] = part_loads_per_criterion[ c]
120- . iter ( )
121- . cloned ( )
122- . minmax ( )
123- . into_option ( )
124- . unwrap ( ) ;
12573 }
126- imbs
127- } ;
128-
129- let ( global_min_load, mut global_max_load) = * min_max_loads ( & part_loads_per_criterion)
130- . iter ( )
131- . max_by_key ( |( min_load, max_load) | * max_load - * min_load)
132- . unwrap ( ) ;
133- let mut imbalance = global_max_load - global_min_load;
13474
135- let mut i = 0 ;
136- let mut i_last = 0 ;
137- let mut algo_iterations = 0 ;
138- while i != i_last {
139- i = ( i + 1 ) % criteria. len ( ) ;
140-
141- // loop through the weights.
142- let p = partition[ i] ;
143-
144- if part_loads_per_criterion[ p]
145- . iter ( )
146- . all ( |criterion_load| * criterion_load < global_max_load)
147- {
148- // weight #i is not in the heaviest partition, and thus the move
149- // will not reduce the max imbalance.
150- continue ;
151- }
152-
153- for q in 0 ..num_parts {
154- // loop through the parts.
155- if p == q {
156- // weight #i is already in partition #q.
157- continue ;
158- }
159-
160- for c in 0 ..C {
161- part_loads_per_criterion[ p] [ c] -= criteria[ i] [ c] ;
162- part_loads_per_criterion[ q] [ c] += criteria[ i] [ c] ;
163- }
164- let ( new_global_min_load, new_global_max_load) =
165- * min_max_loads ( & part_loads_per_criterion)
166- . iter ( )
167- . max_by_key ( |( min_load, max_load) | * max_load - * min_load)
168- . unwrap ( ) ;
169- let new_imbalance = new_global_max_load - new_global_min_load;
170- if imbalance < new_imbalance {
171- // The move does not decrease the partition imbalance.
172- for c in 0 ..C {
173- part_loads_per_criterion[ p] [ c] += criteria[ i] [ c] ;
174- part_loads_per_criterion[ q] [ c] -= criteria[ i] [ c] ;
175- }
176- continue ;
177- }
178- imbalance = new_imbalance;
179- global_max_load = new_global_max_load;
180- partition[ i] = q;
181- i_last = i;
75+ i = ( i + 1 ) % weights. len ( ) ;
76+ if i == i_last {
77+ break ;
18278 }
18379
18480 algo_iterations += 1 ;
@@ -280,18 +176,26 @@ mod tests {
280176 #[ test]
281177 fn small ( ) {
282178 const W : [ [ i32 ; 2 ] ; 6 ] = [ [ 1 , 2 ] , [ 2 , 4 ] , [ 3 , 6 ] , [ 8 , 4 ] , [ 10 , 5 ] , [ 12 , 6 ] ] ;
283- let mut part = [ 0 ; W . len ( ) ] ;
179+ let w: Vec < _ > = W
180+ . iter ( )
181+ . map ( |w| nalgebra:: SVector :: < i32 , 2 > :: from ( * w) )
182+ . collect ( ) ;
183+ let mut partition = [ 0 ; W . len ( ) ] ;
284184
285- vn_first ( & mut part, & W , 1 ) ;
185+ vn_first_mono ( & mut partition, & w, 2 ) ;
186+ println ! ( "partition: {partition:?}" ) ;
286187 let imbs_ini: Vec < i32 > = ( 0 ..W [ 0 ] . len ( ) )
287- . map ( |c| imbalance:: max_imbalance ( 2 , & part, W . iter ( ) . map ( |w| w[ c] ) ) )
188+ . map ( |c| imbalance:: max_imbalance ( 2 , & partition, W . iter ( ) . map ( |w| w[ c] ) ) )
189+ . collect ( ) ;
190+ vn_first_mono ( & mut partition, & w, 2 ) ;
191+ println ! ( "partition: {partition:?}" ) ;
192+ let imbs_end: Vec < i32 > = ( 0 ..W [ 0 ] . len ( ) )
193+ . map ( |c| imbalance:: max_imbalance ( 2 , & partition, W . iter ( ) . map ( |w| w[ c] ) ) )
288194 . collect ( ) ;
289- vn_first ( & mut part, & W , 2 ) ;
290- let imbs_end =
291- ( 0 ..W [ 0 ] . len ( ) ) . map ( |c| imbalance:: max_imbalance ( 2 , & part, W . iter ( ) . map ( |w| w[ c] ) ) ) ;
195+ println ! ( "imbalances: {imbs_end:?} < {imbs_ini:?}" ) ;
292196 for ( imb_ini, imb_end) in imbs_ini. into_iter ( ) . zip ( imbs_end) {
197+ println ! ( "imbalance: {imb_end} < {imb_ini}" ) ;
293198 assert ! ( imb_end <= imb_ini) ;
294- println ! ( "imbalance : {} < {}" , imb_end, imb_ini) ;
295199 }
296200 }
297201
@@ -303,7 +207,7 @@ mod tests {
303207 ( weights, mut partition) in
304208 ( 2 ..200_usize ) . prop_flat_map( |num_weights| {
305209 let weights = prop:: collection:: vec(
306- ( 1 ..1000_i32 , 1 ..1000_i32 ) . prop_map( |( a, b) | [ a, b] ) ,
210+ ( 1 ..1000_i32 , 1 ..1000_i32 ) . prop_map( |( a, b) | nalgebra :: SVector :: < i32 , 2 > :: new ( a, b) ) ,
307211 num_weights
308212 ) ;
309213 let partition = prop:: collection:: vec( 0 ..1_usize , num_weights) ;
@@ -313,7 +217,7 @@ mod tests {
313217 let imbs_ini: Vec <i32 > = ( 0 ..C )
314218 . map( |c| imbalance:: max_imbalance( 2 , & partition, weights. iter( ) . map( |w| w[ c] ) ) )
315219 . collect( ) ;
316- vn_first ( & mut partition, & weights, 2 ) ;
220+ vn_first_mono ( & mut partition, & weights, 2 ) ;
317221 let imbs_end: Vec <i32 > = ( 0 ..C )
318222 . map( |c| imbalance:: max_imbalance( 2 , & partition, weights. iter( ) . map( |w| w[ c] ) ) )
319223 . collect( ) ;
0 commit comments