Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Update to 2018 edition |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
80cbe311acefedefaf6ca79723250209 |
| User & Date: | fifr 2018-12-12 15:30:58.571 |
Context
|
2018-12-12
| ||
| 15:38 | Replace `extern crate` with `use` check-in: 32372fda04 user: fifr tags: trunk | |
| 15:30 | Update to 2018 edition check-in: 80cbe311ac user: fifr tags: trunk | |
|
2018-08-30
| ||
| 13:31 | Merge error-handling check-in: a304098147 user: fifr tags: trunk | |
Changes
Changes to src/firstorderproblem.rs.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 | // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // //! Problem description of a first-order convex optimization problem. | | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
//! Problem description of a first-order convex optimization problem.
use crate::solver::UpdateState;
use crate::{Minorant, Real};
use std::result::Result;
use std::vec::IntoIter;
/**
* Trait for results of an evaluation.
*
|
| ︙ | ︙ |
Changes to src/hkweighter.rs.
| ︙ | ︙ | |||
18 19 20 21 22 23 24 | //! //! The procedure is described in //! //! > Helmberg, C. and Kiwiel, K.C. (2002): A spectral bundle method //! > with bounds, Math. Programming A 93, 173--194 //! | | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
//!
//! The procedure is described in
//!
//! > Helmberg, C. and Kiwiel, K.C. (2002): A spectral bundle method
//! > with bounds, Math. Programming A 93, 173--194
//!
use crate::Real;
use crate::{BundleState, SolverParams, Step, Weighter};
use std::cmp::{max, min};
use std::f64::NEG_INFINITY;
const FACTOR: Real = 2.0;
/**
|
| ︙ | ︙ |
Changes to src/lib.rs.
| ︙ | ︙ | |||
33 34 35 36 37 38 39 |
( $ ( $ x : expr , ) * ) => { DVector(vec![$($x,)*]) };
}
#[macro_use]
extern crate cplex_sys;
pub mod vector;
| | | | | | | 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 |
( $ ( $ x : expr , ) * ) => { DVector(vec![$($x,)*]) };
}
#[macro_use]
extern crate cplex_sys;
pub mod vector;
pub use crate::vector::{DVector, Vector};
pub mod minorant;
pub use crate::minorant::Minorant;
pub mod firstorderproblem;
pub use crate::firstorderproblem::{Evaluation, FirstOrderProblem, SimpleEvaluation, Update};
pub mod solver;
pub use crate::solver::{
BundleState, IterationInfo, Solver, SolverParams, StandardTerminator, Step, Terminator, UpdateState, Weighter,
};
mod hkweighter;
pub use crate::hkweighter::HKWeighter;
mod master;
pub mod mcf;
|
Changes to src/master/base.rs.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
use crate::{DVector, Minorant, Real};
use std::error::Error;
use std::fmt;
use std::result;
/// Error type for master problems.
#[derive(Debug)]
|
| ︙ | ︙ |
Changes to src/master/boxed.rs.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // | | | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
use crate::master::MasterProblem;
use crate::master::UnconstrainedMasterProblem;
use crate::{DVector, Minorant, Real};
use super::Result;
use itertools::multizip;
use std::error::Error;
use std::f64::{EPSILON, INFINITY, NEG_INFINITY};
use std::result;
|
| ︙ | ︙ |
Changes to src/master/cpx.rs.
| ︙ | ︙ | |||
14 15 16 17 18 19 20 | // along with this program. If not, see <http://www.gnu.org/licenses/> // //! Master problem implementation using CPLEX. #![allow(unused_unsafe)] | | | | 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/>
//
//! Master problem implementation using CPLEX.
#![allow(unused_unsafe)]
use crate::master::{Error as MasterProblemError, UnconstrainedMasterProblem};
use crate::{DVector, Minorant, Real};
use cplex_sys as cpx;
use super::Result;
use std;
use std::error::Error;
use std::f64::{self, NEG_INFINITY};
|
| ︙ | ︙ | |||
203 204 205 206 207 208 209 |
// self.force_update = true;
Ok(())
}
fn solve(&mut self, eta: &DVector, _fbound: Real, _augbound: Real, _relprec: Real) -> Result<()> {
if self.force_update || !self.updateinds.is_empty() {
| | | 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
// self.force_update = true;
Ok(())
}
fn solve(&mut self, eta: &DVector, _fbound: Real, _augbound: Real, _relprec: Real) -> Result<()> {
if self.force_update || !self.updateinds.is_empty() {
self.init_qp()?;
}
let nvars = unsafe { cpx::getnumcols(cpx::env(), self.lp) as usize };
if nvars == 0 {
return Err(MasterProblemError::NoMinorants);
}
// update linear costs
|
| ︙ | ︙ |
Changes to src/master/minimal.rs.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // | | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
use crate::master::{Error as MasterProblemError, UnconstrainedMasterProblem};
use crate::{DVector, Minorant, Real};
use super::Result;
use std::error::Error;
use std::f64::NEG_INFINITY;
use std::fmt;
use std::result;
|
| ︙ | ︙ |
Changes to src/master/mod.rs.
| ︙ | ︙ | |||
49 50 51 52 53 54 55 | pub mod minimal; pub use self::minimal::MinimalMaster; // pub mod grb; // pub use master::grb::GurobiMaster; mod cpx; | | | 49 50 51 52 53 54 55 56 | pub mod minimal; pub use self::minimal::MinimalMaster; // pub mod grb; // pub use master::grb::GurobiMaster; mod cpx; pub use crate::master::cpx::CplexMaster; |
Changes to src/master/unconstrained.rs.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
use crate::{DVector, Minorant, Real};
use super::Result;
use std::error::Error;
use std::result;
/**
|
| ︙ | ︙ |
Changes to src/mcf/mod.rs.
| ︙ | ︙ | |||
13 14 15 16 17 18 19 | // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // //! Multi-commodity min-cost-flow subproblems. mod solver; | | | | 13 14 15 16 17 18 19 20 21 22 23 | // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // //! Multi-commodity min-cost-flow subproblems. mod solver; pub use crate::mcf::solver::Solver; mod problem; pub use crate::mcf::problem::MMCFProblem; |
Changes to src/mcf/problem.rs.
| ︙ | ︙ | |||
10 11 12 13 14 15 16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // | | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
use crate::mcf;
use crate::{DVector, FirstOrderProblem, Minorant, Real, SimpleEvaluation};
use std::error::Error;
use std::f64::INFINITY;
use std::fmt;
use std::fs::File;
use std::io::Read;
use std::result;
|
| ︙ | ︙ | |||
65 66 67 68 69 70 71 |
c: Vec<DVector>,
}
impl MMCFProblem {
pub fn read_mnetgen(basename: &str) -> Result<MMCFProblem> {
let mut buffer = String::new();
{
| | | > | | | | | | | | | | | | | | | | | | | | | | | 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 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 165 166 167 168 |
c: Vec<DVector>,
}
impl MMCFProblem {
pub fn read_mnetgen(basename: &str) -> Result<MMCFProblem> {
let mut buffer = String::new();
{
let mut f = File::open(&format!("{}.nod", basename))?;
f.read_to_string(&mut buffer)?;
}
let fnod = buffer
.split_whitespace()
.map(|x| x.parse::<usize>().unwrap())
.collect::<Vec<_>>();
if fnod.len() != 4 {
return Err(MMCFFormatError {
msg: format!("Expected 4 numbers in {}.nod, but got {}", basename, fnod.len()),
}
.into());
}
let ncom = fnod[0];
let nnodes = fnod[1];
let narcs = fnod[2];
let ncaps = fnod[3];
// read nodes
let mut nets = Vec::with_capacity(ncom);
for _ in 0..ncom {
nets.push(mcf::Solver::new(nnodes)?)
}
{
let mut f = File::open(&format!("{}.sup", basename))?;
buffer.clear();
f.read_to_string(&mut buffer)?;
}
for line in buffer.lines() {
let mut data = line.split_whitespace();
let node = data.next().unwrap().parse::<usize>()?;
let com = data.next().unwrap().parse::<usize>()?;
let supply = data.next().unwrap().parse::<Real>()?;
nets[com - 1].set_balance(node - 1, supply)?;
}
// read arcs
let mut arcmap = vec![vec![]; ncom];
let mut cbase = vec![dvec![]; ncom];
// lhs nonzeros
let mut lhsidx = vec![vec![vec![]; ncom]; ncaps];
{
let mut f = File::open(&format!("{}.arc", basename))?;
buffer.clear();
f.read_to_string(&mut buffer)?;
}
for line in buffer.lines() {
let mut data = line.split_whitespace();
let arc = data.next().unwrap().parse::<usize>()? - 1;
let src = data.next().unwrap().parse::<usize>()? - 1;
let snk = data.next().unwrap().parse::<usize>()? - 1;
let com = data.next().unwrap().parse::<usize>()? - 1;
let cost = data.next().unwrap().parse::<Real>()?;
let cap = data.next().unwrap().parse::<Real>()?;
let mt = data.next().unwrap().parse::<isize>()? - 1;
assert!(
arc < narcs,
format!("Wrong arc number (got: {}, expected in 1..{})", arc + 1, narcs)
);
// set internal coeff
let coeff = arcmap[com].len();
arcmap[com].push(ArcInfo {
arc: arc + 1,
src: src + 1,
snk: snk + 1,
});
// add arc
nets[com].add_arc(src, snk, cost, if cap < 0.0 { INFINITY } else { cap })?;
// set objective
cbase[com].push(cost); // + 1e-6 * coeff
// add to mutual capacity constraint
if mt >= 0 {
lhsidx[mt as usize][com].push(coeff);
}
}
// read rhs of coupling constraints
{
let mut f = File::open(&format!("{}.mut", basename))?;
buffer.clear();
f.read_to_string(&mut buffer)?;
}
let mut rhs = dvec![0.0; ncaps];
for line in buffer.lines() {
let mut data = line.split_whitespace();
let mt = data.next().unwrap().parse::<usize>()? - 1;
let cap = data.next().unwrap().parse::<Real>()?;
rhs[mt] = cap;
}
// set lhs
let mut lhs = vec![vec![vec![]; ncom]; ncaps];
for i in 0..ncaps {
for fidx in 0..ncom {
|
| ︙ | ︙ | |||
204 205 206 207 208 209 210 |
let mut aggr = primals[0]
.1
.iter()
.map(|x| {
let mut r = dvec![];
r.scal(primals[0].0, x);
r
| > | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 |
let mut aggr = primals[0]
.1
.iter()
.map(|x| {
let mut r = dvec![];
r.scal(primals[0].0, x);
r
})
.collect::<Vec<_>>();
for &(alpha, primal) in &primals[1..] {
for (j, x) in primal.iter().enumerate() {
aggr[j].add_scaled(alpha, x);
}
}
|
| ︙ | ︙ | |||
264 265 266 267 268 269 270 |
}
}
}
debug!("y={:?}", y);
for i in 0..self.nets.len() {
debug!("c[{}]={}", i, self.c[i]);
| | | | | | | | | | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
}
}
}
debug!("y={:?}", y);
for i in 0..self.nets.len() {
debug!("c[{}]={}", i, self.c[i]);
self.nets[i].set_objective(&self.c[i])?;
}
// solve subproblems
for (i, net) in self.nets.iter_mut().enumerate() {
net.solve()?;
debug!("c[{}]={}", i, net.objective()?);
}
// compute minorant
if self.multimodel {
let objective;
let mut subg;
if fidx == 0 {
subg = self.rhs.clone();
objective = self.rhsval - self.nets[fidx].objective()?;
} else {
subg = dvec![0.0; self.rhs.len()];
objective = -self.nets[fidx].objective()?;
}
let sol = self.nets[fidx].get_solution()?;
for (i, lhs) in self.lhs.iter().enumerate() {
subg[i] -= lhs[fidx].iter().map(|elem| elem.val * sol[elem.ind]).sum::<Real>();
}
Ok(SimpleEvaluation {
objective,
minorants: vec![(
Minorant {
constant: objective,
linear: subg,
},
vec![sol],
)],
})
} else {
let mut objective = self.rhsval;
let mut sols = Vec::with_capacity(self.nets.len());
for i in 0..self.nets.len() {
objective -= self.nets[i].objective()?;
sols.push(self.nets[i].get_solution()?);
}
let mut subg = self.rhs.clone();
for (i, lhs) in self.lhs.iter().enumerate() {
for (fidx, flhs) in lhs.iter().enumerate() {
subg[i] -= flhs.iter().map(|elem| elem.val * sols[fidx][elem.ind]).sum::<Real>();
}
|
| ︙ | ︙ |
Changes to src/mcf/solver.rs.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 | // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // #![allow(unused_unsafe)] | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
#![allow(unused_unsafe)]
use crate::{DVector, Real};
use cplex_sys as cpx;
use std;
use std::error::Error;
use std::ffi::CString;
use std::ptr;
|
| ︙ | ︙ |
Changes to src/minorant.rs.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 | // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // //! A linear minorant. | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
//! A linear minorant.
use crate::{DVector, Real};
use std::fmt;
/**
* A linear minorant of a convex function.
*
* A linear minorant of a convex function $f \colon \mathbb{R}\^n \to
|
| ︙ | ︙ | |||
38 39 40 41 42 43 44 |
/// The linear term.
pub linear: DVector,
}
impl fmt::Display for Minorant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
| | | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
/// The linear term.
pub linear: DVector,
}
impl fmt::Display for Minorant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} + y * {}", self.constant, self.linear)?;
Ok(())
}
}
impl Default for Minorant {
fn default() -> Minorant {
Minorant {
|
| ︙ | ︙ |
Changes to src/solver.rs.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 | // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/> // //! The main bundle method solver. | | | | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
//! The main bundle method solver.
use crate::{DVector, Real};
use crate::{Evaluation, FirstOrderProblem, HKWeighter, Update};
use crate::master::{BoxedMasterProblem, Error as MasterProblemError, MasterProblem, UnconstrainedMasterProblem};
use crate::master::{CplexMaster, MinimalMaster};
use std::error::Error;
use std::f64::{INFINITY, NEG_INFINITY};
use std::fmt;
use std::mem::swap;
use std::result::Result;
use std::time::Instant;
|
| ︙ | ︙ |
Changes to src/vector.rs.
| ︙ | ︙ | |||
12 13 14 15 16 17 18 19 20 |
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
//! Finite-dimensional sparse and dense vectors.
use std::fmt;
use std::ops::{Deref, DerefMut};
| > < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
//
//! Finite-dimensional sparse and dense vectors.
use crate::Real;
use std::fmt;
use std::ops::{Deref, DerefMut};
// use std::cmp::min;
use std::iter::FromIterator;
use std::vec::IntoIter;
/// Type of dense vectors.
#[derive(Debug, Clone, PartialEq, Default)]
pub struct DVector(pub Vec<Real>);
|
| ︙ | ︙ | |||
39 40 41 42 43 44 45 |
fn deref_mut(&mut self) -> &mut Vec<Real> {
&mut self.0
}
}
impl fmt::Display for DVector {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
| | | | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
fn deref_mut(&mut self) -> &mut Vec<Real> {
&mut self.0
}
}
impl fmt::Display for DVector {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(")?;
for (i, x) in self.iter().enumerate() {
if i > 0 {
write!(f, ", ")?;
}
write!(f, "{}", x)?
}
write!(f, ")")?;
Ok(())
}
}
impl FromIterator<Real> for DVector {
fn from_iter<I: IntoIterator<Item = Real>>(iter: I) -> Self {
DVector(Vec::from_iter(iter))
|
| ︙ | ︙ | |||
87 88 89 90 91 92 93 |
impl fmt::Display for Vector {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Vector::Dense(ref v) => write!(f, "{}", v),
Vector::Sparse { size, ref elems } => {
let mut it = elems.iter();
| | | | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
impl fmt::Display for Vector {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Vector::Dense(ref v) => write!(f, "{}", v),
Vector::Sparse { size, ref elems } => {
let mut it = elems.iter();
write!(f, "{}:(", size)?;
if let Some(&(i, x)) = it.next() {
write!(f, "{}:{}", i, x)?;
for &(i, x) in it {
write!(f, ", {}:{}", i, x)?;
}
}
write!(f, ")")
}
}
}
}
|
| ︙ | ︙ |