RsBundle  Check-in [16ede320bb]

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

Overview
Comment:Add possible error handling to master problem methods
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 16ede320bb46620c9710545dc5756f9dba0472c9
User & Date: fifr 2017-11-19 20:30:27.246
Context
2017-11-20
07:55
Add SolverError variants for master and oracle errors. check-in: b0a2986e97 user: fifr tags: trunk
2017-11-19
20:30
Add possible error handling to master problem methods check-in: 16ede320bb user: fifr tags: trunk
2017-11-18
21:42
Use `failure` for error handling. check-in: df7544e94f user: fifr tags: trunk, v0.4.0
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/master/base.rs.
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
    /// Unique index for a minorant.
    type MinorantIndex: Copy + Eq;

    /// Set the number of subproblems.
    fn set_num_subproblems(&mut self, n: usize) -> Result<(), Error>;

    /// Set the lower and upper bounds of the variables.
    fn set_vars(&mut self, nvars: usize, lb: Option<DVector>, ub: Option<DVector>);

    /// Return the current number of minorants of subproblem `fidx`.
    fn num_minorants(&self, fidx: usize) -> usize;

    /// Return the current weight of the quadratic term.
    fn weight(&self) -> Real;

    /// Set the weight of the quadratic term, must be > 0.
    fn set_weight(&mut self, weight: Real);

    /// Set the maximal number of inner iterations.
    fn set_max_updates(&mut self, max_updates: usize);

    /// Return the current number of inner iterations.
    fn cnt_updates(&self) -> usize;

    /// 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]) -> DVector);



    /// 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.







|








|


|










|
>







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
    /// Unique index for a minorant.
    type MinorantIndex: Copy + Eq;

    /// Set the number of subproblems.
    fn set_num_subproblems(&mut self, n: usize) -> Result<(), Error>;

    /// Set the lower and upper bounds of the variables.
    fn set_vars(&mut self, nvars: usize, lb: Option<DVector>, ub: Option<DVector>) -> Result<(), Error>;

    /// Return the current number of minorants of subproblem `fidx`.
    fn num_minorants(&self, fidx: usize) -> usize;

    /// Return the current weight of the quadratic term.
    fn weight(&self) -> Real;

    /// Set the weight of the quadratic term, must be > 0.
    fn set_weight(&mut self, weight: Real) -> Result<(), Error>;

    /// Set the maximal number of inner iterations.
    fn set_max_updates(&mut self, max_updates: usize) -> Result<(), Error>;

    /// Return the current number of inner iterations.
    fn cnt_updates(&self) -> usize;

    /// 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]) -> DVector)
        -> Result<(), Error>;


    /// 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.
72
73
74
75
76
77
78
79
80
81

82
83
84
85
86
87
88
            max_updates: 100,
            cnt_updates: 0,
            need_new_candidate: true,
            master: M::new()?,
        })
    }

    pub fn set_max_updates(&mut self, max_updates: usize) {
        assert!(max_updates > 0);
        self.max_updates = max_updates;

    }

    /**
     * Update box multipliers $\eta$.
     *
     * This function solves the dual problem for fixed aggregated
     * minorant w.r.t. $\eta$. When called, the variable `self.primopt`







|


>







72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
            max_updates: 100,
            cnt_updates: 0,
            need_new_candidate: true,
            master: M::new()?,
        })
    }

    pub fn set_max_updates(&mut self, max_updates: usize) -> Result<(), Error> {
        assert!(max_updates > 0);
        self.max_updates = max_updates;
        Ok(())
    }

    /**
     * Update box multipliers $\eta$.
     *
     * This function solves the dual problem for fixed aggregated
     * minorant w.r.t. $\eta$. When called, the variable `self.primopt`
174
175
176
177
178
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
219


220
221
222
223
224
225
226
impl<M: UnconstrainedMasterProblem> MasterProblem for BoxedMasterProblem<M> {
    type MinorantIndex = M::MinorantIndex;

    fn set_num_subproblems(&mut self, n: usize) -> Result<(), Error> {
        self.master.set_num_subproblems(n)
    }

    fn set_vars(&mut self, n: usize, lb: Option<DVector>, ub: Option<DVector>) {
        assert_eq!(lb.as_ref().map(|x| x.len()).unwrap_or(n), n);
        assert_eq!(ub.as_ref().map(|x| x.len()).unwrap_or(n), n);
        self.lb = lb.unwrap_or_else(|| dvec![NEG_INFINITY; n]);
        self.ub = ub.unwrap_or_else(|| dvec![INFINITY; n]);

    }

    fn num_minorants(&self, fidx: usize) -> usize {
        self.master.num_minorants(fidx)
    }

    fn add_minorant(&mut self, fidx: usize, minorant: Minorant) -> Result<Self::MinorantIndex, Error> {
        self.master.add_minorant(fidx, minorant)
    }

    fn weight(&self) -> Real {
        self.master.weight()
    }

    fn set_weight(&mut self, weight: Real) {
        self.master.set_weight(weight);
    }

    fn add_vars(&mut self,
                bounds: &[(Option<usize>, Real, Real)],
                extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> DVector)

    {
        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));
            self.ub.extend(bounds.iter().filter(|v| v.0.is_none()).map(|x| x.2));
            self.eta.resize(self.lb.len(), 0.0);
            self.need_new_candidate = true;
            let nnew = bounds.iter().filter(|v| v.0.is_none()).count();
            let changed = bounds.iter().filter_map(|v| v.0).collect::<Vec<_>>();
            self.master.add_vars(nnew, &changed, extend_subgradient)


        }
    }

    #[cfg_attr(feature="cargo-clippy", allow(cyclomatic_complexity))]
    fn solve(&mut self, center_value: Real) -> Result<(), Error> {
        debug!("Solve Master");
        debug!("  lb      ={}", self.lb);







|




>














|
|





>













>
>







175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
impl<M: UnconstrainedMasterProblem> MasterProblem for BoxedMasterProblem<M> {
    type MinorantIndex = M::MinorantIndex;

    fn set_num_subproblems(&mut self, n: usize) -> Result<(), Error> {
        self.master.set_num_subproblems(n)
    }

    fn set_vars(&mut self, n: usize, lb: Option<DVector>, ub: Option<DVector>) -> Result<(), Error> {
        assert_eq!(lb.as_ref().map(|x| x.len()).unwrap_or(n), n);
        assert_eq!(ub.as_ref().map(|x| x.len()).unwrap_or(n), n);
        self.lb = lb.unwrap_or_else(|| dvec![NEG_INFINITY; n]);
        self.ub = ub.unwrap_or_else(|| dvec![INFINITY; n]);
        Ok(())
    }

    fn num_minorants(&self, fidx: usize) -> usize {
        self.master.num_minorants(fidx)
    }

    fn add_minorant(&mut self, fidx: usize, minorant: Minorant) -> Result<Self::MinorantIndex, Error> {
        self.master.add_minorant(fidx, minorant)
    }

    fn weight(&self) -> Real {
        self.master.weight()
    }

    fn set_weight(&mut self, weight: Real) -> Result<(), Error> {
        self.master.set_weight(weight)
    }

    fn add_vars(&mut self,
                bounds: &[(Option<usize>, Real, Real)],
                extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> DVector)
        -> Result<(), Error>
    {
        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));
            self.ub.extend(bounds.iter().filter(|v| v.0.is_none()).map(|x| x.2));
            self.eta.resize(self.lb.len(), 0.0);
            self.need_new_candidate = true;
            let nnew = bounds.iter().filter(|v| v.0.is_none()).count();
            let changed = bounds.iter().filter_map(|v| v.0).collect::<Vec<_>>();
            self.master.add_vars(nnew, &changed, extend_subgradient)
        } else {
            Ok(())
        }
    }

    #[cfg_attr(feature="cargo-clippy", allow(cyclomatic_complexity))]
    fn solve(&mut self, center_value: Real) -> Result<(), Error> {
        debug!("Solve Master");
        debug!("  lb      ={}", self.lb);
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
    fn move_center(&mut self, alpha: Real, d: &DVector) {
        self.need_new_candidate = true;
        self.master.move_center(alpha, d);
        self.lb.add_scaled(-alpha, d);
        self.ub.add_scaled(-alpha, d);
    }

    fn set_max_updates(&mut self, max_updates: usize) {
        BoxedMasterProblem::set_max_updates(self, max_updates);
    }

    fn cnt_updates(&self) -> usize {
        self.cnt_updates
    }
}







|
|






319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
    fn move_center(&mut self, alpha: Real, d: &DVector) {
        self.need_new_candidate = true;
        self.master.move_center(alpha, d);
        self.lb.add_scaled(-alpha, d);
        self.ub.add_scaled(-alpha, d);
    }

    fn set_max_updates(&mut self, max_updates: usize) -> Result<(), Error> {
        BoxedMasterProblem::set_max_updates(self, max_updates)
    }

    fn cnt_updates(&self) -> usize {
        self.cnt_updates
    }
}
Changes to src/master/cpx.rs.
109
110
111
112
113
114
115
116
117
118

119
120
121
122
123
124
125
        Ok(())
    }

    fn weight(&self) -> Real {
        self.weight
    }

    fn set_weight(&mut self, weight: Real) {
        assert!(weight > 0.0);
        self.weight = weight;

    }

    fn num_minorants(&self, fidx: usize) -> usize {
        self.minorants[fidx].len()
    }

    fn add_minorant(&mut self, fidx: usize, minorant: Minorant) -> Result<usize, Error> {







|


>







109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
        Ok(())
    }

    fn weight(&self) -> Real {
        self.weight
    }

    fn set_weight(&mut self, weight: Real) -> Result<(), Error> {
        assert!(weight > 0.0);
        self.weight = weight;
        Ok(())
    }

    fn num_minorants(&self, fidx: usize) -> usize {
        self.minorants[fidx].len()
    }

    fn add_minorant(&mut self, fidx: usize, minorant: Minorant) -> Result<usize, Error> {
149
150
151
152
153
154
155

156
157
158
159
160
161
162
        }
    }

    fn add_vars(&mut self,
                nnew: usize,
                changed: &[usize],
                extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> DVector)

    {
        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);







>







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
        }
    }

    fn add_vars(&mut self,
                nnew: usize,
                changed: &[usize],
                extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> DVector)
        -> Result<(), Error>
    {
        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);
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197


198
199
200
201
202
203
204
                    m.linear.extend_from_slice(&new_subg[changed.len()..]);
                }
            }
        }

        // update qterm
        if self.force_update {
            return;
        }
        for (fidx_i, mins_i) in self.minorants.iter().enumerate() {
            for (i, m_i) in mins_i.iter().enumerate() {
                let idx_i = self.min2index[fidx_i][i];
                for (fidx_j, mins_j) in self.minorants.iter().enumerate() {
                    for (j, m_j) in mins_j.iter().enumerate() {
                        let idx_j = self.min2index[fidx_j][j];
                        if idx_i <= idx_j {
                            let x: Real = (nnewvars..noldvars).map(|k| m_i.linear[k] * m_j.linear[k]).sum();
                            self.qterm[idx_i][idx_j] += x;
                            self.qterm[idx_j][idx_i] = self.qterm[idx_i][idx_j];
                        }
                    }
                }
            }
        }

        // WORST CASE: DO THIS
        // self.force_update = true;


    }

    fn solve(&mut self, eta: &DVector, _fbound: Real, _augbound: Real, _relprec: Real) -> Result<(), Error> {
        if self.force_update || !self.updateinds.is_empty() {
            try!(self.init_qp());
        }








|



















>
>







173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
                    m.linear.extend_from_slice(&new_subg[changed.len()..]);
                }
            }
        }

        // update qterm
        if self.force_update {
            return Ok(());
        }
        for (fidx_i, mins_i) in self.minorants.iter().enumerate() {
            for (i, m_i) in mins_i.iter().enumerate() {
                let idx_i = self.min2index[fidx_i][i];
                for (fidx_j, mins_j) in self.minorants.iter().enumerate() {
                    for (j, m_j) in mins_j.iter().enumerate() {
                        let idx_j = self.min2index[fidx_j][j];
                        if idx_i <= idx_j {
                            let x: Real = (nnewvars..noldvars).map(|k| m_i.linear[k] * m_j.linear[k]).sum();
                            self.qterm[idx_i][idx_j] += x;
                            self.qterm[idx_j][idx_i] = self.qterm[idx_i][idx_j];
                        }
                    }
                }
            }
        }

        // WORST CASE: DO THIS
        // self.force_update = true;

        Ok(())
    }

    fn solve(&mut self, eta: &DVector, _fbound: Real, _augbound: Real, _relprec: Real) -> Result<(), Error> {
        if self.force_update || !self.updateinds.is_empty() {
            try!(self.init_qp());
        }

Changes to src/master/minimal.rs.
83
84
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
        }
    }

    fn weight(&self) -> Real {
        self.weight
    }

    fn set_weight(&mut self, weight: Real) {
        assert!(weight > 0.0);
        self.weight = weight;

    }

    fn num_minorants(&self, fidx: usize) -> usize {
        assert_eq!(fidx, 0);
        self.minorants.len()
    }








|


>







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
        }
    }

    fn weight(&self) -> Real {
        self.weight
    }

    fn set_weight(&mut self, weight: Real) -> Result<(), Error> {
        assert!(weight > 0.0);
        self.weight = weight;
        Ok(())
    }

    fn num_minorants(&self, fidx: usize) -> usize {
        assert_eq!(fidx, 0);
        self.minorants.len()
    }

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
        Ok(self.minorants.len() - 1)
    }

    fn add_vars(&mut self,
                nnew: usize,
                changed: &[usize],
                extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> DVector)

    {
        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()..]);
            }
        }


    }

    #[allow(unused_variables)]
    fn solve(&mut self, eta: &DVector, fbound: Real, augbound: Real, relprec: Real) -> Result<(), Error> {
        for (i, m) in self.minorants.iter().enumerate() {
            debug!("  {}:min[{},{}] = {}", i, 0, 0, m);
        }







>














>
>







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
        Ok(self.minorants.len() - 1)
    }

    fn add_vars(&mut self,
                nnew: usize,
                changed: &[usize],
                extend_subgradient: &mut FnMut(usize, Self::MinorantIndex, &[usize]) -> DVector)
        -> Result<(), Error>
    {
        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()..]);
            }
        }

        Ok(())
    }

    #[allow(unused_variables)]
    fn solve(&mut self, eta: &DVector, fbound: Real, augbound: Real, relprec: Real) -> Result<(), Error> {
        for (i, m) in self.minorants.iter().enumerate() {
            debug!("  {}:min[{},{}] = {}", i, 0, 0, m);
        }
Changes to src/master/unconstrained.rs.
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
    /// Set the number of subproblems (different function models.)
    fn set_num_subproblems(&mut self, n: usize) -> Result<(), Error>;

    /// Return the current weight.
    fn weight(&self) -> Real;

    /// Set the weight of the quadratic term, must be > 0.
    fn set_weight(&mut self, weight: Real);

    /// Return the number of minorants of subproblem `fidx`.
    fn num_minorants(&self, fidx: usize) -> usize;

    /// Add a new minorant to the model.
    fn add_minorant(&mut self, fidx: usize, minorant: Minorant) -> Result<Self::MinorantIndex, Error>;

    /// Add or move some variables.
    ///
    /// 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]) -> DVector);


    /// Solve the master problem.
    fn solve(&mut self, eta: &DVector, fbound: Real, augbound: Real, relprec: Real) -> Result<(), Error>;

    /// Return the current dual optimal solution.
    fn dualopt(&self) -> &DVector;








|















|
>







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
    /// Set the number of subproblems (different function models.)
    fn set_num_subproblems(&mut self, n: usize) -> Result<(), Error>;

    /// Return the current weight.
    fn weight(&self) -> Real;

    /// Set the weight of the quadratic term, must be > 0.
    fn set_weight(&mut self, weight: Real) -> Result<(), Error>;

    /// Return the number of minorants of subproblem `fidx`.
    fn num_minorants(&self, fidx: usize) -> usize;

    /// Add a new minorant to the model.
    fn add_minorant(&mut self, fidx: usize, minorant: Minorant) -> Result<Self::MinorantIndex, Error>;

    /// Add or move some variables.
    ///
    /// 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]) -> DVector)
        -> Result<(), Error>;

    /// Solve the master problem.
    fn solve(&mut self, eta: &DVector, fbound: Real, augbound: Real, relprec: Real) -> Result<(), Error>;

    /// Return the current dual optimal solution.
    fn dualopt(&self) -> &DVector;

Changes to src/solver.rs.
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
            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)
                                         .unwrap()
                                 });
            // 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;
                self.nxt_d[index] = 0.0;
            }
            // add new variables







|







632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
            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)
                                         .unwrap()
                                 })?;
            // 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;
                self.nxt_d[index] = 0.0;
            }
            // add new variables
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

        if let Some(ref x) = lb {
            if x.len() != self.problem.num_variables() {
                return Err(SolverError::Dimension.into());
            }
        }

        try!(self.master.set_num_subproblems(m));
        self.master.set_vars(self.problem.num_variables(), lb, ub);
        self.master.set_max_updates(self.params.max_updates);

        self.minorants = Vec::with_capacity(m);
        for _ in 0..m {
            self.minorants.push(vec![]);
        }

        self.cur_val = 0.0;







|
|
|







723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739

        if let Some(ref x) = lb {
            if x.len() != self.problem.num_variables() {
                return Err(SolverError::Dimension.into());
            }
        }

        self.master.set_num_subproblems(m)?;
        self.master.set_vars(self.problem.num_variables(), lb, ub)?;
        self.master.set_max_updates(self.params.max_updates)?;

        self.minorants = Vec::with_capacity(m);
        for _ in 0..m {
            self.minorants.push(vec![]);
        }

        self.cur_val = 0.0;
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
        // subgradient.
        //
        // We could compute that subgradient directly by
        // adding up the initial minorants, but this would not include
        // the eta terms. However, this is a heuristic anyway because
        // we assume an initial weight of 1.0, which, in general, will
        // *not* be the initial weight for the first iteration.
        self.master.set_weight(1.0);
        try!(self.master.solve(self.cur_val));
        self.sgnorm = self.master.get_dualoptnorm2().sqrt();

        // Compute the real initial weight.
        let state = current_state!(self, Step::Term);
        let new_weight = self.weighter.weight(&state, &self.params);
        self.master.set_weight(new_weight);

        debug!("Init master completed");

        Ok(())
    }









|






|







762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
        // subgradient.
        //
        // We could compute that subgradient directly by
        // adding up the initial minorants, but this would not include
        // the eta terms. However, this is a heuristic anyway because
        // we assume an initial weight of 1.0, which, in general, will
        // *not* be the initial weight for the first iteration.
        self.master.set_weight(1.0)?;
        try!(self.master.solve(self.cur_val));
        self.sgnorm = self.master.get_dualoptnorm2().sqrt();

        // Compute the real initial weight.
        let state = current_state!(self, Step::Term);
        let new_weight = self.weighter.weight(&state, &self.params);
        self.master.set_weight(new_weight)?;

        debug!("Init master completed");

        Ok(())
    }


828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847

848
849
850
851
852
853
854
855

856
857
858
859
860
861
862
                });
            }
        }
        Ok(())
    }

    /// Perform a descent step.
    fn descent_step(&mut self) {
        let new_weight = self.weighter.weight(&current_state!(self, Step::Descent), &self.params);
        self.master.set_weight(new_weight);
        self.cnt_descent += 1;
        swap(&mut self.cur_y, &mut self.nxt_y);
        swap(&mut self.cur_val, &mut self.nxt_val);
        swap(&mut self.cur_mod, &mut self.nxt_mod);
        swap(&mut self.cur_vals, &mut self.nxt_vals);
        swap(&mut self.cur_mods, &mut self.nxt_mods);
        self.master.move_center(1.0, &self.nxt_d);
        debug!("Descent Step");
        debug!("  dir ={}", self.nxt_d);
        debug!("  newy={}", self.cur_y);

    }

    /// Perform a null step.
    fn null_step(&mut self) {
        let new_weight = self.weighter.weight(&current_state!(self, Step::Null), &self.params);
        self.master.set_weight(new_weight);
        self.cnt_null += 1;
        debug!("Null Step");

    }

    /// Perform one bundle iteration.
    #[cfg_attr(feature = "cargo-clippy", allow(collapsible_if))]
    pub fn step(&mut self) -> Result<Step, Error> {
        self.iterinfos.clear();








|

|










>



|

|


>







828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
                });
            }
        }
        Ok(())
    }

    /// Perform a descent step.
    fn descent_step(&mut self) -> Result<(), Error> {
        let new_weight = self.weighter.weight(&current_state!(self, Step::Descent), &self.params);
        self.master.set_weight(new_weight)?;
        self.cnt_descent += 1;
        swap(&mut self.cur_y, &mut self.nxt_y);
        swap(&mut self.cur_val, &mut self.nxt_val);
        swap(&mut self.cur_mod, &mut self.nxt_mod);
        swap(&mut self.cur_vals, &mut self.nxt_vals);
        swap(&mut self.cur_mods, &mut self.nxt_mods);
        self.master.move_center(1.0, &self.nxt_d);
        debug!("Descent Step");
        debug!("  dir ={}", self.nxt_d);
        debug!("  newy={}", self.cur_y);
        Ok(())
    }

    /// Perform a null step.
    fn null_step(&mut self) -> Result<(), Error> {
        let new_weight = self.weighter.weight(&current_state!(self, Step::Null), &self.params);
        self.master.set_weight(new_weight)?;
        self.cnt_null += 1;
        debug!("Null Step");
        Ok(())
    }

    /// Perform one bundle iteration.
    #[cfg_attr(feature = "cargo-clippy", allow(collapsible_if))]
    pub fn step(&mut self) -> Result<Step, Error> {
        self.iterinfos.clear();

953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
        debug!("  cur_val    ={}", self.cur_val);
        debug!("  nxt_mod    ={}", self.nxt_mod);
        debug!("  nxt_ub     ={}", self.nxt_val);
        debug!("  descent_bnd={}", descent_bnd);

        // do a descent step or null step
        if nxt_ub <= descent_bnd {
            self.descent_step();
            Ok(Step::Descent)
        } else {
            self.null_step();
            Ok(Step::Null)
        }
    }

    /**
     * Return the bound on the function value that enforces a
     * nullstep.







|


|







955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
        debug!("  cur_val    ={}", self.cur_val);
        debug!("  nxt_mod    ={}", self.nxt_mod);
        debug!("  nxt_ub     ={}", self.nxt_val);
        debug!("  descent_bnd={}", descent_bnd);

        // do a descent step or null step
        if nxt_ub <= descent_bnd {
            self.descent_step()?;
            Ok(Step::Descent)
        } else {
            self.null_step()?;
            Ok(Step::Null)
        }
    }

    /**
     * Return the bound on the function value that enforces a
     * nullstep.