RsBundle  Check-in [2c9472f892]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Move additional requirements to basic traits. This includes bounds on `Send` and `'static` so that master problems and function oracles can always be used in threads. The requirements have always been there as additional bounds for the solvers, but it is easier (and more descriptive) to state them in the basic traits.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | async
Files: files | file ages | folders
SHA1: 2c9472f892c2c7183e2854812dddcad6cc1b7234
User & Date: fifr 2019-07-22 11:50:12.258
Context
2019-07-22
11:52
Add explicit `dyn` where appropriate check-in: 2cb2bf4cbc user: fifr tags: async
11:50
Move additional requirements to basic traits. check-in: 2c9472f892 user: fifr tags: async
09:48
parallel: require `Primal` to be sendable check-in: b6db39804c user: fifr tags: async
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/master/base.rs.
19
20
21
22
23
24
25






26
27
28
29
30
31
32
33
34
35
36
37
38
use std::error::Error;
use std::result;

/// Callback for subgradient extensions.
pub type SubgradientExtension<'a, I> =
    FnMut(usize, I, &[usize]) -> result::Result<DVector, Box<dyn Error + Send + Sync + 'static>> + 'a;







pub trait MasterProblem {
    /// Unique index for a minorant.
    type MinorantIndex: Copy + Eq;

    /// The error returned by the master problem.
    type Err;

    /// Create a new master problem.
    fn new() -> Result<Self, Self::Err>
    where
        Self: Sized;

    /// Set the number of subproblems.







>
>
>
>
>
>
|




|







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
use std::error::Error;
use std::result;

/// Callback for subgradient extensions.
pub type SubgradientExtension<'a, I> =
    FnMut(usize, I, &[usize]) -> result::Result<DVector, Box<dyn Error + Send + Sync + 'static>> + 'a;

/// Trait for master problems of a proximal bundle methods.
///
/// Note that solvers are allowed to create multiple master problems potentially
/// running them in different threads. Because of this they must implement `Send
/// + 'static`, i.e. they must be quite self-contained and independent from
/// everything else.
pub trait MasterProblem: Send + 'static {
    /// Unique index for a minorant.
    type MinorantIndex: Copy + Eq;

    /// The error returned by the master problem.
    type Err: Error + Send + Sync;

    /// Create a new master problem.
    fn new() -> Result<Self, Self::Err>
    where
        Self: Sized;

    /// Set the number of subproblems.
115
116
117
118
119
120
121
122
123
124
125
126
127
}

/// A builder for creating a master problem solvers.
pub trait Builder {
    /// The master problem to be build.
    type MasterProblem: MasterProblem;

    /// Type of errors.
    type Err;

    /// Create a new master problem.
    fn build(&mut self) -> Result<Self::MasterProblem, Self::Err>;
}







<
<
<

|

121
122
123
124
125
126
127



128
129
130
}

/// A builder for creating a master problem solvers.
pub trait Builder {
    /// The master problem to be build.
    type MasterProblem: MasterProblem;




    /// Create a new master problem.
    fn build(&mut self) -> Result<Self::MasterProblem, <Self::MasterProblem as MasterProblem>::Err>;
}
Changes to src/master/boxed.rs.
370
371
372
373
374
375
376
377
378
379
380
381
382
impl<B> master::Builder for Builder<B>
where
    B: master::unconstrained::Builder,
    B::MasterProblem: UnconstrainedMasterProblem,
{
    type MasterProblem = BoxedMasterProblem<B::MasterProblem>;

    type Err = B::Err;

    fn build(&mut self) -> Result<Self::MasterProblem, Self::Err> {
        self.0.build().map(BoxedMasterProblem::with_master)
    }
}







<
<
|



370
371
372
373
374
375
376


377
378
379
380
impl<B> master::Builder for Builder<B>
where
    B: master::unconstrained::Builder,
    B::MasterProblem: UnconstrainedMasterProblem,
{
    type MasterProblem = BoxedMasterProblem<B::MasterProblem>;



    fn build(&mut self) -> Result<Self::MasterProblem, <Self::MasterProblem as MasterProblem>::Err> {
        self.0.build().map(BoxedMasterProblem::with_master)
    }
}
Changes to src/master/cpx.rs.
548
549
550
551
552
553
554
555
556
557
558
559
560

#[derive(Default)]
pub struct Builder;

impl unconstrained::Builder for Builder {
    type MasterProblem = CplexMaster;

    type Err = CplexMasterError;

    fn build(&mut self) -> Result<CplexMaster> {
        CplexMaster::new()
    }
}







<
<




548
549
550
551
552
553
554


555
556
557
558

#[derive(Default)]
pub struct Builder;

impl unconstrained::Builder for Builder {
    type MasterProblem = CplexMaster;



    fn build(&mut self) -> Result<CplexMaster> {
        CplexMaster::new()
    }
}
Changes to src/master/minimal.rs.
245
246
247
248
249
250
251
252
253
254
255
256
257
}

pub struct Builder;

impl unconstrained::Builder for Builder {
    type MasterProblem = MinimalMaster;

    type Err = MinimalMasterError;

    fn build(&mut self) -> Result<MinimalMaster, Self::Err> {
        MinimalMaster::new()
    }
}







<
<
|



245
246
247
248
249
250
251


252
253
254
255
}

pub struct Builder;

impl unconstrained::Builder for Builder {
    type MasterProblem = MinimalMaster;



    fn build(&mut self) -> Result<MinimalMaster, MinimalMasterError> {
        MinimalMaster::new()
    }
}
Changes to src/master/unconstrained.rs.
14
15
16
17
18
19
20


21
22
23
24
25
26
27
// along with this program.  If not, see  <http://www.gnu.org/licenses/>
//

use crate::{DVector, Minorant, Real};

use super::SubgradientExtension;



/**
 * Trait for master problems without box constraints.
 *
 * Implementors of this trait are supposed to solve quadratic
 * optimization problems of the form
 *
 * \\[ \min \left\\{ \hat{f}(d) + \frac{u}{2} \\| d \\|\^2 \colon







>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// along with this program.  If not, see  <http://www.gnu.org/licenses/>
//

use crate::{DVector, Minorant, Real};

use super::SubgradientExtension;

use std::error::Error;

/**
 * Trait for master problems without box constraints.
 *
 * Implementors of this trait are supposed to solve quadratic
 * optimization problems of the form
 *
 * \\[ \min \left\\{ \hat{f}(d) + \frac{u}{2} \\| d \\|\^2 \colon
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
 * \alpha_i = 1 \right\\}$. Note, the unconstrained solver is expected
 * to compute *dual* optimal solutions, i.e. the solver must compute
 * optimal coefficients $\bar{\alpha}$ for the dual problem
 *
 * \\[ \max_{\alpha \in \Delta} \min_{d \in \mathbb{R}\^n}
 *     \sum_{i=1}\^k \alpha_i \ell_i(d) + \frac{u}{2} \\| d \\|\^2. \\]
 */
pub trait UnconstrainedMasterProblem {
    /// Unique index for a minorant.
    type MinorantIndex: Copy + Eq;

    /// Error type for this master problem.
    type Err;

    /// Return a new instance of the unconstrained master problem.
    fn new() -> Result<Self, Self::Err>
    where
        Self: Sized;

    /// Return the number of subproblems.







|




|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
 * \alpha_i = 1 \right\\}$. Note, the unconstrained solver is expected
 * to compute *dual* optimal solutions, i.e. the solver must compute
 * optimal coefficients $\bar{\alpha}$ for the dual problem
 *
 * \\[ \max_{\alpha \in \Delta} \min_{d \in \mathbb{R}\^n}
 *     \sum_{i=1}\^k \alpha_i \ell_i(d) + \frac{u}{2} \\| d \\|\^2. \\]
 */
pub trait UnconstrainedMasterProblem: Send + 'static {
    /// Unique index for a minorant.
    type MinorantIndex: Copy + Eq;

    /// Error type for this master problem.
    type Err: Error + Send + Sync;

    /// Return a new instance of the unconstrained master problem.
    fn new() -> Result<Self, Self::Err>
    where
        Self: Sized;

    /// Return the number of subproblems.
116
117
118
119
120
121
122
123
124
125
126
127
128
}

/// A builder for creating unconstrained master problem solvers.
pub trait Builder {
    /// The master problem to be build.
    type MasterProblem: UnconstrainedMasterProblem;

    /// Type of errors.
    type Err;

    /// Create a new master problem.
    fn build(&mut self) -> Result<Self::MasterProblem, Self::Err>;
}







<
<
<

|

118
119
120
121
122
123
124



125
126
127
}

/// A builder for creating unconstrained master problem solvers.
pub trait Builder {
    /// The master problem to be build.
    type MasterProblem: UnconstrainedMasterProblem;




    /// Create a new master problem.
    fn build(&mut self) -> Result<Self::MasterProblem, <Self::MasterProblem as UnconstrainedMasterProblem>::Err>;
}
Changes to src/parallel/problem.rs.
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/// Trait for implementing a first-order problem description.
///
/// All computations made by an implementation are supposed to
/// be asynchronous. Hence, the interface is slightly different
/// compared with [`crate::FirstOrderProblem`].
pub trait FirstOrderProblem {
    /// Error raised by this oracle.
    type Err: Send + 'static;

    /// The primal information associated with a minorant.
    type Primal: Aggregatable + Send + 'static;

    /// Return the number of variables.
    fn num_variables(&self) -> usize;








|







42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
/// Trait for implementing a first-order problem description.
///
/// All computations made by an implementation are supposed to
/// be asynchronous. Hence, the interface is slightly different
/// compared with [`crate::FirstOrderProblem`].
pub trait FirstOrderProblem {
    /// Error raised by this oracle.
    type Err;

    /// The primal information associated with a minorant.
    type Primal: Aggregatable + Send + 'static;

    /// Return the number of variables.
    fn num_variables(&self) -> usize;

Changes to src/parallel/solver.rs.
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
    /// This is actually the time of the last call to `Solver::init`.
    start_time: Instant,
}

impl<P, T, W, M> Solver<P, T, W, M>
where
    P: FirstOrderProblem,
    P::Err: std::error::Error,
    T: Terminator<SolverData> + Default,
    W: Weighter<SolverData> + Default,
    M: master::Builder + Default,
    M::Err: Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
    M::MasterProblem: MasterProblem<MinorantIndex = usize> + Send + 'static,
    <M::MasterProblem as MasterProblem>::Err: Into<Box<dyn std::error::Error + Send + Sync + 'static>> + Send,
{
    /// Create a new parallel bundle solver.
    pub fn new(problem: P) -> Self {
        Solver {
            params: Parameters::default(),
            terminator: Default::default(),
            weighter: Default::default(),







<



<
|
<







217
218
219
220
221
222
223

224
225
226

227

228
229
230
231
232
233
234
    /// This is actually the time of the last call to `Solver::init`.
    start_time: Instant,
}

impl<P, T, W, M> Solver<P, T, W, M>
where
    P: FirstOrderProblem,

    T: Terminator<SolverData> + Default,
    W: Weighter<SolverData> + Default,
    M: master::Builder + Default,

    M::MasterProblem: MasterProblem<MinorantIndex = usize>,

{
    /// Create a new parallel bundle solver.
    pub fn new(problem: P) -> Self {
        Solver {
            params: Parameters::default(),
            terminator: Default::default(),
            weighter: Default::default(),
Changes to src/solver.rs.
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
    T,
    SolverError<<P as FirstOrderProblem>::Err, <<M as master::Builder>::MasterProblem as MasterProblem>::Err>,
>;

impl<P, T, W, M> Solver<P, T, W, M>
where
    P: FirstOrderProblem,
    P::Err: Into<Box<std::error::Error + Send + Sync + 'static>>,
    T: for<'a> Terminator<BundleState<'a>> + Default,
    W: for<'a> Weighter<BundleState<'a>> + Default,
    M: master::Builder + Default,
    M::Err: Into<Box<std::error::Error + Send + Sync + 'static>>,
    M::MasterProblem: MasterProblem<MinorantIndex = usize>,
    <M::MasterProblem as master::MasterProblem>::Err: Into<Box<std::error::Error + Send + Sync + 'static>>,
{
    /**
     * 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







|



<

<







452
453
454
455
456
457
458
459
460
461
462

463

464
465
466
467
468
469
470
    T,
    SolverError<<P as FirstOrderProblem>::Err, <<M as master::Builder>::MasterProblem as MasterProblem>::Err>,
>;

impl<P, T, W, M> Solver<P, T, W, M>
where
    P: FirstOrderProblem,
    P::Err: Into<Box<dyn std::error::Error + Sync + Send>>,
    T: for<'a> Terminator<BundleState<'a>> + Default,
    W: for<'a> Weighter<BundleState<'a>> + Default,
    M: master::Builder + Default,

    M::MasterProblem: 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