RsBundle  Diff

Differences From Artifact [6402964398]:

  • File src/solver.rs — part of check-in [29f93aefac] at 2016-09-28 15:52:38 on branch trunk — Add `MinorantIndex` as reference to minorants to master problem. (user: fifr size: 23723)

To Artifact [28a03735c5]:

  • File src/solver.rs — part of check-in [e671068275] at 2016-09-28 16:31:19 on branch trunk — solver: Handle minorants correctly. (user: fifr size: 24108)

362
363
364
365
366
367
368



369
370
371
372
373
374
375
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378







+
+
+







     *
     * This is actually the time of the last call to `Solver::init`.
     */
    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>
{
    /**
403
404
405
406
407
408
409
410


411
412
413
414
415
416
417
406
407
408
409
410
411
412

413
414
415
416
417
418
419
420
421







-
+
+







            expected_progress: 0.0,
            cnt_descent: 0,
            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![],
        })
    }

    /// A new solver with default parameter.
    pub fn new(problem : P) -> Result<Solver<P>> {
        Solver::new_params(problem, SolverParams::default())
    }
526
527
528
529
530
531
532


533
534
535
536
537
538
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551

552
553
554
555
556
557
558
559







+
+













-
+







            }
        }

        self.master.set_num_subproblems(m);
        self.master.set_vars(self.problem.num_variables(), lb, ub);
        self.master.set_max_updates(self.params.max_updates);

        self.minorants = vec![vec![]; m];

        self.cur_val = 0.0;
        for i in 0..m {
            let result = match self.problem.evaluate(i, &self.cur_y, INFINITY, 0.0) {
                Ok(r) => r,
                Err(err) => return Err(Error::Eval(Box::new(err))),
            };
            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];
                try!(self.master.add_minorant(i, minorant));
                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);
575
576
577
578
579
580
581
582

583
584
585
586



587
588

589
590
591
592
593
594
595
581
582
583
584
585
586
587

588
589
590
591

592
593
594
595
596
597
598
599
600
601
602
603
604







-
+



-
+
+
+


+







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


    /// Reduce size of bundle.
    fn compress_bundle(&mut self) {
    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 {
                self.master.aggregate(0, &(self.params.max_bundle_size-2..n).collect::<Vec<_>>());
                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) {
        let new_weight = self.weighter.weight(&current_state!(self, Step::Descent), &self.params);
        self.master.set_weight(new_weight);
        self.cnt_descent += 1;
625
626
627
628
629
630
631
632

633
634
635
636
637
638
639
634
635
636
637
638
639
640

641
642
643
644
645
646
647
648







-
+







        }

        let m = self.problem.num_subproblems();
        let descent_bnd = self.get_descent_bound();
        let nullstep_bnd = if m == 1 { self.get_nullstep_bound() } else { INFINITY };
        let relprec = if m == 1 { self.get_relative_precision() } else { 0.0 };

        self.compress_bundle();
        try!(self.compress_bundle());

        let mut nxt_lb = 0.0;
        let mut nxt_ub = 0.0;
        for fidx in 0..self.problem.num_subproblems() {
            let result = match self.problem.evaluate(fidx, &self.nxt_y, nullstep_bnd, relprec) {
                Ok(r) => r,
                Err(err) => return Err(Error::Eval(Box::new(err))),
651
652
653
654
655
656
657
658

659
660
661
662
663
664
665
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;
            try!(self.master.add_minorant(fidx, nxt_minorant));
            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;
        }