1use std::marker::PhantomData;
18
19pub trait ConstraintState {}
21
22pub trait ObjectiveState {}
24
25pub trait ConvexityState {}
27
28pub trait ManifoldState {}
30
31#[derive(Clone, Copy, Debug)]
33pub struct Unconstrained;
34
35#[derive(Clone, Copy, Debug)]
37pub struct Constrained;
38
39#[derive(Clone, Copy, Debug)]
41pub struct SingleObjective;
42
43#[derive(Clone, Copy, Debug)]
45pub struct MultiObjective;
46
47#[derive(Clone, Copy, Debug)]
49pub struct Convex;
50
51#[derive(Clone, Copy, Debug)]
53pub struct NonConvex;
54
55#[derive(Clone, Copy, Debug)]
57pub struct Euclidean;
58
59#[derive(Clone, Copy, Debug)]
61pub struct Riemannian;
62
63#[derive(Clone, Copy, Debug)]
65pub struct Statistical;
66
67impl ConstraintState for Unconstrained {}
69impl ConstraintState for Constrained {}
70
71impl ObjectiveState for SingleObjective {}
72impl ObjectiveState for MultiObjective {}
73
74impl ConvexityState for Convex {}
75impl ConvexityState for NonConvex {}
76
77impl ManifoldState for Euclidean {}
78impl ManifoldState for Riemannian {}
79impl ManifoldState for Statistical {}
80
81#[derive(Clone, Debug)]
106pub struct OptimizationProblem<
107 const DIM: usize,
108 C: ConstraintState = Unconstrained,
109 O: ObjectiveState = SingleObjective,
110 V: ConvexityState = NonConvex,
111 M: ManifoldState = Euclidean,
112> {
113 _constraint: PhantomData<C>,
114 _objective: PhantomData<O>,
115 _convexity: PhantomData<V>,
116 _manifold: PhantomData<M>,
117}
118
119impl<
120 const DIM: usize,
121 C: ConstraintState,
122 O: ObjectiveState,
123 V: ConvexityState,
124 M: ManifoldState,
125 > OptimizationProblem<DIM, C, O, V, M>
126{
127 pub fn new() -> Self {
129 Self {
130 _constraint: PhantomData,
131 _objective: PhantomData,
132 _convexity: PhantomData,
133 _manifold: PhantomData,
134 }
135 }
136
137 pub const fn dimension(&self) -> usize {
139 DIM
140 }
141}
142
143impl<
144 const DIM: usize,
145 C: ConstraintState,
146 O: ObjectiveState,
147 V: ConvexityState,
148 M: ManifoldState,
149 > Default for OptimizationProblem<DIM, C, O, V, M>
150{
151 fn default() -> Self {
152 Self::new()
153 }
154}
155
156impl<const DIM: usize, O: ObjectiveState, V: ConvexityState, M: ManifoldState>
159 OptimizationProblem<DIM, Unconstrained, O, V, M>
160{
161 pub fn with_constraints(self) -> OptimizationProblem<DIM, Constrained, O, V, M> {
163 OptimizationProblem::new()
164 }
165}
166
167impl<const DIM: usize, C: ConstraintState, V: ConvexityState, M: ManifoldState>
168 OptimizationProblem<DIM, C, SingleObjective, V, M>
169{
170 pub fn with_multiple_objectives(self) -> OptimizationProblem<DIM, C, MultiObjective, V, M> {
172 OptimizationProblem::new()
173 }
174}
175
176impl<const DIM: usize, C: ConstraintState, O: ObjectiveState, M: ManifoldState>
177 OptimizationProblem<DIM, C, O, NonConvex, M>
178{
179 pub fn assume_convex(self) -> OptimizationProblem<DIM, C, O, Convex, M> {
181 OptimizationProblem::new()
182 }
183}
184
185impl<const DIM: usize, C: ConstraintState, O: ObjectiveState, V: ConvexityState>
186 OptimizationProblem<DIM, C, O, V, Euclidean>
187{
188 pub fn on_riemannian_manifold(self) -> OptimizationProblem<DIM, C, O, V, Riemannian> {
190 OptimizationProblem::new()
191 }
192
193 pub fn on_statistical_manifold(self) -> OptimizationProblem<DIM, C, O, V, Statistical> {
195 OptimizationProblem::new()
196 }
197}
198
199pub trait HandlesUnconstrained<
201 const DIM: usize,
202 O: ObjectiveState,
203 V: ConvexityState,
204 M: ManifoldState,
205>
206{
207 type Output;
209
210 fn optimize_unconstrained(
212 &self,
213 problem: &OptimizationProblem<DIM, Unconstrained, O, V, M>,
214 ) -> Self::Output;
215}
216
217pub trait HandlesConstrained<
219 const DIM: usize,
220 O: ObjectiveState,
221 V: ConvexityState,
222 M: ManifoldState,
223>
224{
225 type Output;
227
228 fn optimize_constrained(
230 &self,
231 problem: &OptimizationProblem<DIM, Constrained, O, V, M>,
232 ) -> Self::Output;
233}
234
235pub trait RequiresConvex<const DIM: usize, C: ConstraintState, O: ObjectiveState, M: ManifoldState>
237{
238 type Output;
240
241 fn optimize_convex(&self, problem: &OptimizationProblem<DIM, C, O, Convex, M>) -> Self::Output;
243}
244
245pub trait HandlesMultiObjective<
247 const DIM: usize,
248 C: ConstraintState,
249 V: ConvexityState,
250 M: ManifoldState,
251>
252{
253 type Output;
255
256 fn optimize_multiobjective(
258 &self,
259 problem: &OptimizationProblem<DIM, C, MultiObjective, V, M>,
260 ) -> Self::Output;
261}
262
263pub trait HandlesStatistical<
265 const DIM: usize,
266 C: ConstraintState,
267 O: ObjectiveState,
268 V: ConvexityState,
269>
270{
271 type Output;
273
274 fn optimize_statistical(
276 &self,
277 problem: &OptimizationProblem<DIM, C, O, V, Statistical>,
278 ) -> Self::Output;
279}
280
281#[cfg(test)]
282mod tests {
283 use super::*;
284
285 #[test]
286 fn test_problem_creation() {
287 let _problem: OptimizationProblem<
288 10,
289 Unconstrained,
290 SingleObjective,
291 NonConvex,
292 Euclidean,
293 > = OptimizationProblem::new();
294
295 assert_eq!(_problem.dimension(), 10);
296 }
297
298 #[test]
299 fn test_type_state_transitions() {
300 let problem: OptimizationProblem<5, Unconstrained, SingleObjective, NonConvex, Euclidean> =
301 OptimizationProblem::new();
302
303 let _constrained = problem.with_constraints();
305
306 let problem =
308 OptimizationProblem::<5, Unconstrained, SingleObjective, NonConvex, Euclidean>::new();
309 let _multiobjective = problem.with_multiple_objectives();
310
311 let problem =
313 OptimizationProblem::<5, Unconstrained, SingleObjective, NonConvex, Euclidean>::new();
314 let _convex = problem.assume_convex();
315
316 let problem =
318 OptimizationProblem::<5, Unconstrained, SingleObjective, NonConvex, Euclidean>::new();
319 let _riemannian = problem.clone().on_riemannian_manifold();
320 let _statistical = problem.on_statistical_manifold();
321 }
322
323 #[test]
324 fn test_default_construction() {
325 let _problem: OptimizationProblem<3> = OptimizationProblem::default();
326 assert_eq!(_problem.dimension(), 3);
327 }
328}