RsBundle  Diff

Differences From Artifact [cb2c7849ad]:

  • File src/parallel/solver.rs — part of check-in [04cb8ebb99] at 2019-07-21 20:52:30 on branch async — parallel::solver: fix ref in doc of `init` (user: fifr size: 20104)

To Artifact [7a89c2116c]:

  • File src/parallel/solver.rs — part of check-in [5ee9fe59e5] at 2019-07-22 08:52:58 on branch master-builder — Introduce master problem builder (user: fifr size: 20732)

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
use std::time::Instant;
use threadpool::ThreadPool;

use crate::{DVector, Real};

use super::masterprocess::{MasterConfig, MasterProcess};
use super::problem::{EvalResult, FirstOrderProblem};

use crate::master::{BoxedMasterProblem, CplexMaster, MasterProblem as MP};
use crate::solver::{SolverParams, Step};
use crate::terminator::{StandardTerminatable, StandardTerminator, Terminator};
use crate::weighter::{HKWeightable, HKWeighter, Weighter};

/// The default iteration limit.
pub const DEFAULT_ITERATION_LIMIT: usize = 10_000;



type MasterProblem = BoxedMasterProblem<CplexMaster>;

type MasterProblemError = <MasterProblem as MP>::Err;

/// Error raised by the parallel bundle [`Solver`].
#[derive(Debug)]
pub enum Error<E> {


    /// An error raised by the master problem process.
    Master(MasterProblemError),
    /// The iteration limit has been reached.
    IterationLimit { limit: usize },
    /// An error raised by a subproblem evaluation.
    Evaluation(E),
    /// The dimension of some data is wrong.







>
|







>
>
|






>
>







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
55
56
57
58
use std::time::Instant;
use threadpool::ThreadPool;

use crate::{DVector, Real};

use super::masterprocess::{MasterConfig, MasterProcess};
use super::problem::{EvalResult, FirstOrderProblem};
use crate::master::{boxed, cpx};
use crate::master::{BoxedMasterProblem, Builder, MasterProblem as MP};
use crate::solver::{SolverParams, Step};
use crate::terminator::{StandardTerminatable, StandardTerminator, Terminator};
use crate::weighter::{HKWeightable, HKWeighter, Weighter};

/// The default iteration limit.
pub const DEFAULT_ITERATION_LIMIT: usize = 10_000;

type MasterBuilder = boxed::Builder<cpx::Builder>;

type MasterProblem = BoxedMasterProblem<cpx::CplexMaster>;

type MasterProblemError = <MasterProblem as MP>::Err;

/// Error raised by the parallel bundle [`Solver`].
#[derive(Debug)]
pub enum Error<E> {
    /// An error raised when creating a new master problem solver.
    BuildMaster(Box<dyn std::error::Error>),
    /// An error raised by the master problem process.
    Master(MasterProblemError),
    /// The iteration limit has been reached.
    IterationLimit { limit: usize },
    /// An error raised by a subproblem evaluation.
    Evaluation(E),
    /// The dimension of some data is wrong.
61
62
63
64
65
66
67

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

85
86
87
88
89
90
91
impl<E> std::fmt::Display for Error<E>
where
    E: std::fmt::Display,
{
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
        use Error::*;
        match self {

            Master(err) => writeln!(fmt, "Error in master problem: {}", err),
            IterationLimit { limit } => writeln!(fmt, "The iteration limit has been reached: {}", limit),
            Evaluation(err) => writeln!(fmt, "Error in subproblem evaluation: {}", err),
            Dimension(what) => writeln!(fmt, "Wrong dimension for {}", what),
            Process(err) => writeln!(fmt, "Error in subprocess: {}", err),
            NotInitialized => writeln!(fmt, "The solver must be initialized (called Solver::init()?)"),
        }
    }
}

impl<E> std::error::Error for Error<E>
where
    E: std::error::Error + 'static,
{
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use Error::*;
        match self {

            Master(err) => Some(err),
            Evaluation(err) => Some(err),
            Process(err) => Some(err.as_ref()),
            _ => None,
        }
    }
}







>

















>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
impl<E> std::fmt::Display for Error<E>
where
    E: std::fmt::Display,
{
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::result::Result<(), std::fmt::Error> {
        use Error::*;
        match self {
            BuildMaster(err) => writeln!(fmt, "Cannot create master problem solver: {}", err),
            Master(err) => writeln!(fmt, "Error in master problem: {}", err),
            IterationLimit { limit } => writeln!(fmt, "The iteration limit has been reached: {}", limit),
            Evaluation(err) => writeln!(fmt, "Error in subproblem evaluation: {}", err),
            Dimension(what) => writeln!(fmt, "Wrong dimension for {}", what),
            Process(err) => writeln!(fmt, "Error in subprocess: {}", err),
            NotInitialized => writeln!(fmt, "The solver must be initialized (called Solver::init()?)"),
        }
    }
}

impl<E> std::error::Error for Error<E>
where
    E: std::error::Error + 'static,
{
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        use Error::*;
        match self {
            BuildMaster(err) => Some(err.as_ref()),
            Master(err) => Some(err),
            Evaluation(err) => Some(err),
            Process(err) => Some(err.as_ref()),
            _ => None,
        }
    }
}
180
181
182
183
184
185
186



187
188
189
190
191
192
193
    pub threadpool: ThreadPool,

    /// The first order problem.
    problem: P,

    /// The algorithm data.
    data: SolverData,




    /// The master problem process.
    master: Option<MasterProcess<P, MasterProblem>>,

    /// The channel to receive the evaluation results from subproblems.
    client_tx: Option<ClientSender<P>>,








>
>
>







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
    pub threadpool: ThreadPool,

    /// The first order problem.
    problem: P,

    /// The algorithm data.
    data: SolverData,

    /// The master problem builder.
    master_builder: MasterBuilder,

    /// The master problem process.
    master: Option<MasterProcess<P, MasterProblem>>,

    /// The channel to receive the evaluation results from subproblems.
    client_tx: Option<ClientSender<P>>,

231
232
233
234
235
236
237

238
239
240
241
242
243
244
                nxt_mod: 0.0,
                new_cutval: 0.0,
                sgnorm: 0.0,
                cur_weight: 1.0,
            },

            threadpool: ThreadPool::with_name("Parallel bundle solver".to_string(), num_cpus::get()),

            master: None,
            client_tx: None,
            client_rx: None,

            cnt_descent: 0,
            cnt_null: 0,
            cnt_evals: 0,







>







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
                nxt_mod: 0.0,
                new_cutval: 0.0,
                sgnorm: 0.0,
                cur_weight: 1.0,
            },

            threadpool: ThreadPool::with_name("Parallel bundle solver".to_string(), num_cpus::get()),
            master_builder: MasterBuilder::default(),
            master: None,
            client_tx: None,
            client_rx: None,

            cnt_descent: 0,
            cnt_null: 0,
            cnt_evals: 0,
310
311
312
313
314
315
316
317






318
319
320
321
322
323
324
            .map(|ub| ub.len() != n)
            .unwrap_or(false)
        {
            return Err(Error::Dimension("upper bounds".to_string()));
        }

        debug!("Start master process");
        self.master = Some(MasterProcess::start(master_config, &mut self.threadpool));






        let master = self.master.as_mut().unwrap();

        debug!("Initial problem evaluation");
        // We need an initial evaluation of all oracles for the first center.
        let y = Arc::new(self.data.cur_y.clone());
        for i in 0..m {
            self.problem







|
>
>
>
>
>
>







321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
            .map(|ub| ub.len() != n)
            .unwrap_or(false)
        {
            return Err(Error::Dimension("upper bounds".to_string()));
        }

        debug!("Start master process");
        self.master = Some(MasterProcess::start(
            self.master_builder
                .build()
                .map_err(|err| Error::BuildMaster(err.into()))?,
            master_config,
            &mut self.threadpool,
        ));
        let master = self.master.as_mut().unwrap();

        debug!("Initial problem evaluation");
        // We need an initial evaluation of all oracles for the first center.
        let y = Arc::new(self.data.cur_y.clone());
        for i in 0..m {
            self.problem