RsBundle  Diff

Differences From Artifact [0e8d373bd7]:

  • File src/solver.rs — part of check-in [d08662bfb8] at 2016-10-06 09:28:32 on branch trunk — solver: Call `update_problem` only once per iteration. (user: fifr size: 29072)

To Artifact [dbdd4928cb]:

  • File src/solver.rs — part of check-in [8d6b894491] at 2016-10-10 14:43:45 on branch trunk — Add `IterationInfo` to update state. (user: fifr size: 29785)

288
289
290
291
292
293
294









295
296
297
298
299
300
301


302
303
304
305
306
307
308
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319







+
+
+
+
+
+
+
+
+







+
+







    /// The minorant's index in the master problem
    index: usize,
    /// Current multiplier.
    multiplier: Real,
    /// Primal associated with this minorant.
    primal: Option<Pr>,
}

/// Information about the last iteration.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum IterationInfo {
    NewMinorantTooHigh{ new: Real, old: Real },
    UpperBoundNullStep,
    ShallowCut,
}


/// State information for the update callback.
pub struct UpdateState<'a, Pr:'a> {
    /// Current model minorants.
    minorants: &'a [Vec<MinorantInfo<Pr>>],
    /// The last step type.
    pub step: Step,
    /// Iteration information.
    pub iteration_info: &'a [IterationInfo],
}

impl<'a, Pr:'a> UpdateState<'a, Pr> {
    pub fn aggregated_primals(&self, subproblem : usize) -> Vec<(Real, &Pr)> {
        self.minorants[subproblem].iter().map(|m| {
            (m.multiplier, m.primal.as_ref().unwrap())
        }).collect()
392
393
394
395
396
397
398



399
400
401
402
403
404
405
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419







+
+
+







    start_time : Instant,

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

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

    /// Accumulated information about the last iteration.
    iterinfos: Vec<IterationInfo>,
}


impl<P, Pr, E> Solver<P, Pr, E>
    where P : for <'a> FirstOrderProblem<'a, Primal=Pr,EvalResult=E>,
          E : Evaluation<Pr>
{
436
437
438
439
440
441
442

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464







+







            cnt_null: 0,
            start_time: Instant::now(),
            master: match BoxedMasterProblem::<MinimalMaster>::new() {
                Ok(master) => Box::new(master),
                Err(err) => return Err(Error::Master(Box::new(err))),
            },
            minorants: vec![],
            iterinfos: vec![],
        })
    }

    /// A new solver with default parameter.
    pub fn new(problem : P) -> Result<Solver<P,Pr,E>> {
        Solver::new_params(problem, SolverParams::default())
    }
516
517
518
519
520
521
522
523

524
525
526
527
528
529
530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
545







-
+







    }

    /// Called to update the problem.
    ///
    /// Calling this function typically triggers the problem to
    /// separate new constraints depending on the current solution.
    fn update_problem(&mut self, term: Step) -> Result<bool> {
        let state = UpdateState {minorants: &self.minorants, step: term};
        let state = UpdateState {minorants: &self.minorants, step: term, iteration_info: &self.iterinfos};
        let updates = match self.problem.update(&state) {
            Ok(updates) => updates,
            Err(err) => return Err(Error::Update(Box::new(err))),
        };

        let mut newvars = Vec::with_capacity(updates.len());
        for u in updates {
734
735
736
737
738
739
740
741
742



743
744
745
746
747
748
749
749
750
751
752
753
754
755


756
757
758
759
760
761
762
763
764
765







-
-
+
+
+







        let new_weight = self.weighter.weight(&current_state!(self, Step::Null), &self.params);
        self.master.set_weight(new_weight);
        self.cnt_null += 1;
        debug!("Null Step");
    }

    /// Perform one bundle iteration.
    pub fn step(&mut self) -> Result<Step>
    {
    pub fn step(&mut self) -> Result<Step> {
        self.iterinfos.clear();

        if !self.cur_valid {
            // current point needs new evaluation
            try!(self.init_master());
        }

        try!(self.solve_model());
        if self.terminator.terminate(&current_state!(self, Step::Term), &self.params) {
793
794
795
796
797
798
799

800
801
802
803
804
805
806
807
808
809
810


811
812
813
814
815
816
817

818
819
820
821
822
823
824
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826

827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843







+










-
+
+







+







                primal: Some(nxt_primal),
            });
        }

        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;
            self.iterinfos.push(IterationInfo::NewMinorantTooHigh{new: self.new_cutval, old: self.cur_val});
        }

        self.nxt_val = nxt_ub;

        // check for potential problems with relative precision of all kinds
        if nxt_lb <= descent_bnd {
            // lower bound gives descent step
            if nxt_ub > descent_bnd {
                // upper bound will produce null-step
                if self.cur_val - nxt_lb > (self.cur_val - self.nxt_mod) * self.params.nullstep_factor.max(0.5) {
                    warn!("Relative precision of returned objective interval enforces null-step.")
                    warn!("Relative precision of returned objective interval enforces null-step.");
                    self.iterinfos.push(IterationInfo::UpperBoundNullStep);
                }
            }
        } else {
            // lower bound gives already a null step
            if self.cur_val - nxt_lb > 0.8 * (self.cur_val - self.nxt_mod) {
                // subgradient won't yield much improvement
                warn!("Shallow cut (subgradient won't yield much improvement)");
                self.iterinfos.push(IterationInfo::ShallowCut);
            }
        }

        debug!("Step");
        debug!("  cur_val    ={}", self.cur_val);
        debug!("  nxt_mod    ={}", self.nxt_mod);
        debug!("  nxt_ub     ={}", self.nxt_val);