RsBundle  Diff

Differences From Artifact [f39de7c967]:

  • File src/solver.rs — part of check-in [106f4bb24e] at 2016-10-05 12:58:49 on branch trunk — solver: Update multipliers from master in `solve_model`. This is required so that `aggregated_primals` returns the correct multipliers even if no futher iteration is executed. In particular, if only one iteration is executed. (user: fifr size: 26779)

To Artifact [41149cfa3a]:

  • File src/solver.rs — part of check-in [814bd7230a] at 2016-10-05 16:54:25 on branch trunk — Add problem update callback. (user: fifr size: 28626)

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40







41
42
43
44
45
46
47
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see  <http://www.gnu.org/licenses/>
 */

//! The main bundle method solver.

use {Real, DVector};
use {FirstOrderProblem, Evaluation, HKWeighter};

use master::{self, MasterProblem, BoxedMasterProblem, MinimalMaster, CplexMaster};

use std::result;
use std::error;
use std::mem::swap;
use std::f64::{INFINITY, NEG_INFINITY};
use std::time::Instant;

quick_error! {
    /// A solver error.
    #[derive(Debug)]
    pub enum Error {
        /// An error occurred during evaluation of the oracle.
        Eval(err: Box<error::Error>) {
            cause(&**err)
            description(err.description())
            display("Evaluation error: {}", err)
        }








        /// Error solving the master problem.
        Master(err: Box<error::Error>) {
            cause(&**err)
            description(err.description())
            display("Master problem error: {}", err)
            from(err: master::Error) -> (Box::new(err))







|



















>
>
>
>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see  <http://www.gnu.org/licenses/>
 */

//! The main bundle method solver.

use {Real, DVector};
use {FirstOrderProblem, Update, Evaluation, HKWeighter};

use master::{self, MasterProblem, BoxedMasterProblem, MinimalMaster, CplexMaster};

use std::result;
use std::error;
use std::mem::swap;
use std::f64::{INFINITY, NEG_INFINITY};
use std::time::Instant;

quick_error! {
    /// A solver error.
    #[derive(Debug)]
    pub enum Error {
        /// An error occurred during evaluation of the oracle.
        Eval(err: Box<error::Error>) {
            cause(&**err)
            description(err.description())
            display("Evaluation error: {}", err)
        }

        /// An error occurred during update of the oracle.
        Update(err: Box<error::Error>) {
            cause(&**err)
            description(err.description())
            display("Update error: {}", err)
        }

        /// Error solving the master problem.
        Master(err: Box<error::Error>) {
            cause(&**err)
            description(err.description())
            display("Master problem error: {}", err)
            from(err: master::Error) -> (Box::new(err))
281
282
283
284
285
286
287
















288
289
290
291
292
293
294
    /// The minorant's index in the master problem
    index: usize,
    /// Current multiplier.
    multiplier: Real,
    /// Primal associated with this minorant.
    primal: Option<Pr>,
}

















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







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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

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

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()
    }
}

/**
 * Implementation of a bundle method.
 */
pub struct Solver<P, Pr, E>
    where P : for <'a> FirstOrderProblem<'a,Primal=Pr,EvalResult=E>,
          E : Evaluation<Pr>,
477
478
479
480
481
482
483

484
485
486
487
488































489
490
491
492
493
494
495
    }

    /// Solve the problem.
    pub fn solve(&mut self) -> Result<()> {
        try!(self.init());
        for _ in 0..100000 {
            let term = try!(self.step());

            self.show_info(term);
            if term == Step::Term {
                break;
            }
        }































        Ok(())
    }

    /// Return the current aggregated primal information for a subproblem.
    ///
    /// This function returns all currently used minorants $x_i$ along
    /// with their coefficients $\alpha_i$. The aggregated primal can







>





>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
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
546
547
548
549
550
    }

    /// Solve the problem.
    pub fn solve(&mut self) -> Result<()> {
        try!(self.init());
        for _ in 0..100000 {
            let term = try!(self.step());
            try!(self.update_problem(term));
            self.show_info(term);
            if term == Step::Term {
                break;
            }
        }
        Ok(())
    }

    /// 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<()> {
        let state = UpdateState {minorants: &self.minorants, step: term};
        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 {
            match u {
                Update::AddVariable{lower, upper} => {
                    newvars.push((lower, upper));
                },
            }
        }

        if !newvars.is_empty() {
            let mut problem = &mut self.problem;
            let minorants = &self.minorants;
            self.master.add_vars(&newvars, &mut move |fidx, minidx, vars| {
                problem.extend_subgradient(minorants[fidx][minidx].primal.as_ref().unwrap(), vars).unwrap()
            });
        }

        Ok(())
    }

    /// Return the current aggregated primal information for a subproblem.
    ///
    /// This function returns all currently used minorants $x_i$ along
    /// with their coefficients $\alpha_i$. The aggregated primal can