RsBundle  Check-in [9a0f6816f5]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:FirstOrderProblem returns primal information along minorants.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9a0f6816f581a9e7ac1096d93f345575d8c5fef9
User & Date: fifr 2016-09-30 19:42:04.510
Context
2016-10-01
07:47
vector: Implement `FromIterator` for `DVector`. check-in: b19701a2cb user: fifr tags: trunk
2016-09-30
19:42
FirstOrderProblem returns primal information along minorants. check-in: 9a0f6816f5 user: fifr tags: trunk
19:14
cpx: Update quadratic term when aggregating minorants. check-in: 3386c2a253 user: fifr tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to examples/quadratic.rs.
39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
            c : 3.0,
        }
    }
}

impl<'a> FirstOrderProblem<'a> for QuadraticProblem {
    type Error = io::Error;

    type EvalResult = SimpleEvaluation;

    fn num_variables(&self) -> usize { 2 }

    #[allow(unused_variables)]
    fn evaluate(&'a mut self, fidx : usize, x : &DVector, nullstep_bnd : Real, relprec : Real) -> Result<Self::EvalResult, Self::Error> {
        assert!(fidx == 0);
        let mut objective = self.c;







>
|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
            c : 3.0,
        }
    }
}

impl<'a> FirstOrderProblem<'a> for QuadraticProblem {
    type Error = io::Error;
    type Primal = ();
    type EvalResult = SimpleEvaluation<()>;

    fn num_variables(&self) -> usize { 2 }

    #[allow(unused_variables)]
    fn evaluate(&'a mut self, fidx : usize, x : &DVector, nullstep_bnd : Real, relprec : Real) -> Result<Self::EvalResult, Self::Error> {
        assert!(fidx == 0);
        let mut objective = self.c;
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
        debug!("Evaluation at {}", x);
        debug!("  objective={}", objective);
        debug!("  subgradient={}", g);

        Ok(SimpleEvaluation {
            objective: objective,
            minorants: vec![
                Minorant {
                    constant: objective,
                    linear: g,
                }
            ],
        })
    }
}

fn main() {
    env_logger::init().unwrap();







|


|







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
        debug!("Evaluation at {}", x);
        debug!("  objective={}", objective);
        debug!("  subgradient={}", g);

        Ok(SimpleEvaluation {
            objective: objective,
            minorants: vec![
                (Minorant {
                    constant: objective,
                    linear: g,
                },())
            ],
        })
    }
}

fn main() {
    env_logger::init().unwrap();
Changes to src/firstorderproblem.rs.
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
 *
 * An evaluation returns the function value at the point of evaluation
 * and one or more subgradients.
 *
 * The subgradients (linear minorants) can be obtained by iterating over the result. The
 * subgradients are centered around the point of evaluation.
 */
pub trait Evaluation : IntoIterator<Item=Minorant> {
    /// Return the function value at the point of evaluation.
    fn objective(&self) -> Real;
}


/**
 * Simple standard evaluation result.
 *
 * This result consists of the function value and a list of one or
 * more minorants.
 */
pub struct SimpleEvaluation {
    pub objective : Real,
    pub minorants : Vec<Minorant>,
}

impl IntoIterator for SimpleEvaluation {
    type Item = Minorant;
    type IntoIter = IntoIter<Minorant>;

    fn into_iter(self) -> Self::IntoIter {
        self.minorants.into_iter()
    }
}

impl Evaluation for SimpleEvaluation {
    fn objective(&self) -> Real {
        self.objective
    }
}


/**
 * Trait for implementing a first-order problem description.
 *
 */
pub trait FirstOrderProblem<'a> {
    /// Custom error type for evaluating this oracle.
    type Error : error::Error + 'static;




    /// Custom evaluation result value.
    type EvalResult : Evaluation;

    /// Return the number of variables.
    fn num_variables(&self) -> usize;

    /**
     * Return the lower bounds on the variables.
     *







|









|

|

|


|
|
|






|














>
>
>

|







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
 *
 * An evaluation returns the function value at the point of evaluation
 * and one or more subgradients.
 *
 * The subgradients (linear minorants) can be obtained by iterating over the result. The
 * subgradients are centered around the point of evaluation.
 */
pub trait Evaluation<P> : IntoIterator<Item=(Minorant, P)> {
    /// Return the function value at the point of evaluation.
    fn objective(&self) -> Real;
}


/**
 * Simple standard evaluation result.
 *
 * This result consists of the function value and a list of one or
 * more minorants and associated primal information.
 */
pub struct SimpleEvaluation<P> {
    pub objective : Real,
    pub minorants : Vec<(Minorant, P)>,
}

impl<P> IntoIterator for SimpleEvaluation<P> {
    type Item = (Minorant, P);
    type IntoIter = IntoIter<(Minorant, P)>;

    fn into_iter(self) -> Self::IntoIter {
        self.minorants.into_iter()
    }
}

impl<P> Evaluation<P> for SimpleEvaluation<P> {
    fn objective(&self) -> Real {
        self.objective
    }
}


/**
 * Trait for implementing a first-order problem description.
 *
 */
pub trait FirstOrderProblem<'a> {
    /// Custom error type for evaluating this oracle.
    type Error : error::Error + 'static;

    /// The primal information associated with a minorant.
    type Primal;

    /// Custom evaluation result value.
    type EvalResult : Evaluation<Self::Primal>;

    /// Return the number of variables.
    fn num_variables(&self) -> usize;

    /**
     * Return the lower bounds on the variables.
     *
Changes to src/mcf/problem.rs.
170
171
172
173
174
175
176


177
178
179
180
181
182
183
184
        })
    }
}

impl<'a> FirstOrderProblem<'a> for MMCFProblem {
    type Error = Error;



    type EvalResult = SimpleEvaluation;

    fn num_variables(&self) -> usize { self.lhs.len() }

    fn lower_bounds(&self) -> Option<Vector> {
        Some(Vector::new_sparse(self.lhs.len(), &[], &[]))
    }








>
>
|







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
        })
    }
}

impl<'a> FirstOrderProblem<'a> for MMCFProblem {
    type Error = Error;

    type Primal = ();

    type EvalResult = SimpleEvaluation<()>;

    fn num_variables(&self) -> usize { self.lhs.len() }

    fn lower_bounds(&self) -> Option<Vector> {
        Some(Vector::new_sparse(self.lhs.len(), &[], &[]))
    }

239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
                for elem in &self.lhs[i][fidx] {
                    subg[i] -= elem.val * sol[elem.ind];
                }
            }

            Ok(SimpleEvaluation {
                objective: objective,
                minorants: vec![Minorant { constant: objective, linear: subg }],
            })
        } else {
            let mut objective = self.rhsval;
            let mut sols = Vec::with_capacity(self.nets.len());
            for i in 0..self.nets.len() {
                objective -= try!(self.nets[i].objective());
                sols.push(try!(self.nets[i].get_solution()));
            }

            let mut subg = self.rhs.clone();
            for i in 0..self.lhs.len() {
                for (fidx, flhs) in self.lhs[i].iter().enumerate() {
                    for elem in flhs {
                        subg[i] -= elem.val * sols[fidx][elem.ind];
                    }
                }
            }

            Ok(SimpleEvaluation {
                objective: objective,
                minorants: vec![Minorant { constant: objective, linear: subg }],
            })
        }
    }
}







|




















|




241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
                for elem in &self.lhs[i][fidx] {
                    subg[i] -= elem.val * sol[elem.ind];
                }
            }

            Ok(SimpleEvaluation {
                objective: objective,
                minorants: vec![(Minorant { constant: objective, linear: subg }, ())],
            })
        } else {
            let mut objective = self.rhsval;
            let mut sols = Vec::with_capacity(self.nets.len());
            for i in 0..self.nets.len() {
                objective -= try!(self.nets[i].objective());
                sols.push(try!(self.nets[i].get_solution()));
            }

            let mut subg = self.rhs.clone();
            for i in 0..self.lhs.len() {
                for (fidx, flhs) in self.lhs[i].iter().enumerate() {
                    for elem in flhs {
                        subg[i] -= elem.val * sols[fidx][elem.ind];
                    }
                }
            }

            Ok(SimpleEvaluation {
                objective: objective,
                minorants: vec![(Minorant { constant: objective, linear: subg }, ())],
            })
        }
    }
}
Changes to src/solver.rs.
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
                Ok(r) => r,
                Err(err) => return Err(Error::Eval(Box::new(err))),
            };
            self.cur_vals[i] = result.objective();
            self.cur_val += self.cur_vals[i];

            let mut minorants = result.into_iter();
            if let Some(minorant) = minorants.next() {
                self.cur_mods[i] = minorant.constant;
                self.cur_mod += self.cur_mods[i];
                self.minorants[i].push(MinorantInfo {
                    index: try!(self.master.add_minorant(i, minorant)),
                    multiplier: 0,
                });
            } else {







|







543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
                Ok(r) => r,
                Err(err) => return Err(Error::Eval(Box::new(err))),
            };
            self.cur_vals[i] = result.objective();
            self.cur_val += self.cur_vals[i];

            let mut minorants = result.into_iter();
            if let Some((minorant, _)) = minorants.next() {
                self.cur_mods[i] = minorant.constant;
                self.cur_mod += self.cur_mods[i];
                self.minorants[i].push(MinorantInfo {
                    index: try!(self.master.add_minorant(i, minorant)),
                    multiplier: 0,
                });
            } else {
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
                Err(err) => return Err(Error::Eval(Box::new(err))),
            };

            let fun_ub = result.objective();

            let mut minorants = result.into_iter();
            let mut nxt_minorant = match minorants.next() {
                Some(m) => m,
                None => return Err(Error::NoMinorant)
            };
            let fun_lb = nxt_minorant.constant;

            nxt_lb += fun_lb;
            nxt_ub += fun_ub;
            self.nxt_vals[fidx] = fun_ub;







|







672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
                Err(err) => return Err(Error::Eval(Box::new(err))),
            };

            let fun_ub = result.objective();

            let mut minorants = result.into_iter();
            let mut nxt_minorant = match minorants.next() {
                Some((m, _)) => m,
                None => return Err(Error::NoMinorant)
            };
            let fun_lb = nxt_minorant.constant;

            nxt_lb += fun_lb;
            nxt_ub += fun_ub;
            self.nxt_vals[fidx] = fun_ub;