| ︙ | | |
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
-
-
+
+
+
+
|
//
//! The main bundle method solver.
use crate::{Aggregatable, DVector, Real};
use crate::{Evaluation, FirstOrderProblem, HKWeighter, Update};
use crate::master::{BoxedMasterProblem, Error as MasterProblemError, MasterProblem, UnconstrainedMasterProblem};
use crate::master::{CplexMaster, MinimalMaster};
use crate::master::CplexMaster;
use crate::master::{
BoxedMasterProblem, Error as MasterProblemError, MasterProblem, MinimalMaster, UnconstrainedMasterProblem,
};
use log::{debug, info, warn};
use std::error::Error;
use std::f64::{INFINITY, NEG_INFINITY};
use std::fmt;
use std::mem::swap;
|
| ︙ | | |
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
|
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
|
+
+
+
+
+
+
+
+
-
+
+
|
///
/// 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>>>;
/// A bundle solver with a minimal cutting plane model.
pub type NoBundleSolver<P> = Solver<P, BoxedMasterProblem<MinimalMaster<<P as FirstOrderProblem>::Err>>>;
/**
* Implementation of a bundle method.
*/
pub struct Solver<P, M = BoxedMasterProblem<CplexMaster<<P as FirstOrderProblem>::Err>>>
where
pub struct Solver<P: FirstOrderProblem> {
P: FirstOrderProblem,
{
/// The first order problem description.
problem: P,
/// The solver parameter.
pub params: SolverParams,
/// Termination predicate.
|
| ︙ | | |
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
|
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
|
-
+
-
+
+
+
-
+
+
|
* Time when the solution process started.
*
* This is actually the time of the last call to `Solver::init`.
*/
start_time: Instant,
/// The master problem.
master: Box<MasterProblem<MinorantIndex = usize, SubgradientExtensionErr = P::Err>>,
master: M,
/// The active minorant indices for each subproblem.
minorants: Vec<Vec<MinorantInfo<P::Primal>>>,
/// Accumulated information about the last iteration.
iterinfos: Vec<IterationInfo>,
}
impl<P: FirstOrderProblem> Solver<P>
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>,
{
/**
* 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
* internally stored problem using `Solver::problem()`.
*/
pub fn new_params(problem: P, params: SolverParams) -> Result<Solver<P>, SolverError<P::Err>> {
pub fn new_params(problem: P, params: SolverParams) -> Result<Solver<P, M>, SolverError<P::Err>> {
let master: M = M::new()?;
Ok(Solver {
problem,
params,
terminator: Box::new(StandardTerminator {
termination_precision: 1e-3,
}),
weighter: Box::new(HKWeighter::new()),
|
| ︙ | | |
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
|
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
|
-
+
-
+
|
nxt_mods: dvec![],
new_cutval: 0.0,
sgnorm: 0.0,
expected_progress: 0.0,
cnt_descent: 0,
cnt_null: 0,
start_time: Instant::now(),
master: Box::new(BoxedMasterProblem::new(MinimalMaster::new()?)),
master: master,
minorants: vec![],
iterinfos: vec![],
})
}
/// A new solver with default parameter.
pub fn new(problem: P) -> Result<Solver<P>, SolverError<P::Err>> {
pub fn new(problem: P) -> Result<Solver<P, M>, SolverError<P::Err>> {
Solver::new_params(problem, SolverParams::default())
}
/**
* Set the first order problem description associated with this
* solver.
*
|
| ︙ | | |
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
|
793
794
795
796
797
798
799
800
801
802
803
804
805
806
|
-
-
-
-
-
-
-
-
|
* The oracle is evaluated once at the initial center and the
* master problem is initialized with the returned subgradient
* information.
*/
fn init_master(&mut self) -> Result<(), SolverError<P::Err>> {
let m = self.problem.num_subproblems();
self.master = if m == 1 && self.params.max_bundle_size == 2 {
debug!("Use minimal master problem");
Box::new(BoxedMasterProblem::new(MinimalMaster::new()?))
} else {
debug!("Use CPLEX master problem");
Box::new(BoxedMasterProblem::new(CplexMaster::new()?))
};
let lb = self.problem.lower_bounds().map(DVector);
let ub = self.problem.upper_bounds().map(DVector);
if lb
.as_ref()
.map(|lb| lb.len() != self.problem.num_variables())
.unwrap_or(false)
|
| ︙ | | |