1use std::ops::{Add, Div, Mul, Neg};
2
3use get_size2::GetSize;
4use rand::{Rng, RngExt};
5
6use crate::{
7 Expression, Type, TypeError, Val,
8 grammar::{BooleanExpr, IntegerExpr, NaturalExpr},
9};
10
11pub type Float = f64;
13
14#[derive(Debug, Clone, GetSize)]
16pub enum FloatExpr<V>
17where
18 V: Clone,
19{
20 Const(Float),
25 Var(V),
27 Nat(NaturalExpr<V>),
29 Int(IntegerExpr<V>),
31 Rand(Box<(FloatExpr<V>, FloatExpr<V>)>),
36 Opposite(Box<FloatExpr<V>>),
41 Sum(Vec<FloatExpr<V>>),
43 Product(Vec<FloatExpr<V>>),
45 Div(Box<(FloatExpr<V>, FloatExpr<V>)>),
47 Min(Box<(FloatExpr<V>, FloatExpr<V>)>),
52 Max(Box<(FloatExpr<V>, FloatExpr<V>)>),
54 Ite(Box<(BooleanExpr<V>, FloatExpr<V>, FloatExpr<V>)>),
61}
62
63impl<V> FloatExpr<V>
64where
65 V: Copy,
66{
67 pub fn is_constant(&self) -> bool {
69 match self {
70 FloatExpr::Const(_) => true,
71 FloatExpr::Var(_) | FloatExpr::Rand(_) => false,
72 FloatExpr::Nat(natural_expr) => natural_expr.is_constant(),
73 FloatExpr::Int(integer_expr) => integer_expr.is_constant(),
74
75 FloatExpr::Opposite(float_expr) => float_expr.is_constant(),
76 FloatExpr::Sum(float_exprs) | FloatExpr::Product(float_exprs) => {
77 float_exprs.iter().all(FloatExpr::is_constant)
78 }
79 FloatExpr::Div(args) | FloatExpr::Min(args) | FloatExpr::Max(args) => {
80 let (lhs, rhs) = args.as_ref();
81 lhs.is_constant() && rhs.is_constant()
82 }
83 FloatExpr::Ite(args) => {
84 let (ite, lhs, rhs) = args.as_ref();
85 ite.is_constant() && lhs.is_constant() && rhs.is_constant()
86 }
87 }
88 }
89
90 pub fn eval<R: Rng>(&self, vars: &dyn Fn(V) -> Val, mut rng: Option<&mut R>) -> Float {
99 match self {
100 FloatExpr::Const(float) => *float,
101 FloatExpr::Var(var) => {
102 if let Val::Float(float) = vars(*var) {
103 float
104 } else {
105 panic!("type mismatch: expected float variable")
106 }
107 }
108 FloatExpr::Nat(natural_expr) => natural_expr.eval(vars, rng) as f64,
110 FloatExpr::Int(integer_expr) => integer_expr.eval(vars, rng) as f64,
112 FloatExpr::Rand(bounds) => {
113 let (lower_bound_expr, upper_bound_expr) = bounds.as_ref();
114 let lower_bound = lower_bound_expr.eval(vars, rng.as_deref_mut());
115 let upper_bound = upper_bound_expr.eval(vars, rng.as_deref_mut());
116 rng.as_mut()
117 .expect("rng")
118 .random_range(lower_bound..upper_bound)
119 }
120 FloatExpr::Opposite(float_expr) => -float_expr.eval(vars, rng),
121 FloatExpr::Sum(float_exprs) => float_exprs
122 .iter()
123 .map(|expr| expr.eval(vars, rng.as_deref_mut()))
124 .sum(),
125 FloatExpr::Product(float_exprs) => float_exprs
126 .iter()
127 .map(|expr| expr.eval(vars, rng.as_deref_mut()))
128 .product(),
129 FloatExpr::Div(args) => {
130 let (lhs_expr, rhs_expr) = args.as_ref();
131 let lhs = lhs_expr.eval(vars, rng.as_deref_mut());
132 let rhs = rhs_expr.eval(vars, rng);
133 lhs / rhs
134 }
135 FloatExpr::Ite(args) => {
136 let (ite, lhs, rhs) = args.as_ref();
137 if ite.eval(vars, rng.as_deref_mut()) {
138 lhs.eval(vars, rng)
139 } else {
140 rhs.eval(vars, rng)
141 }
142 }
143 FloatExpr::Min(args) => {
144 let (lhs_expr, rhs_expr) = args.as_ref();
145 let lhs = lhs_expr.eval(vars, rng.as_deref_mut());
146 let rhs = rhs_expr.eval(vars, rng);
147 lhs.min(rhs)
148 }
149 FloatExpr::Max(args) => {
150 let (lhs_expr, rhs_expr) = args.as_ref();
151 let lhs = lhs_expr.eval(vars, rng.as_deref_mut());
152 let rhs = rhs_expr.eval(vars, rng);
153 lhs.max(rhs)
154 }
155 }
156 }
157
158 pub(crate) fn map<W: Clone>(self, map: &dyn Fn(V) -> W) -> FloatExpr<W> {
159 match self {
160 FloatExpr::Const(float) => FloatExpr::Const(float),
161 FloatExpr::Var(var) => FloatExpr::Var(map(var)),
162 FloatExpr::Nat(natural_expr) => FloatExpr::Nat(natural_expr.map(map)),
163 FloatExpr::Int(integer_expr) => FloatExpr::Int(integer_expr.map(map)),
164 FloatExpr::Rand(bounds) => {
165 let (lower_bound, upper_bound) = *bounds;
166 FloatExpr::Rand(Box::new((lower_bound.map(map), upper_bound.map(map))))
167 }
168 FloatExpr::Opposite(float_expr) => FloatExpr::Opposite(Box::new(float_expr.map(map))),
169 FloatExpr::Sum(float_exprs) => {
170 FloatExpr::Sum(float_exprs.into_iter().map(|expr| expr.map(map)).collect())
171 }
172 FloatExpr::Product(float_exprs) => {
173 FloatExpr::Product(float_exprs.into_iter().map(|expr| expr.map(map)).collect())
174 }
175 FloatExpr::Div(args) => {
176 let (lhs, rhs) = *args;
177 FloatExpr::Div(Box::new((lhs.map(map), rhs.map(map))))
178 }
179 FloatExpr::Ite(args) => {
180 let (r#if, then, r#else) = *args;
181 FloatExpr::Ite(Box::new((r#if.map(map), then.map(map), r#else.map(map))))
182 }
183 FloatExpr::Min(args) => {
184 let (lhs, rhs) = *args;
185 FloatExpr::Min(Box::new((lhs.map(map), rhs.map(map))))
186 }
187 FloatExpr::Max(args) => {
188 let (lhs, rhs) = *args;
189 FloatExpr::Max(Box::new((lhs.map(map), rhs.map(map))))
190 }
191 }
192 }
193
194 pub(crate) fn context(&self, vars: &dyn Fn(V) -> Option<Type>) -> Result<(), TypeError> {
195 match self {
196 FloatExpr::Const(_) => Ok(()),
197 FloatExpr::Var(v) => matches!(vars(*v), Some(Type::Float))
198 .then_some(())
199 .ok_or(TypeError::TypeMismatch),
200 FloatExpr::Nat(natural_expr) => natural_expr.context(vars),
201 FloatExpr::Int(integer_expr) => integer_expr.context(vars),
202 FloatExpr::Rand(exprs)
203 | FloatExpr::Div(exprs)
204 | FloatExpr::Min(exprs)
205 | FloatExpr::Max(exprs) => exprs.0.context(vars).and_then(|()| exprs.1.context(vars)),
206 FloatExpr::Opposite(integer_expr) => integer_expr.context(vars),
207 FloatExpr::Sum(integer_exprs) | FloatExpr::Product(integer_exprs) => {
208 integer_exprs.iter().try_for_each(|expr| expr.context(vars))
209 }
210 FloatExpr::Ite(exprs) => exprs
211 .0
212 .context(vars)
213 .and_then(|()| exprs.1.context(vars))
214 .and_then(|()| exprs.2.context(vars)),
215 }
216 }
217}
218
219impl<V> From<Float> for FloatExpr<V>
220where
221 V: Clone,
222{
223 fn from(value: Float) -> Self {
224 Self::Const(value)
225 }
226}
227
228impl<V> TryFrom<Expression<V>> for FloatExpr<V>
229where
230 V: Clone,
231{
232 type Error = TypeError;
233
234 fn try_from(value: Expression<V>) -> Result<Self, Self::Error> {
235 match value {
236 Expression::Boolean(_) => Err(TypeError::TypeMismatch),
237 Expression::Natural(natural_expr) => Ok(FloatExpr::Nat(natural_expr)),
238 Expression::Integer(integer_expr) => Ok(FloatExpr::Int(integer_expr)),
239 Expression::Float(float_expr) => Ok(float_expr),
240 }
241 }
242}
243
244impl<V> From<NaturalExpr<V>> for FloatExpr<V>
245where
246 V: Clone,
247{
248 fn from(value: NaturalExpr<V>) -> Self {
249 Self::Nat(value)
250 }
251}
252
253impl<V> From<IntegerExpr<V>> for FloatExpr<V>
254where
255 V: Clone,
256{
257 fn from(value: IntegerExpr<V>) -> Self {
258 if let IntegerExpr::Nat(nat_expr) = value {
259 Self::Nat(nat_expr)
260 } else {
261 Self::Int(value)
262 }
263 }
264}
265
266impl<V> Add for FloatExpr<V>
267where
268 V: Clone,
269{
270 type Output = Self;
271
272 fn add(mut self, mut rhs: Self) -> Self::Output {
273 if let FloatExpr::Sum(ref mut exprs) = self {
274 if let FloatExpr::Sum(rhs_exprs) = rhs {
275 exprs.extend(rhs_exprs);
276 } else {
277 exprs.push(rhs);
278 }
279 self
280 } else if let FloatExpr::Sum(ref mut rhs_exprs) = rhs {
281 rhs_exprs.push(self);
282 rhs
283 } else {
284 FloatExpr::Sum(vec![self, rhs])
285 }
286 }
287}
288
289impl<V> Mul for FloatExpr<V>
290where
291 V: Clone,
292{
293 type Output = Self;
294
295 fn mul(mut self, mut rhs: Self) -> Self::Output {
296 if let FloatExpr::Product(ref mut exprs) = self {
297 if let FloatExpr::Product(rhs_exprs) = rhs {
298 exprs.extend(rhs_exprs);
299 } else {
300 exprs.push(rhs);
301 }
302 self
303 } else if let FloatExpr::Product(ref mut rhs_exprs) = rhs {
304 rhs_exprs.push(self);
305 rhs
306 } else {
307 FloatExpr::Product(vec![self, rhs])
308 }
309 }
310}
311
312impl<V> Neg for FloatExpr<V>
313where
314 V: Clone,
315{
316 type Output = Self;
317
318 fn neg(self) -> Self::Output {
319 if let FloatExpr::Opposite(expr) = self {
320 *expr
321 } else {
322 FloatExpr::Opposite(Box::new(self))
323 }
324 }
325}
326
327impl<V> Div for FloatExpr<V>
328where
329 V: Clone,
330{
331 type Output = Self;
332
333 fn div(self, rhs: Self) -> Self::Output {
334 FloatExpr::Div(Box::new((self, rhs)))
335 }
336}