RsBundle  Check-in [a86c952bc8]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:solver: Compress minorants with smallest multipliers.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: a86c952bc8b71b5f634b91dfc4a1d8844ecd5a10
User & Date: fifr 2016-09-28 21:05:48.319
Context
2016-09-28
21:15
solver: Fix fractions in time output. check-in: 77d15f47e4 user: fifr tags: trunk
21:05
solver: Compress minorants with smallest multipliers. check-in: a86c952bc8 user: fifr tags: trunk
21:04
master: Add `multiplier` method. check-in: 3863fc49a4 user: fifr tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/solver.rs.
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197

/// Parameters for tuning the solver.
#[derive(Clone, Debug)]
pub struct SolverParams {
    /// Maximal individual bundle size.
    pub max_bundle_size : usize,

    /**
     * Maximal age of a minorant before it gets compressed.
     *
     * Minorants that have not been active for that many iterations will be compressed,
     * independent of the size of the bundle.
     */
    pub max_age: usize,

    /**
     * Factor for doing a descent step.
     *
     * If the proportion of actual decrease to predicted decrease is
     * at least that high, a descent step will be done.
     *
     * Must be in (0,1).







<
<
<
<
<
<
<
<







176
177
178
179
180
181
182








183
184
185
186
187
188
189

/// Parameters for tuning the solver.
#[derive(Clone, Debug)]
pub struct SolverParams {
    /// Maximal individual bundle size.
    pub max_bundle_size : usize,









    /**
     * Factor for doing a descent step.
     *
     * If the proportion of actual decrease to predicted decrease is
     * at least that high, a descent step will be done.
     *
     * Must be in (0,1).
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
    }
}

impl Default for SolverParams {
    fn default() -> SolverParams {
        SolverParams {
            max_bundle_size: 50,
            max_age: 10,

            nullstep_factor: 0.1,
            acceptance_factor: 0.1,

            min_weight: 0.01,
            max_weight: 1000.0,








<







246
247
248
249
250
251
252

253
254
255
256
257
258
259
    }
}

impl Default for SolverParams {
    fn default() -> SolverParams {
        SolverParams {
            max_bundle_size: 50,


            nullstep_factor: 0.1,
            acceptance_factor: 0.1,

            min_weight: 0.01,
            max_weight: 1000.0,

279
280
281
282
283
284
285










286
287
288
289
290
291
292
    Null,
    /// A descent step has been performed.
    Descent,
    /// No step but the algorithm has been terminated.
    Term,
}











/**
 * Implementation of a bundle method.
 */
pub struct Solver<P>
    where P : for <'a> FirstOrderProblem<'a>
{
    /// The first order problem description.







>
>
>
>
>
>
>
>
>
>







270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
    Null,
    /// A descent step has been performed.
    Descent,
    /// No step but the algorithm has been terminated.
    Term,
}


/// Information about a minorant.
#[derive(Debug, Clone, Copy)]
struct MinorantInfo {
    /// The minorant's index in the master problem
    index: usize,
    /// Current multiplier.
    multiplier: usize,
}

/**
 * Implementation of a bundle method.
 */
pub struct Solver<P>
    where P : for <'a> FirstOrderProblem<'a>
{
    /// The first order problem description.
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
     */
    start_time : Instant,

    /// The master problem.
    master: Box<MasterProblem<MinorantIndex=usize>>,

    /// The active minorant indices for each subproblem.
    minorants: Vec<Vec<usize>>,
}


impl<P> Solver<P>
    where P : for <'a> FirstOrderProblem<'a>
{
    /**







|







365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
     */
    start_time : Instant,

    /// The master problem.
    master: Box<MasterProblem<MinorantIndex=usize>>,

    /// The active minorant indices for each subproblem.
    minorants: Vec<Vec<MinorantInfo>>,
}


impl<P> Solver<P>
    where P : for <'a> FirstOrderProblem<'a>
{
    /**
545
546
547
548
549
550
551

552


553
554
555
556
557
558
559
            self.cur_vals[i] = result.objective();
            self.cur_val += self.cur_vals[i];

            let mut minorants = result.into_iter();
            if let Some(minorant) = minorants.next() {
                self.cur_mods[i] = minorant.constant;
                self.cur_mod += self.cur_mods[i];

                self.minorants[i].push(try!(self.master.add_minorant(i, minorant)));


            } else {
                return Err(Error::NoMinorant);
            }
        }

        self.cur_valid = true;
        self.master.set_weight(1.0);







>
|
>
>







546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
            self.cur_vals[i] = result.objective();
            self.cur_val += self.cur_vals[i];

            let mut minorants = result.into_iter();
            if let Some(minorant) = minorants.next() {
                self.cur_mods[i] = minorant.constant;
                self.cur_mod += self.cur_mods[i];
                self.minorants[i].push(MinorantInfo {
                    index: try!(self.master.add_minorant(i, minorant)),
                    multiplier: 0,
                });
            } else {
                return Err(Error::NoMinorant);
            }
        }

        self.cur_valid = true;
        self.master.set_weight(1.0);
572
573
574
575
576
577
578

579
580
581
582
583
584
585
586
587
588
589
590
591




592
593
594


595
596
597
598
599
600
601
    fn solve_model(&mut self) -> Result<()> {
        try!(self.master.solve(self.cur_val));
        self.nxt_d = self.master.get_primopt();
        self.nxt_y.add(&self.cur_y, &self.nxt_d);
        self.nxt_mod = self.master.get_primoptval();
        self.sgnorm = self.master.get_dualoptnorm2().sqrt();
        self.expected_progress = self.cur_val - self.nxt_mod;

        debug!("Model result");
        debug!("  cur_val ={}", self.cur_val);
        debug!("  nxt_mod ={}", self.nxt_mod);
        debug!("  expected={}", self.expected_progress);
        Ok(())
    }


    /// Reduce size of bundle.
    fn compress_bundle(&mut self) -> Result<()> {
        for i in 0..self.problem.num_subproblems() {
            let n = self.master.num_minorants(i);
            if n >= self.params.max_bundle_size {




                let mut remove = self.minorants[i].split_off(self.params.max_bundle_size-2);
                swap(&mut remove, &mut self.minorants[i]);
                self.minorants[i].push(try!(self.master.aggregate(i, &remove)));


            }
        }
        Ok(())
    }

    /// Perform a descent step.
    fn descent_step(&mut self) {







>













>
>
>
>
|
|
|
>
>







576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
    fn solve_model(&mut self) -> Result<()> {
        try!(self.master.solve(self.cur_val));
        self.nxt_d = self.master.get_primopt();
        self.nxt_y.add(&self.cur_y, &self.nxt_d);
        self.nxt_mod = self.master.get_primoptval();
        self.sgnorm = self.master.get_dualoptnorm2().sqrt();
        self.expected_progress = self.cur_val - self.nxt_mod;

        debug!("Model result");
        debug!("  cur_val ={}", self.cur_val);
        debug!("  nxt_mod ={}", self.nxt_mod);
        debug!("  expected={}", self.expected_progress);
        Ok(())
    }


    /// Reduce size of bundle.
    fn compress_bundle(&mut self) -> Result<()> {
        for i in 0..self.problem.num_subproblems() {
            let n = self.master.num_minorants(i);
            if n >= self.params.max_bundle_size {
                for m in self.minorants[i].iter_mut() {
                    m.multiplier = (1e6 * self.master.multiplier(m.index)) as usize;
                }
                self.minorants[i].sort_by_key(|m| -(m.multiplier as isize));
                let remove = self.minorants[i].split_off(self.params.max_bundle_size-2);
                self.minorants[i].push(MinorantInfo{
                    index: try!(self.master.aggregate(i, &remove.iter().map(|m| m.index).collect::<Vec<_>>())),
                    multiplier: 0,
                });
            }
        }
        Ok(())
    }

    /// Perform a descent step.
    fn descent_step(&mut self) {
660
661
662
663
664
665
666

667


668
669
670
671
672
673
674
            nxt_lb += fun_lb;
            nxt_ub += fun_ub;
            self.nxt_vals[fidx] = fun_ub;

            // move center of minorant to cur_y
            nxt_minorant.move_center(-1.0, &self.nxt_d);
            self.new_cutval += nxt_minorant.constant;

            self.minorants[fidx].push(try!(self.master.add_minorant(fidx, nxt_minorant)));


        }

        if self.new_cutval > self.cur_val + 1e-3 {
            warn!("New minorant has higher value in center new:{} old:{}", self.new_cutval, self.cur_val);
            self.cur_val = self.new_cutval;
        }








>
|
>
>







671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
            nxt_lb += fun_lb;
            nxt_ub += fun_ub;
            self.nxt_vals[fidx] = fun_ub;

            // move center of minorant to cur_y
            nxt_minorant.move_center(-1.0, &self.nxt_d);
            self.new_cutval += nxt_minorant.constant;
            self.minorants[fidx].push(MinorantInfo{
                index: try!(self.master.add_minorant(fidx, nxt_minorant)),
                multiplier: 0,
            });
        }

        if self.new_cutval > self.cur_val + 1e-3 {
            warn!("New minorant has higher value in center new:{} old:{}", self.new_cutval, self.cur_val);
            self.cur_val = self.new_cutval;
        }