14
15
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
14
15
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
|
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
-
-
|
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
//! An asynchronous first-order oracle.
use crate::{Aggregatable, DVector, Minorant, Real};
use crossbeam::channel::{SendError, Sender};
use crossbeam::channel::Sender;
use std::sync::Arc;
/// Evaluation result.
///
/// The result of an evaluation is new information to be made
/// available to the solver and the master problem. There are
/// essentially two types of information:
///
/// 1. The (exact) function value of a sub-function at some point.
/// 2. A minorant of some sub-function.
#[derive(Debug)]
pub enum EvalResult<I, P> {
/// The objective value at some point.
ObjectiveValue { index: I, value: Real },
/// A minorant with an associated primal.
Minorant { index: I, minorant: Minorant, primal: P },
}
/// Channel to send evaluation results to.
//pub type ResultSender<I, P, E> = Sender<Result<EvalResult<I, P>, E>>;
pub struct ResultSender<I, P, E> {
index: I,
tx: Sender<Result<EvalResult<I, P>, E>>,
}
impl<I, P, E> ResultSender<I, P, E>
pub trait ResultSender<P>: Send
where
I: Clone,
P: FirstOrderProblem,
{
pub fn new(index: I, tx: Sender<Result<EvalResult<I, P>, E>>) -> Self {
ResultSender { index, tx }
}
pub fn objective(&self, value: Real) -> Result<(), SendError<Result<EvalResult<I, P>, E>>> {
type Err: std::error::Error + Send;
/// Send a new objective `value`.
fn objective(&self, value: Real) -> Result<(), Self::Err>;
self.tx.send(Ok(EvalResult::ObjectiveValue {
index: self.index.clone(),
value,
}))
}
pub fn minorant(&self, minorant: Minorant, primal: P) -> Result<(), SendError<Result<EvalResult<I, P>, E>>> {
/// Send a new `minorant` with associated `primal`.
fn minorant(&self, minorant: Minorant, primal: P::Primal) -> Result<(), Self::Err>;
self.tx.send(Ok(EvalResult::Minorant {
index: self.index.clone(),
minorant,
primal,
}))
}
pub fn error(&self, err: E) -> Result<(), SendError<Result<EvalResult<I, P>, E>>> {
/// Send an error message.
fn error(&self, err: P::Err) -> Result<(), Self::Err>;
self.tx.send(Err(err))
}
}
/// Problem update information.
///
/// The solver calls the `update` method of the problem regularly.
/// This method can modify the problem by adding (or moving)
/// variables. The possible updates are encoded in this type.
|
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
-
-
-
-
-
-
+
-
+
+
|
/// Start the evaluation of the i^th subproblem at the given point.
///
/// The results of the evaluation should be passed to the provided channel.
/// In order to work correctly, the results must contain (an upper bound on)
/// the objective value at $y$ as well as at least one subgradient centered
/// at $y$ eventually.
fn evaluate<I: Send + Copy + 'static>(
&mut self,
i: usize,
y: Arc<DVector>,
tx: ResultSender<I, Self::Primal, Self::Err>,
) -> Result<(), Self::Err>
fn evaluate<S>(&mut self, i: usize, y: Arc<DVector>, tx: S) -> Result<(), Self::Err>
where
I: Send + 'static;
S: ResultSender<Self> + 'static,
Self: Sized;
/// Called to update the problem.
///
/// This method is called regularly by the solver. The problem should send problem update
/// information (e.g. adding new variables) to the provided channel.
///
/// The updates might be generated asynchronously.
|