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
|