Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Remove old sequential solver |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | restructure |
| Files: | files | file ages | folders |
| SHA1: |
b194454b53eb0a102d9efcb195ec9fc2 |
| User & Date: | fifr 2019-07-30 07:25:14.820 |
Context
|
2019-07-30
| ||
| 07:40 | Move `parallel` to `solver::sync` check-in: 62c311d2a4 user: fifr tags: restructure | |
| 07:25 | Remove old sequential solver check-in: b194454b53 user: fifr tags: restructure | |
|
2019-07-29
| ||
| 19:08 | Add `dyn` to trait object types check-in: 3b15a29a64 user: fifr tags: async | |
Changes
Changes to examples/cflp.rs.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 | */ #![allow(non_upper_case_globals)] //! Example implementation for a capacitated facility location problem. use better_panic; | < < < < | 16 17 18 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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
*/
#![allow(non_upper_case_globals)]
//! Example implementation for a capacitated facility location problem.
use better_panic;
use log::{info, Level};
use rustop::opts;
use std::error::Error;
use std::fmt::Write;
use std::io::Write as _;
use std::sync::Arc;
use env_logger::{self, fmt::Color};
use ordered_float::NotNan;
use threadpool::ThreadPool;
use bundle::parallel::{
DefaultSolver as ParallelSolver, EvalResult, FirstOrderProblem as ParallelProblem,
NoBundleSolver as NoParallelSolver, ResultSender,
};
use bundle::{dvec, DVector, Minorant, Real};
const Nfac: usize = 3;
const Ncus: usize = 5;
const F: [Real; Nfac] = [1000.0, 1000.0, 1000.0];
const CAP: [Real; Nfac] = [500.0, 500.0, 500.0];
const C: [[Real; Ncus]; Nfac] = [
[4.0, 5.0, 6.0, 8.0, 10.0], //
[6.0, 4.0, 3.0, 5.0, 8.0], //
[9.0, 7.0, 4.0, 3.0, 4.0], //
];
const DEMAND: [Real; 5] = [80.0, 270.0, 250.0, 160.0, 180.0];
#[derive(Debug)]
enum EvalError {
Customer(usize),
}
impl std::fmt::Display for EvalError {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
match self {
EvalError::Customer(i) => writeln!(fmt, "Customer subproblem {} failed", i),
}
}
}
impl Error for EvalError {}
struct CFLProblem {
|
| ︙ | ︙ | |||
121 122 123 124 125 126 127 |
constant: objective,
linear: subg,
},
primal,
))
}
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
constant: objective,
linear: subg,
},
primal,
))
}
impl ParallelProblem for CFLProblem {
type Err = EvalError;
type Primal = DVector;
fn num_variables(&self) -> usize {
Nfac
|
| ︙ | ︙ | |||
300 301 302 303 304 305 306 |
let (args, _) = opts! {
synopsis "Solver a simple capacitated facility location problem";
opt minimal:bool, desc:"Use the minimal master model";
}
.parse_or_exit();
if !args.minimal {
| < < < < < < < < < < < < | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
let (args, _) = opts! {
synopsis "Solver a simple capacitated facility location problem";
opt minimal:bool, desc:"Use the minimal master model";
}
.parse_or_exit();
if !args.minimal {
let mut slv = ParallelSolver::<_>::new(CFLProblem::new());
slv.terminator.termination_precision = 1e-9;
slv.master.max_bundle_size = 5;
slv.solve()?;
show_primals(|i| slv.aggregated_primal(i).unwrap())?;
} else {
let mut slv = NoParallelSolver::<_>::new(CFLProblem::new());
slv.terminator.termination_precision = 1e-5;
slv.solve()?;
show_primals(|i| slv.aggregated_primal(i).unwrap())?;
}
Ok(())
}
|
Changes to examples/mmcf.rs.
| ︙ | ︙ | |||
21 22 23 24 25 26 27 |
use rustop::opts;
use std::io::Write;
use bundle::master::{Builder as MasterBuilder, MasterProblem};
use bundle::mcf::MMCFProblem;
use bundle::parallel;
use bundle::{terminator::StandardTerminator, weighter::HKWeighter};
| < < < < < < < < < < < < < < < < < < < < | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
use rustop::opts;
use std::io::Write;
use bundle::master::{Builder as MasterBuilder, MasterProblem};
use bundle::mcf::MMCFProblem;
use bundle::parallel;
use bundle::{terminator::StandardTerminator, weighter::HKWeighter};
use bundle::{FullMasterBuilder, MinimalMasterBuilder};
use std::error::Error;
use std::result::Result;
fn solve_parallel<M>(master: M, mmcf: MMCFProblem) -> Result<(), Box<dyn Error>>
where
M: MasterBuilder,
M::MasterProblem: MasterProblem<MinorantIndex = usize>,
{
let mut slv = parallel::Solver::<_, StandardTerminator, HKWeighter, M>::with_master(mmcf, master);
slv.weighter.set_weight_bounds(1e-1, 100.0);
|
| ︙ | ︙ | |||
103 104 105 106 107 108 109 |
}
.parse_or_exit();
let filename = args.file;
info!("Reading instance: {}", filename);
if !args.minimal {
| < | < < < < < | < < < < < < < < < < < < < < < < < < < | | | | | | | | | < < | < < < < < < < < < < | | | | < | 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 |
}
.parse_or_exit();
let filename = args.file;
info!("Reading instance: {}", filename);
if !args.minimal {
let mut mmcf = MMCFProblem::read_mnetgen(&filename)?;
mmcf.set_separate_constraints(args.separate);
mmcf.multimodel = true;
let mut master = FullMasterBuilder::default();
if args.aggregated {
master.max_bundle_size(if args.bundle_size <= 1 { 50 } else { args.bundle_size });
master.use_full_aggregation();
} else {
master.max_bundle_size(if args.bundle_size <= 1 { 5 } else { args.bundle_size });
}
solve_parallel(master, mmcf)?;
} else {
let mut mmcf = MMCFProblem::read_mnetgen(&filename)?;
mmcf.set_separate_constraints(args.separate);
mmcf.multimodel = true;
let master = MinimalMasterBuilder::default();
solve_parallel(master, mmcf)?;
}
Ok(())
}
|
Changes to examples/quadratic.rs.
| ︙ | ︙ | |||
27 28 29 30 31 32 33 |
use std::sync::Arc;
use std::thread;
use bundle::parallel::{
DefaultSolver as ParallelSolver, EvalResult, FirstOrderProblem as ParallelProblem,
NoBundleSolver as NoParallelSolver, ResultSender,
};
| | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | | > > > | > > > > > > > > > > | | | | | < | | | > > > | | | < < < | 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 59 60 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 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
use std::sync::Arc;
use std::thread;
use bundle::parallel::{
DefaultSolver as ParallelSolver, EvalResult, FirstOrderProblem as ParallelProblem,
NoBundleSolver as NoParallelSolver, ResultSender,
};
use bundle::{DVector, Minorant, Real};
#[derive(Clone)]
struct QuadraticProblem {
a: [[Real; 2]; 2],
b: [Real; 2],
c: Real,
}
impl QuadraticProblem {
fn new() -> QuadraticProblem {
QuadraticProblem {
a: [[5.0, 1.0], [1.0, 4.0]],
b: [-12.0, -10.0],
c: 3.0,
}
}
}
impl ParallelProblem for QuadraticProblem {
type Err = Box<dyn Error + Send + Sync>;
type Primal = ();
fn num_variables(&self) -> usize {
2
}
fn num_subproblems(&self) -> usize {
1
}
fn start(&mut self) {}
fn stop(&mut self) {}
fn evaluate<I>(
&mut self,
fidx: usize,
x: Arc<DVector>,
index: I,
tx: ResultSender<I, Self::Primal, Self::Err>,
) -> Result<(), Self::Err>
where
I: Send + Copy + 'static,
{
let x = x.clone();
let p = self.clone();
thread::spawn(move || {
assert_eq!(fidx, 0);
let mut objective = p.c;
let mut g = dvec![0.0; 2];
for i in 0..2 {
g[i] += (0..2).map(|j| p.a[i][j] * x[j]).sum::<Real>();
objective += x[i] * (g[i] + p.b[i]);
g[i] = 2.0 * g[i] + p.b[i];
}
debug!("Evaluation at {:?}", x);
debug!(" objective={}", objective);
debug!(" subgradient={}", g);
tx.send(Ok(EvalResult::ObjectiveValue {
index,
value: objective,
}))
.unwrap();
tx.send(Ok(EvalResult::Minorant {
index,
minorant: Minorant {
constant: objective,
linear: g,
},
primal: (),
}))
.unwrap();
});
Ok(())
}
}
fn main() -> Result<(), Box<dyn Error>> {
better_panic::install();
|
| ︙ | ︙ | |||
169 170 171 172 173 174 175 |
let (args, _) = opts! {
synopsis "Solver a simple quadratic optimization problem";
opt minimal:bool, desc:"Use the minimal master model";
}
.parse_or_exit();
| < | | < < < < < < < < < < < < < < < < | | | | | | | < | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
let (args, _) = opts! {
synopsis "Solver a simple quadratic optimization problem";
opt minimal:bool, desc:"Use the minimal master model";
}
.parse_or_exit();
let f = QuadraticProblem::new();
if !args.minimal {
let mut solver = ParallelSolver::<_>::new(f);
solver.solve().map_err(|e| format!("{}", e))?;
} else {
let mut solver = NoParallelSolver::<_>::new(f);
solver.solve().map_err(|e| format!("{}", e))?;
}
Ok(())
}
|
Deleted src/firstorderproblem.rs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to src/lib.rs.
| ︙ | ︙ | |||
28 29 30 31 32 33 34 |
pub mod vector;
pub use crate::vector::{DVector, Vector};
pub mod minorant;
pub use crate::minorant::{Aggregatable, Minorant};
| < < < < < < | < < | < | | 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
pub mod vector;
pub use crate::vector::{DVector, Vector};
pub mod minorant;
pub use crate::minorant::{Aggregatable, Minorant};
pub mod parallel;
pub mod weighter;
pub mod terminator;
pub mod master;
pub mod mcf;
/// The minimal bundle builder.
pub type FullMasterBuilder = master::boxed::Builder<master::cpx::Builder>;
/// The minimal bundle builder.
pub type MinimalMasterBuilder = master::boxed::Builder<master::minimal::Builder>;
|
Changes to src/mcf/problem.rs.
| ︙ | ︙ | |||
15 16 17 18 19 20 21 |
//
use crate::mcf;
use crate::parallel::{
EvalResult, FirstOrderProblem as ParallelProblem, ResultSender, Update as ParallelUpdate, UpdateSender,
UpdateState as ParallelUpdateState,
};
| | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
//
use crate::mcf;
use crate::parallel::{
EvalResult, FirstOrderProblem as ParallelProblem, ResultSender, Update as ParallelUpdate, UpdateSender,
UpdateState as ParallelUpdateState,
};
use crate::{DVector, Minorant, Real};
use itertools::izip;
use log::{debug, warn};
use num_traits::Float;
use threadpool::ThreadPool;
use std::f64::INFINITY;
|
| ︙ | ︙ | |||
181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
.map(|elem| elem.val * primal[elem.ind])
.sum::<Real>();
rhs - lhs
}
}
impl MMCFProblem {
pub fn read_mnetgen(basename: &str) -> std::result::Result<MMCFProblem, MMCFReadError> {
let mut buffer = String::new();
{
let mut f = File::open(&format!("{}.nod", basename))?;
f.read_to_string(&mut buffer)?;
}
let fnod = buffer
| > > > > | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
.map(|elem| elem.val * primal[elem.ind])
.sum::<Real>();
rhs - lhs
}
}
impl MMCFProblem {
pub fn num_subproblems(&self) -> usize {
self.subs.len()
}
pub fn read_mnetgen(basename: &str) -> std::result::Result<MMCFProblem, MMCFReadError> {
let mut buffer = String::new();
{
let mut f = File::open(&format!("{}.nod", basename))?;
f.read_to_string(&mut buffer)?;
}
let fnod = buffer
|
| ︙ | ︙ | |||
358 359 360 361 362 363 364 |
}
}
aggr
}
}
| | | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 |
}
}
aggr
}
}
impl ParallelProblem for MMCFProblem {
type Err = Error;
type Primal = DVector;
fn num_variables(&self) -> usize {
self.active_constraints.len()
}
fn lower_bounds(&self) -> Option<Vec<Real>> {
Some(vec![0.0; self.num_variables()])
}
fn num_subproblems(&self) -> usize {
self.subs.len()
}
fn start(&mut self) {
|
| ︙ | ︙ |
Changes to src/parallel/solver.rs.
| ︙ | ︙ | |||
26 27 28 29 30 31 32 |
use threadpool::ThreadPool;
use crate::{DVector, Real};
use super::masterprocess::{MasterConfig, MasterProcess, MasterResponse};
use super::problem::{EvalResult, FirstOrderProblem, Update, UpdateState};
use crate::master::{self, MasterProblem};
| < | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
use threadpool::ThreadPool;
use crate::{DVector, Real};
use super::masterprocess::{MasterConfig, MasterProcess, MasterResponse};
use super::problem::{EvalResult, FirstOrderProblem, Update, UpdateState};
use crate::master::{self, MasterProblem};
use crate::terminator::{StandardTerminatable, StandardTerminator, Terminator};
use crate::weighter::{HKWeightable, HKWeighter, Weighter};
/// The default iteration limit.
pub const DEFAULT_ITERATION_LIMIT: usize = 10_000;
/// Error raised by the parallel bundle [`Solver`].
|
| ︙ | ︙ | |||
114 115 116 117 118 119 120 |
type ClientSender<P> =
Sender<std::result::Result<EvalResult<usize, <P as FirstOrderProblem>::Primal>, <P as FirstOrderProblem>::Err>>;
type ClientReceiver<P> =
Receiver<std::result::Result<EvalResult<usize, <P as FirstOrderProblem>::Primal>, <P as FirstOrderProblem>::Err>>;
/// Parameters for tuning the solver.
| > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > | 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
type ClientSender<P> =
Sender<std::result::Result<EvalResult<usize, <P as FirstOrderProblem>::Primal>, <P as FirstOrderProblem>::Err>>;
type ClientReceiver<P> =
Receiver<std::result::Result<EvalResult<usize, <P as FirstOrderProblem>::Primal>, <P as FirstOrderProblem>::Err>>;
/// Parameters for tuning the solver.
#[derive(Debug, Clone)]
pub struct Parameters {
/// The descent step acceptance factors, must be in (0,1).
///
/// The default value is 0.1.
acceptance_factor: Real,
}
impl Default for Parameters {
fn default() -> Self {
Parameters { acceptance_factor: 0.1 }
}
}
impl Parameters {
/// Change the descent step acceptance factor.
///
/// The default value is 0.1.
pub fn set_acceptance_factor(&mut self, acceptance_factor: Real) {
assert!(
acceptance_factor > 0.0 && acceptance_factor < 1.0,
"Descent step acceptance factors must be in (0,1), got: {}",
acceptance_factor
);
self.acceptance_factor = acceptance_factor;
}
}
/// The step type that has been performed.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Step {
/// A null step has been performed.
Null,
/// A descent step has been performed.
Descent,
/// No step but the algorithm has been terminated.
Term,
}
pub struct SolverData {
/// Current center of stability.
cur_y: DVector,
/// Function value in the current point.
cur_val: Real,
|
| ︙ | ︙ |
Deleted src/solver.rs.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |