Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | master: Subgradient extension callback may return an error. This callback eventually calls a method of the oracle and may fail with some user error. This error is now returned to the master problem and finally back to the solver. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | error-handling |
| Files: | files | file ages | folders |
| SHA1: |
cd30b6f27247dbfbda5d1378e135328c |
| User & Date: | fifr 2018-06-26 21:17:34.348 |
Context
|
2018-06-26
| ||
| 21:39 | Implement `MasterProblemError` as more specific enum check-in: 58f8ffe7a1 user: fifr tags: error-handling | |
| 21:17 | master: Subgradient extension callback may return an error. check-in: cd30b6f272 user: fifr tags: error-handling | |
| 16:00 | Update version to 0.5.0 check-in: c62a27d815 user: fifr tags: error-handling, v0.5.0 | |
Changes
Changes to src/master/base.rs.
| ︙ | ︙ | |||
55 56 57 58 59 60 61 |
/// Add or movesome variables with bounds.
///
/// If an index is specified, existing variables are moved,
/// otherwise new variables are generated.
fn add_vars(
&mut self,
bounds: &[(Option<usize>, Real, Real)],
| | | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
/// Add or movesome variables with bounds.
///
/// If an index is specified, existing variables are moved,
/// otherwise new variables are generated.
fn add_vars(
&mut self,
bounds: &[(Option<usize>, Real, Real)],
extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> Result<DVector>,
) -> Result<()>;
/// Add a new minorant to the model.
///
/// The function returns a unique (among all minorants of all
/// subproblems) index of the minorant. This index must remain
/// valid until the minorant is aggregated.
|
| ︙ | ︙ |
Changes to src/master/boxed.rs.
| ︙ | ︙ | |||
205 206 207 208 209 210 211 |
fn set_weight(&mut self, weight: Real) -> Result<()> {
self.master.set_weight(weight)
}
fn add_vars(
&mut self,
bounds: &[(Option<usize>, Real, Real)],
| | | 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
fn set_weight(&mut self, weight: Real) -> Result<()> {
self.master.set_weight(weight)
}
fn add_vars(
&mut self,
bounds: &[(Option<usize>, Real, Real)],
extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> Result<DVector>,
) -> Result<()> {
if !bounds.is_empty() {
for (index, l, u) in bounds.iter().filter_map(|v| v.0.map(|i| (i, v.1, v.2))) {
self.lb[index] = l;
self.ub[index] = u;
}
self.lb.extend(bounds.iter().filter(|v| v.0.is_none()).map(|x| x.1));
|
| ︙ | ︙ |
Changes to src/master/cpx.rs.
| ︙ | ︙ | |||
165 166 167 168 169 170 171 |
}
}
fn add_vars(
&mut self,
nnew: usize,
changed: &[usize],
| | | | 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
}
}
fn add_vars(
&mut self,
nnew: usize,
changed: &[usize],
extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> Result<DVector>,
) -> Result<()> {
debug_assert!(!self.minorants[0].is_empty());
let noldvars = self.minorants[0][0].linear.len();
let nnewvars = noldvars + nnew;
let mut changedvars = vec![];
changedvars.extend_from_slice(changed);
changedvars.extend(noldvars..nnewvars);
for (fidx, mins) in self.minorants.iter_mut().enumerate() {
if !mins.is_empty() {
for (i, m) in mins.iter_mut().enumerate() {
let new_subg = extend_subgradient(fidx, i, &changedvars)?;
for (&j, &g) in changed.iter().zip(new_subg.iter()) {
m.linear[j] = g;
}
m.linear.extend_from_slice(&new_subg[changed.len()..]);
}
}
}
|
| ︙ | ︙ |
Changes to src/master/minimal.rs.
| ︙ | ︙ | |||
117 118 119 120 121 122 123 |
Ok(self.minorants.len() - 1)
}
fn add_vars(
&mut self,
nnew: usize,
changed: &[usize],
| | | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
Ok(self.minorants.len() - 1)
}
fn add_vars(
&mut self,
nnew: usize,
changed: &[usize],
extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> Result<DVector>,
) -> Result<()> {
if !self.minorants.is_empty() {
let noldvars = self.minorants[0].linear.len();
let mut changedvars = vec![];
changedvars.extend_from_slice(changed);
changedvars.extend(noldvars..noldvars + nnew);
for (i, m) in self.minorants.iter_mut().enumerate() {
let new_subg = extend_subgradient(0, i, &changedvars)?;
for (&j, &g) in changed.iter().zip(new_subg.iter()) {
m.linear[j] = g;
}
m.linear.extend_from_slice(&new_subg[changed.len()..]);
}
}
|
| ︙ | ︙ |
Changes to src/master/unconstrained.rs.
| ︙ | ︙ | |||
74 75 76 77 78 79 80 |
/// The variables in `changed` have been changed, so the subgradient
/// information must be updated. Furthermore, `nnew` new variables
/// are added.
fn add_vars(
&mut self,
nnew: usize,
changed: &[usize],
| | | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
/// The variables in `changed` have been changed, so the subgradient
/// information must be updated. Furthermore, `nnew` new variables
/// are added.
fn add_vars(
&mut self,
nnew: usize,
changed: &[usize],
extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> Result<DVector>,
) -> Result<()>;
/// Solve the master problem.
fn solve(&mut self, eta: &DVector, fbound: Real, augbound: Real, relprec: Real) -> Result<()>;
/// Return the current dual optimal solution.
fn dualopt(&self) -> &DVector;
|
| ︙ | ︙ |
Changes to src/solver.rs.
| ︙ | ︙ | |||
460 461 462 463 464 465 466 |
/// The active minorant indices for each subproblem.
minorants: Vec<Vec<MinorantInfo<P::Primal>>>,
/// Accumulated information about the last iteration.
iterinfos: Vec<IterationInfo>,
}
| | > > > | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 |
/// 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>
where
P::Err: Into<Box<dyn Error>>,
{
/**
* 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()`.
|
| ︙ | ︙ | |||
681 682 683 684 685 686 687 |
if !newvars.is_empty() {
let mut problem = &mut self.problem;
let minorants = &self.minorants;
self.master
.add_vars(
&newvars.iter().map(|v| (v.0, v.1, v.2)).collect::<Vec<_>>(),
| | > | | < < | | 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 |
if !newvars.is_empty() {
let mut problem = &mut self.problem;
let minorants = &self.minorants;
self.master
.add_vars(
&newvars.iter().map(|v| (v.0, v.1, v.2)).collect::<Vec<_>>(),
&mut move |fidx, minidx, vars| {
problem
.extend_subgradient(minorants[fidx][minidx].primal.as_ref().unwrap(), vars)
.map(DVector)
.map_err(|e| e.into())
},
)
.map_err(SolverError::Master)?;
// modify moved variables
for (index, val) in newvars.iter().filter_map(|v| v.0.map(|i| (i, v.3))) {
self.cur_y[index] = val;
self.nxt_y[index] = val;
|
| ︙ | ︙ |