RsBundle  Diff

Differences From Artifact [9a81b4967c]:

  • File src/solver.rs — part of check-in [9a0f6816f5] at 2016-09-30 19:42:04 on branch trunk — FirstOrderProblem returns primal information along minorants. (user: fifr size: 25184)

To Artifact [ee0e357dc6]:

  • File src/solver.rs — part of check-in [7b213efa22] at 2016-10-01 07:49:00 on branch trunk — Aggregate primal information. For this, master problems must return the coefficients and the problem trait needs to implement an `aggregate` method. (user: fifr size: 25959)

272
273
274
275
276
277
278
279
280


281
282
283
284


285
286
287
288
289
290
291



292
293
294
295
296
297
298
272
273
274
275
276
277
278


279
280
281
282
283
284
285
286
287
288
289
290
291


292
293
294
295
296
297
298
299
300
301







-
-
+
+




+
+





-
-
+
+
+







    Descent,
    /// No step but the algorithm has been terminated.
    Term,
}


/// Information about a minorant.
#[derive(Debug, Clone, Copy)]
struct MinorantInfo {
#[derive(Debug, Clone)]
struct MinorantInfo<Pr> {
    /// The minorant's index in the master problem
    index: usize,
    /// Current multiplier.
    multiplier: usize,
    /// Primal associated with this minorant.
    primal: Option<Pr>,
}

/**
 * Implementation of a bundle method.
 */
pub struct Solver<P>
    where P : for <'a> FirstOrderProblem<'a>
pub struct Solver<P, Pr, E>
    where P : for <'a> FirstOrderProblem<'a,Primal=Pr,EvalResult=E>,
          E : Evaluation<Pr>,
{
    /// The first order problem description.
    problem : P,

    /// The solver parameter.
    pub params : SolverParams,

365
366
367
368
369
370
371
372

373
374
375
376
377



378
379
380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
368
369
370
371
372
373
374

375
376
377
378


379
380
381
382
383
384
385
386
387
388
389
390

391
392
393
394
395
396
397
398







-
+



-
-
+
+
+









-
+







     */
    start_time : Instant,

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

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


impl<P> Solver<P>
    where P : for <'a> FirstOrderProblem<'a>
impl<P, Pr, E> Solver<P, Pr, E>
    where P : for <'a> FirstOrderProblem<'a, Primal=Pr,EvalResult=E>,
          E : Evaluation<Pr>
{
    /**
     * Create a new solver for the given problem.
     *
     * Note that the solver owns the problem, so you cannot use the
     * same problem description elsewhere as long as it is assigned to
     * the solver. However, it is possible to get a reference to the
     * internally stored problem using `Solver::problem()`.
     */
    pub fn new_params(problem : P, params : SolverParams) -> Result<Solver<P>> {
    pub fn new_params(problem : P, params : SolverParams) -> Result<Solver<P, Pr, E>> {
        Ok(Solver{
            problem: problem,
            params:  params,
            terminator: Box::new(StandardTerminator { termination_precision: 1e-3 }),
            weighter: Box::new(HKWeighter::new()),
            cur_y : dvec![],
            cur_val : 0.0,
413
414
415
416
417
418
419
420

421
422
423
424
425
426
427
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431







-
+







                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>> {
    pub fn new(problem : P) -> Result<Solver<P,Pr,E>> {
        Solver::new_params(problem, SolverParams::default())
    }

    /**
     * Set the first order problem description associated with this
     * solver.
     *
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
560
561
562
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
560
561
562
563
564
565
566
567
568







-
+
+











-
+





+







            }
        }

        try!(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.minorants = Vec::with_capacity(m);
        for _ in 0..m { self.minorants.push(vec![]); }

        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() {
            if let Some((minorant, primal)) = 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,
                    primal: Some(primal),
                });
            } else {
                return Err(Error::NoMinorant);
            }
        }

        self.cur_valid = true;
606
607
608
609
610
611
612
613





614
615

616

617
618
619
620
621
622
623
612
613
614
615
616
617
618

619
620
621
622
623
624

625
626
627
628
629
630
631
632
633
634







-
+
+
+
+
+

-
+

+







        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);
                let aggr = self.minorants[i].split_off(self.params.max_bundle_size-2);
                let (aggr_mins, aggr_primals) : (Vec<_>, Vec<_>) = aggr.into_iter().map(|m| {
                    (m.index, m.primal.unwrap())
                }).unzip();
                let (aggr_min, aggr_coeffs) = try!(self.master.aggregate(i, &aggr_mins));
                self.minorants[i].push(MinorantInfo{
                    index: try!(self.master.aggregate(i, &remove.iter().map(|m| m.index).collect::<Vec<_>>())),
                    index: aggr_min,
                    multiplier: 0,
                    primal: Some(self.problem.aggregate_primals(&aggr_coeffs, aggr_primals)),
                });
            }
        }
        Ok(())
    }

    /// Perform a descent step.
641
642
643
644
645
646
647
648


649
650
651
652
653
654
655
652
653
654
655
656
657
658

659
660
661
662
663
664
665
666
667







-
+
+







        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>
    {
        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) {
671
672
673
674
675
676
677
678
679







680
681

682
683
684
685
686
687
688
689
690
691
692
693

694
695
696
697
698
699
700
683
684
685
686
687
688
689


690
691
692
693
694
695
696
697

698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718







-
-
+
+
+
+
+
+
+

-
+












+







                Ok(r) => r,
                Err(err) => return Err(Error::Eval(Box::new(err))),
            };

            let fun_ub = result.objective();

            let mut minorants = result.into_iter();
            let mut nxt_minorant = match minorants.next() {
                Some((m, _)) => m,
            let mut nxt_minorant;
            let nxt_primal;
            match minorants.next() {
                Some((m, p)) => {
                    nxt_minorant = m;
                    nxt_primal = p;
                },
                None => return Err(Error::NoMinorant)
            };
            }
            let fun_lb = nxt_minorant.constant;

            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,
                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;
        }