1
2
3
4
5
6
7
8
9
10
11
12
13
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
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//! Mathematical optimization
//!
//!
//! This module provides tools for mathematical optimization, which can be used to [tighten cycle representatives](https://www.frontiersin.org/articles/10.3389/frai.2021.681117/full).
//!
//!
use crateKeyValGet;
use crateSolutionL1;
use Debug;
use Hash;
use ToPrimitive;
/// This conditionally includes a module which uses the Gurobi solver
///
/// The Gurobi solver is a powerful optimization engine that can be used to solve linear programming problems efficiently. It requires a license and some setup, but it can significantly speed up optimization tasks.
///
/// Minimize `c' y` subject to `y = |Ax + b|`
///
/// This function solves a problem of form
///
/// ```text
/// minimize c' |y|
/// subject to y = Ax + b
/// |y| is the entry-wise absolute value of y
/// y and x are unconstrained continuous variables
/// ```
///
/// We solve this problem by solving the following equivalent linear programming problem:
///
/// ```text
/// minimize c' y
/// subject to y >= + Ax + b
/// y >= - Ax - b
/// y and x are unconstrained continuous variables
/// ```
///
/// Arguments:
///
/// - `a`: function that consumes `k` and returns the `k`th column of `A`; order of entries does not matter
/// - `b`: the vector `b`, represented as an iterator over the nonzero entries; entries can by any type that implements `KeyValGet< Key = Key, Val = Coefficient >`, where `Coefficient` implements `ToPrimitive`; order does not matter, but $b$ should contain no repeat entries
/// - `c`: the vector `c`, represented as a function that consumes `i` and returns `c[i]`. We require the coefficients of `c` to be nonnegative.
/// - `column_indices`: iterator that runs over the column indices of `A`; order does not matter
/// - `verbose`: if true, then print the progress of the optimization
///
/// Returns:
///
/// An [SolutionL1]
///
/// # Examples
///
/// ```
/// // Minimize the l1 norm of
/// // | 1 | | 2 |
/// // | 1 | * x + | 2 |
///
/// use oat_rust::utilities::optimization::minimize_l1::minimize_l1;
///
/// let constraint_data = vec![ vec![ (0,1.), (1,1.) ] ];
/// let a = |i: & usize | -> Vec<(usize,f64)> { constraint_data[*i].clone() }; // the matrix 2x1 matrix [1; 1]
/// let b = vec![ (0usize,2f64), (1usize,2f64) ]; // the vector [2, 2]
/// let c = |x: & usize| -> f64 { 1.0 }; // the vector [1, 1]
/// let column_indices = vec![0];
/// let verbose = false;
///
/// let solution = minimize_l1( a.clone(),b.clone(),c.clone(), column_indices, verbose).unwrap();
///
/// println!("{:?}", solution);
/// assert_eq!( solution.x(), &vec![(0,-2.0)] );
/// assert_eq!( solution.b(), &b );
/// assert_eq!( solution.y(), &Vec::<(usize,f64)>::new() );
/// assert_eq!( solution.cost_b(), &4.0 );
/// assert_eq!( solution.cost_y(), &0.0 );
/// ```
///
/// ```
/// /// Minimize the l1 norm of
/// /// ```
/// /// | 1 | | 1 |
/// /// | 1 | * x + | 1 |
/// /// | 1 | | 0 |
///
/// use oat_rust::utilities::optimization::minimize_l1::minimize_l1;
///
/// let constraint_data = vec![ vec![ (0,1.), (1,1.), (2,1.), ] ];
/// let a = |i: & usize | -> Vec<(usize,f64)> { constraint_data[*i].clone() };
/// let b = vec![ (0,1.), (1,1.), ];
/// let c = |x: & usize| -> f64 { 1.0 };
/// let column_indices = vec![0];
/// let verbose = false;
///
/// let solution = minimize_l1( a.clone(),b.clone(),c.clone(), column_indices, verbose).unwrap();
///
/// println!("{:?}", solution);
/// assert_eq!( solution.x(), &vec![(0,-1.0)] );
/// assert_eq!( solution.b(), &b );
/// assert_eq!( solution.y(), &vec![(2,-1.0)] );
/// assert_eq!( solution.cost_b(), &2.0 );
/// assert_eq!( solution.cost_y(), &1.0 );
/// ```