summaryrefslogtreecommitdiffstats
path: root/core/src/solving.rs
diff options
context:
space:
mode:
authorMinijackson <minijackson@riseup.net>2022-12-22 12:19:59 +0100
committerMinijackson <minijackson@riseup.net>2022-12-22 12:19:59 +0100
commit92a02c34628343153b33602eae00cef46e28d191 (patch)
tree8622ec528d24e456be22d984d93aa9bcafc97399 /core/src/solving.rs
downloaddiaphragm-92a02c34628343153b33602eae00cef46e28d191.tar.gz
diaphragm-92a02c34628343153b33602eae00cef46e28d191.zip
WIP
Diffstat (limited to 'core/src/solving.rs')
-rw-r--r--core/src/solving.rs279
1 files changed, 279 insertions, 0 deletions
diff --git a/core/src/solving.rs b/core/src/solving.rs
new file mode 100644
index 0000000..c7e94ba
--- /dev/null
+++ b/core/src/solving.rs
@@ -0,0 +1,279 @@
1use super::core_shapes::*;
2use super::styles::*;
3use super::text::*;
4use super::types::{Bool, Float};
5
6#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
7pub struct VariableHandle(usize);
8
9impl VariableHandle {
10 pub fn new(id: usize) -> Self {
11 Self(id)
12 }
13
14 pub fn id(&self) -> usize {
15 self.0
16 }
17}
18
19/*
20pub trait VariableFloat<'a> {
21 fn id(&self) -> usize;
22 fn dyn_clone(&self) -> Box<dyn VariableFloat<'a> + 'a>;
23
24 fn eq(&self, other: &dyn VariableFloat) -> Bool<'a>;
25 fn neq(&self, other: &dyn VariableFloat) -> Bool<'a>;
26 fn gt(&self, other: &dyn VariableFloat) -> Bool<'a>;
27 fn ge(&self, other: &dyn VariableFloat) -> Bool<'a>;
28 fn lt(&self, other: &dyn VariableFloat) -> Bool<'a>;
29 fn le(&self, other: &dyn VariableFloat) -> Bool<'a>;
30
31 fn add(&self, other: &dyn VariableFloat) -> Float<'a>;
32 fn sub(&self, other: &dyn VariableFloat) -> Float<'a>;
33 fn mul(&self, other: &dyn VariableFloat) -> Float<'a>;
34 fn div(&self, other: &dyn VariableFloat) -> Float<'a>;
35
36 fn neg(&self) -> Float<'a>;
37}
38
39pub trait VariableBool<'a> {
40 fn id(&self) -> usize;
41 fn dyn_clone(&self) -> Box<dyn VariableBool<'a> + 'a>;
42
43 fn eq(&self, other: &dyn VariableBool) -> Bool<'a>;
44 fn neq(&self, other: &dyn VariableBool) -> Bool<'a>;
45
46 fn and(&self, other: &dyn VariableBool) -> Bool<'a>;
47 fn or(&self, other: &dyn VariableBool) -> Bool<'a>;
48
49 fn not(&self) -> Bool<'a>;
50}
51*/
52
53pub trait SolverContext {
54 fn solve<'a>(&'a self) -> Box<dyn SolverModel + 'a>;
55 fn constrain(&mut self, assertion: Bool);
56
57 // Floats
58
59 fn new_free_float(&mut self) -> Float;
60 fn new_fixed_float(&mut self, value: f64) -> Float;
61
62 fn float_add(&mut self, values: &[Float]) -> Float;
63 fn float_sub(&mut self, values: &[Float]) -> Float;
64 fn float_mul(&mut self, values: &[Float]) -> Float;
65 fn float_div(&mut self, lhs: Float, rhs: Float) -> Float;
66 fn float_neg(&mut self, value: Float) -> Float;
67
68 fn float_eq(&mut self, lhs: Float, rhs: Float) -> Bool;
69 fn float_ne(&mut self, lhs: Float, rhs: Float) -> Bool;
70 fn float_gt(&mut self, lhs: Float, rhs: Float) -> Bool;
71 fn float_ge(&mut self, lhs: Float, rhs: Float) -> Bool;
72 fn float_lt(&mut self, lhs: Float, rhs: Float) -> Bool;
73 fn float_le(&mut self, lhs: Float, rhs: Float) -> Bool;
74
75 fn float_max(&mut self, values: &[Float]) -> Float {
76 let result = self.new_free_float();
77
78 for (index, &candidate) in values.iter().enumerate() {
79 let comparisons: Vec<_> = values
80 .iter()
81 .enumerate()
82 .filter(|(other_index, _)| *other_index != index)
83 .map(|(_, &other)| self.float_ge(candidate, other))
84 .collect();
85
86 let premise = self.bool_and(&comparisons);
87 let conclusion = self.float_eq(candidate, result);
88 let implication = self.bool_implies(premise, conclusion);
89 self.constrain(implication);
90 }
91
92 result
93 }
94
95 fn float_min(&mut self, values: &[Float]) -> Float {
96 let result = self.new_free_float();
97
98 for (index, &candidate) in values.iter().enumerate() {
99 let comparisons: Vec<_> = values
100 .iter()
101 .enumerate()
102 .filter(|(other_index, _)| *other_index != index)
103 .map(|(_, &other)| self.float_le(candidate, other))
104 .collect();
105
106 let premise = self.bool_and(&comparisons);
107 let conclusion = self.float_eq(candidate, result);
108 let implication = self.bool_implies(premise, conclusion);
109 self.constrain(implication);
110 }
111
112 result
113 }
114
115 // Bools
116
117 fn new_free_bool(&mut self) -> Bool;
118 fn new_fixed_bool(&mut self, value: bool) -> Bool;
119
120 fn bool_eq(&mut self, lhs: Bool, rhs: Bool) -> Bool;
121 fn bool_ne(&mut self, lhs: Bool, rhs: Bool) -> Bool;
122
123 fn bool_and(&mut self, values: &[Bool]) -> Bool;
124 fn bool_or(&mut self, values: &[Bool]) -> Bool;
125 fn bool_not(&mut self, value: Bool) -> Bool;
126
127 fn bool_implies(&mut self, lhs: Bool, rhs: Bool) -> Bool;
128}
129
130pub trait SolverModel {
131 fn eval_float(&self, f: Float) -> Option<f64>;
132 fn eval_bool(&self, b: Bool) -> Option<bool>;
133}
134
135/*
136pub trait Solver {
137 fn constrain(&mut self, assertion: &Bool);
138 fn solve(&self) -> Box<dyn SolverModel>;
139}
140*/
141
142use super::types::*;
143
144pub trait Constrainable {
145 type Fixated;
146
147 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated>;
148}
149
150impl Constrainable for Float {
151 type Fixated = f64;
152
153 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
154 model.eval_float(*self)
155 }
156
157 /*
158 fn fixate(&self, model: &Model) -> Self::Fixated {
159 match self {
160 Float::Defined(float) => *float,
161 Float::Constrained(variable) => {
162 let (num, den) = model
163 .eval::<z3::ast::Real>(variable)
164 .expect("Couldn't eval variable")
165 .as_real()
166 .expect("Couldn't get value from variable");
167
168 num as f64 / den as f64
169 }
170 Float::Undefined => panic!("Undefined float"),
171 }
172 }
173 */
174}
175
176impl Constrainable for Bounds {
177 type Fixated = DefinedBounds;
178
179 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
180 Some(DefinedBounds {
181 top: self.top.fixate(model)?,
182 left: self.left.fixate(model)?,
183 width: self.width.fixate(model)?,
184 height: self.height.fixate(model)?,
185 })
186 }
187}
188
189impl Constrainable for StrokeStyle {
190 type Fixated = DefinedStrokeStyle;
191
192 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
193 let dash = match &self.dash {
194 Some(dash) => Some(dash.fixate(model)?),
195 None => None,
196 };
197
198 Some(DefinedStrokeStyle {
199 pattern: self.pattern.clone(),
200 dash,
201 line_width: self.line_width.fixate(model)?,
202 })
203 }
204}
205
206impl Constrainable for DashStyle {
207 type Fixated = DefinedDashStyle;
208
209 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
210 Some(DefinedDashStyle {
211 dashes: self
212 .dashes
213 .iter()
214 .map(|value| value.fixate(model))
215 .collect::<Option<_>>()?,
216 offset: self.offset.fixate(model)?,
217 })
218 }
219}
220
221impl Constrainable for ShapeContext {
222 type Fixated = DefinedShapeContext;
223
224 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
225 Some(DefinedShapeContext {
226 bounds: self.bounds.fixate(model)?,
227 fill: self.fill.clone(),
228 stroke: self.stroke.fixate(model)?,
229 })
230 }
231}
232
233impl Constrainable for Point2D {
234 type Fixated = DefinedPoint2D;
235
236 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
237 Some(DefinedPoint2D {
238 x: self.x.fixate(model)?,
239 y: self.y.fixate(model)?,
240 })
241 }
242}
243
244impl Constrainable for FontDescription {
245 type Fixated = DefinedFontDescription;
246
247 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
248 Some(DefinedFontDescription {
249 family: self.family.clone(),
250 style: self.style,
251 weight: self.weight,
252 size: self.size.fixate(&*model)?,
253 })
254 }
255}
256
257impl Constrainable for Text {
258 type Fixated = DefinedText;
259
260 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
261 Some(DefinedText {
262 content: self.content.clone(),
263 font: self.font.fixate(&*model)?,
264 })
265 }
266}
267
268impl Constrainable for StraightPath {
269 type Fixated = DefinedStraightPath;
270
271 fn fixate(&self, model: &dyn SolverModel) -> Option<Self::Fixated> {
272 let points: Option<_> = self
273 .points
274 .iter()
275 .map(|point| point.fixate(model))
276 .collect();
277 Some(DefinedStraightPath { points: points? })
278 }
279}