RsBundle  Diff

Differences From Artifact [f2405d0d0b]:

  • File src/solver.rs — part of check-in [6186a4f7ed] at 2019-07-17 14:41:42 on branch async — solver: make master problem a type argument (user: fifr size: 36835)

To Artifact [57470ce51a]:

  • File src/solver.rs — part of check-in [b6b5c1ec21] at 2019-07-17 15:38:30 on branch async — Simplify error handling (again) by using boxed errors (user: fifr size: 36759)

37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
37
38
39
40
41
42
43

44
45
46
47
48
49
50
51







-
+







#[derive(Debug)]
pub enum SolverError<E> {
    /// An error occurred during oracle evaluation.
    Evaluation(E),
    /// An error occurred during oracle update.
    Update(E),
    /// An error has been raised by the master problem.
    Master(MasterProblemError<E>),
    Master(MasterProblemError),
    /// The oracle did not return a minorant.
    NoMinorant,
    /// The dimension of some data is wrong.
    Dimension,
    /// Some parameter has an invalid value.
    Parameter(ParameterError),
    /// The lower bound of a variable is larger than the upper bound.
78
79
80
81
82
83
84
85

86
87
88
89

90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106


107
108
109
110
111
112
113
78
79
80
81
82
83
84

85




86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101


102
103
104
105
106
107
108
109
110







-
+
-
-
-
-
+















-
-
+
+







                write!(fmt, "Variable index out of bounds, got:{} must be < {}", index, nvars)
            }
            IterationLimit { limit } => write!(fmt, "The iteration limit of {} has been reached.", limit),
        }
    }
}

impl<E: Error> Error for SolverError<E>
impl<E: Error + 'static> Error for SolverError<E> {
where
    E: 'static,
{
    fn cause(&self) -> Option<&Error> {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            SolverError::Evaluation(err) => Some(err),
            SolverError::Update(err) => Some(err),
            SolverError::Master(err) => Some(err),
            _ => None,
        }
    }
}

impl<E> From<ParameterError> for SolverError<E> {
    fn from(err: ParameterError) -> SolverError<E> {
        SolverError::Parameter(err)
    }
}

impl<E> From<MasterProblemError<E>> for SolverError<E> {
    fn from(err: MasterProblemError<E>) -> SolverError<E> {
impl<E> From<MasterProblemError> for SolverError<E> {
    fn from(err: MasterProblemError) -> SolverError<E> {
        SolverError::Master(err)
    }
}

/**
 * The current state of the bundle method.
 *
382
383
384
385
386
387
388
389

390
391
392

393
394
395
396
397

398
399
400
401
402
403
404
379
380
381
382
383
384
385

386
387
388

389
390
391
392
393

394
395
396
397
398
399
400
401







-
+


-
+




-
+







    /// This is the last primal generated by the oracle.
    pub fn last_primal(&self, fidx: usize) -> Option<&Pr> {
        self.minorants[fidx].last().and_then(|m| m.primal.as_ref())
    }
}

/// The default bundle solver with general master problem.
pub type DefaultSolver<P> = Solver<P, BoxedMasterProblem<CplexMaster<<P as FirstOrderProblem>::Err>>>;
pub type DefaultSolver<P> = Solver<P, BoxedMasterProblem<CplexMaster>>;

/// A bundle solver with a minimal cutting plane model.
pub type NoBundleSolver<P> = Solver<P, BoxedMasterProblem<MinimalMaster<<P as FirstOrderProblem>::Err>>>;
pub type NoBundleSolver<P> = Solver<P, BoxedMasterProblem<MinimalMaster>>;

/**
 * Implementation of a bundle method.
 */
pub struct Solver<P, M = BoxedMasterProblem<CplexMaster<<P as FirstOrderProblem>::Err>>>
pub struct Solver<P, M = BoxedMasterProblem<CplexMaster>>
where
    P: FirstOrderProblem,
{
    /// The first order problem description.
    problem: P,

    /// The solver parameter.
485
486
487
488
489
490
491
492
493


494
495
496
497
498
499
500
482
483
484
485
486
487
488


489
490
491
492
493
494
495
496
497







-
-
+
+







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

impl<P, M> Solver<P, M>
where
    P: FirstOrderProblem,
    P::Err: Into<Box<dyn Error + Send + Sync>> + 'static,
    M: MasterProblem<MinorantIndex = usize, SubgradientExtensionErr = P::Err>,
    P::Err: Into<Box<std::error::Error + Send + Sync + 'static>>,
    M: MasterProblem<MinorantIndex = usize>,
{
    /**
     * 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
719
720
721
722
723
724
725

726
727
728
729
730
731
732
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730







+







            let minorants = &self.minorants;
            self.master.add_vars(
                &newvars.iter().map(|v| (v.0, v.1, v.2)).collect::<Vec<_>>(),
                &mut |fidx, minidx, vars| {
                    problem
                        .extend_subgradient(minorants[fidx][minidx].primal.as_ref().unwrap(), vars)
                        .map(DVector)
                        .map_err(|e| e.into())
                },
            )?;
            // modify moved variables
            for (index, val) in newvars.iter().filter_map(|v| v.0.map(|i| (i, v.3))) {
                self.cur_y[index] = val;
                self.nxt_y[index] = val;
                self.nxt_d[index] = 0.0;