1use self::LpExprNode::*;
4use self::LpExprOp::*;
5
6use proc_macro2::{TokenStream};
7use quote::{quote, ToTokens};
8
9use std::convert::Into;
10use std::collections::HashMap;
11use std::fmt::Write;
12
13pub trait BoundableLp: PartialEq + Clone {
14 fn lower_bound(&self, lw: f32) -> Self;
15 fn upper_bound(&self, up: f32) -> Self;
16}
17
18#[derive(Debug, Clone, PartialEq)]
22pub struct LpBinary {
23 pub name: String,
24}
25impl LpBinary {
26 pub fn new(name: &str) -> LpBinary {
27 LpBinary {
28 name: name.to_string(),
29 }
30 }
31}
32
33impl ToTokens for LpBinary {
34 fn to_tokens(&self, stream: &mut TokenStream) {
35 let name = &self.name;
36 stream.extend(quote! {
37 LpBinary{
38 name: #name,
39 }
40 });
41 }
42}
43
44#[derive(Debug, Clone, PartialEq)]
45pub struct LpInteger {
46 pub(crate) name: String,
47 pub(crate) lower_bound: Option<f32>,
48 pub(crate) upper_bound: Option<f32>,
49}
50impl LpInteger {
51 pub fn new(name: &str) -> LpInteger {
52 LpInteger {
53 name: name.to_string(),
54 lower_bound: None,
55 upper_bound: None,
56 }
57 }
58}
59impl ToTokens for LpInteger {
60 fn to_tokens(&self, stream: &mut TokenStream) {
61 let name = &self.name;
62 let lower_bound = match self.lower_bound {
63 Some(ref v) => quote!(Some(#v)),
64 None => quote!(None)
65 };
66 let upper_bound = match self.upper_bound {
67 Some(ref v) => quote!(Some(#v)),
68 None => quote!(None)
69 };
70 stream.extend(quote! {
71 LpInteger{
72 name: #name.to_string(),
73 lower_bound: #lower_bound,
74 upper_bound: #upper_bound
75 }
76 });
77 }
78}
79
80#[derive(Debug, Clone, PartialEq)]
81pub struct LpContinuous {
82 pub name: String,
83 pub lower_bound: Option<f32>,
84 pub upper_bound: Option<f32>,
85}
86impl LpContinuous {
87 pub fn new(name: &str) -> LpContinuous {
88 LpContinuous {
89 name: name.to_string(),
90 lower_bound: None,
91 upper_bound: None,
92 }
93 }
94}
95impl ToTokens for LpContinuous {
96 fn to_tokens(&self, stream: &mut TokenStream) {
97 let name = &self.name;
98 let lower_bound = match self.lower_bound {
99 Some(ref v) => quote!(Some(#v)),
100 None => quote!(None)
101 };
102 let upper_bound = match self.upper_bound {
103 Some(ref v) => quote!(Some(#v)),
104 None => quote!(None)
105 };
106 stream.extend(quote! {
107 LpContinuous{
108 name: #name.to_string(),
109 lower_bound: #lower_bound,
110 upper_bound: #upper_bound
111 }
112 });
113 }
114}
115
116macro_rules! implement_boundable {
117 ($lp_type: ident) => {
118 impl BoundableLp for $lp_type {
119 fn lower_bound(&self, lw: f32) -> $lp_type {
120 $lp_type {
121 name: self.name.clone(),
122 lower_bound: Some(lw),
123 upper_bound: self.upper_bound,
124 }
125 }
126 fn upper_bound(&self, up: f32) -> $lp_type {
127 $lp_type {
128 name: self.name.clone(),
129 lower_bound: self.lower_bound,
130 upper_bound: Some(up),
131 }
132 }
133 }
134 };
135}
136implement_boundable!(LpInteger);
137implement_boundable!(LpContinuous);
138
139#[derive(Debug, Clone, PartialEq)]
140pub(crate) enum LpExprOp {
141 Multiplication,
142 Addition,
143 Subtraction
144}
145
146impl ToTokens for LpExprOp {
147 fn to_tokens(&self, stream: &mut TokenStream) {
148 stream.extend(
149 match self {
150 LpExprOp::Multiplication => quote!(LpExprOp::Multiplication),
151 LpExprOp::Addition => quote!(LpExprOp::Addition),
152 LpExprOp::Subtraction => quote!(LpExprOp::Subtraction),
153 }
154 );
155 }
156}
157
158pub(crate) type LpExprArenaIndex = usize;
159
160#[derive(Debug, Clone, PartialEq)]
161pub(crate) struct LpCompExpr {
162 operation: LpExprOp,
163 left_index: LpExprArenaIndex,
164 right_index: LpExprArenaIndex
165}
166
167#[derive(Debug, Clone, PartialEq)]
169pub(crate) enum LpExprNode {
170 ConsInt(LpInteger),
171 ConsBin(LpBinary),
172 ConsCont(LpContinuous),
173 LitVal(f32),
174 EmptyExpr,
175 LpCompExpr(LpExprOp, LpExprArenaIndex, LpExprArenaIndex)
176}
177
178impl ToTokens for LpExprNode {
179 fn to_tokens(&self, stream: &mut TokenStream) {
180 stream.extend(
181 match self {
182 LpExprNode::ConsInt(v) => quote!(LpExprNode::ConsInt(#v)),
183 LpExprNode::ConsBin(v) => quote!(LpExprNode::ConsBin(#v)),
184 LpExprNode::ConsCont(v) => quote!(LpExprNode::ConsCont(#v)),
185 LpExprNode::LpCompExpr(op, lhs, rhs) => quote!(LpExprNode::LpCompExpr(#op, #lhs, #rhs)),
186 LpExprNode::LitVal(v) => quote!(LpExprNode::LitVal(#v)),
187 LpExprNode::EmptyExpr => quote!(LpExprNode::EmptyExpr),
188 }
189 );
190 }
191}
192
193macro_rules! cons_into_expr {
195 ($type_from:ty, $wrapper: ident) => {
196 impl From<$type_from> for LpExprNode {
197 fn from(from: $type_from) -> Self {
198 $wrapper(from)
199 }
200 }
201 impl<'a> From<&'a $type_from> for LpExprNode {
202 fn from(from: &'a $type_from) -> Self {
203 $wrapper((*from).clone())
204 }
205 }
206 };
207}
208cons_into_expr!(LpBinary, ConsBin);
209cons_into_expr!(LpInteger, ConsInt);
210cons_into_expr!(LpContinuous, ConsCont);
211
212macro_rules! lit_into_expr {
213 ($type_from:ty) => {
214 impl From<$type_from> for LpExprNode {
215 fn from(from: $type_from) -> Self {
216 LitVal(from as f32)
217 }
218 }
219 impl<'a> From<&'a $type_from> for LpExprNode {
220 fn from(from: &'a $type_from) -> Self {
221 LitVal((*from).clone() as f32)
222 }
223 }
224 };
225}
226lit_into_expr!(f32);
227lit_into_expr!(i32);
228
229#[derive(Debug, Clone, PartialEq)]
230pub struct LpExpression {
231 root: LpExprArenaIndex,
232 arena: Vec<LpExprNode>
233}
234
235impl ToTokens for LpExpression {
236 fn to_tokens(&self, stream: &mut TokenStream) {
237 let root = self.get_root_index();
238 let arena = self.arena.clone();
239 stream.extend( quote! {
240 LpExpression {
241 root: #root,
242 arena: #( struct #arena;),*
243 }
244 });
245 }
246}
247
248macro_rules! cons_into_expr_arena {
250 ($type_from:ty, $wrapper: ident) => {
251 impl From<$type_from> for LpExpression {
252 fn from(from: $type_from) -> Self {
253 LpExpression {
254 root: 0,
255 arena: vec![$wrapper(from); 1]
256 }
257 }
258 }
259 impl<'a> From<&'a $type_from> for LpExpression {
260 fn from(from: &'a $type_from) -> Self {
261 LpExpression {
262 root: 0,
263 arena: vec![$wrapper((*from).clone()); 1]
264 }
265 }
266 }
267 };
268}
269cons_into_expr_arena!(LpBinary, ConsBin);
270cons_into_expr_arena!(LpInteger, ConsInt);
271cons_into_expr_arena!(LpContinuous, ConsCont);
272
273macro_rules! lit_into_expr_arena {
274 ($type_from:ty) => {
275 impl From<$type_from> for LpExpression {
276 fn from(from: $type_from) -> Self {
277 LpExpression {
278 root: 0,
279 arena: vec![LitVal(from as f32); 1]
280 }
281 }
282 }
283 impl<'a> From<&'a $type_from> for LpExpression {
284 fn from(from: &'a $type_from) -> Self {
285 LpExpression {
286 root: 0,
287 arena: vec![LitVal((*from).clone() as f32); 1]
288 }
289 }
290 }
291 };
292}
293lit_into_expr_arena!(f32);
294lit_into_expr_arena!(i32);
295
296impl From<LpExprNode> for LpExpression {
297 fn from(expr: LpExprNode) -> Self {
298 LpExpression {
299 root: 0,
300 arena: vec![expr; 1]
301 }
302 }
303}
304
305impl From<&LpExprNode> for LpExpression {
306 fn from(expr: &LpExprNode) -> Self {
307 LpExpression {
308 root: 0,
309 arena: vec![expr.clone(); 1]
310 }
311 }
312}
313
314impl LpExpression {
315 fn new() -> Self {
316 LpExpression {
317 root: 0,
318 arena: Vec::new()
319 }
320 }
321
322 pub fn literal(value: f32) -> Self {
323 value.into()
324 }
325
326 #[cfg(test)]
327 fn build(root: LpExprArenaIndex, arena: Vec<LpExprNode>) -> Self {
328 LpExpression {
329 root: root,
330 arena: arena
331 }
332 }
333
334 pub(crate) fn get_root_index(&self) -> LpExprArenaIndex {
335 self.root
336 }
337
338 fn set_root_to_index(&mut self, root_index: LpExprArenaIndex) {
339 self.root = root_index;
340 }
341
342 fn push_as_expr<T>(&mut self, lp_expr: &T) -> LpExprArenaIndex where T: Into<LpExprNode> + Clone {
343 let index = self.arena.len();
344 self.arena.push(lp_expr.clone().into());
345 return index
346 }
347
348 fn clone_expr_at_and_push(&mut self, index: LpExprArenaIndex) -> LpExprArenaIndex {
349 let new_index = self.arena.len();
350 self.arena.push(self.expr_clone_at(index));
351 return new_index
352 }
353
354 fn overwrite_expr_at(&mut self, index: LpExprArenaIndex, lp_expr: LpExprNode) {
355 self.arena[index] = lp_expr;
356 }
357
358 pub(crate) fn expr_ref_at(&self, index: LpExprArenaIndex) -> &LpExprNode {
359 match self.arena.get(index) {
360 Some(expr) => expr,
361 None => panic!("Requested index out of bound of LpExpression vector. This should not happen.")
362 }
363 }
364
365 fn expr_clone_at(&self, index: LpExprArenaIndex) -> LpExprNode {
366 match self.arena.get(index) {
367 Some(expr) => expr.clone(),
368 None => panic!("Requested index out of bound of LpExpression vector. This should not happen.")
369 }
370 }
371
372 pub(crate) fn get_root_expr_ref(&self) -> &LpExprNode {
373 self.expr_ref_at(self.root)
374 }
375
376 pub(crate) fn split_off_constant(&mut self) -> f32 {
377 match self.expr_clone_at(self.root) {
378 LitVal(c) => {
379 self.clone_from(&LpExpression::new());
380 c
381 },
382 LpCompExpr(Addition, e1, e2) => {
383 if let LitVal(c) = self.expr_clone_at(e2) {
384 self.set_root_to_index(e1);
385 c
386 } else {
387 0.0
388 }
389 },
390 LpCompExpr(Subtraction, e1, e2) => {
391 if let LitVal(c) = self.expr_clone_at(e2) {
392 self.set_root_to_index(e1);
393 -c
394 } else {
395 0.0
396 }
397 },
398 _ => 0.0
399 }
400 }
401
402 pub(crate) fn merge_cloned_arenas(&self, right_lp_expr_arena: &LpExpression, operation: LpExprOp) -> Self {
403 let mut new_arena = self.clone();
404 let index_at_insertion = new_arena.push_arena_at_root(right_lp_expr_arena);
405 let new_root = new_arena.push_as_expr(
406 &LpCompExpr(operation, new_arena.get_root_index(), index_at_insertion)
407 );
408 new_arena.set_root_to_index(new_root);
409 new_arena
410 }
411
412 fn push_arena_at_root(&mut self, right_lp_expr_arena: &LpExpression) -> LpExprArenaIndex {
413 let right_root_expr_ref = right_lp_expr_arena.get_root_expr_ref();
414 let new_index_right_root = self.push_as_expr(right_root_expr_ref);
415 let mut move_stack: Vec<LpExprArenaIndex> = Vec::new();
416 move_stack.push(new_index_right_root);
417 while let Some(new_parent_index) = move_stack.pop() {
418 let lp_expr_arena = self.expr_clone_at(new_parent_index);
419 if let LpCompExpr(operation, right_arena_left_index, right_arena_right_index) = lp_expr_arena {
420 let new_left_index = self.push_as_expr(right_lp_expr_arena.expr_ref_at(right_arena_left_index));
421 let new_right_index = self.push_as_expr(right_lp_expr_arena.expr_ref_at(right_arena_right_index));
422 self.overwrite_expr_at(
423 new_parent_index,
424 LpCompExpr(
425 operation.clone(),
426 new_left_index,
427 new_right_index
428 )
429 );
430 move_stack.push(new_left_index);
431 move_stack.push(new_right_index);
432 }
433 }
434 new_index_right_root
435 }
436
437 fn clone_subtree_at_index_and_push(&mut self, index: LpExprArenaIndex) -> LpExpression {
438 let mut clone_stack: Vec<LpExprNode> = vec![self.expr_clone_at(index)];
439 let mut cloned_subtree = LpExpression::new();
440 let mut new_left_index: LpExprArenaIndex;
441 let mut new_right_index_stack: Vec<LpExprArenaIndex> = Vec::new();
442 let mut left_stack: Vec<bool> = vec![false];
443 while let (Some(expr), Some(mut left)) = (clone_stack.pop(), left_stack.pop()) {
444 if let LpCompExpr(op, left_index, right_index) = expr {
445 clone_stack.push(LpCompExpr(op, left_index, right_index));
446 left_stack.push(left);
447 clone_stack.push(self.expr_clone_at(left_index));
448 left_stack.push(true);
449 clone_stack.push(self.expr_clone_at(right_index));
450 left_stack.push(false);
451 } else {
452 if left {
453 new_left_index = cloned_subtree.push_as_expr(&expr);
454 while left {
455 if let (Some(LpCompExpr(op, _, _)), Some(local_left)) = (clone_stack.pop(), left_stack.pop()) {
456 if let Some(new_right_index) = new_right_index_stack.pop() {
457 left = local_left;
458 if left {
459 new_left_index = cloned_subtree.push_as_expr(
460 &LpCompExpr(op, new_left_index, new_right_index)
461 );
462 } else {
463 new_right_index_stack.push(
464 cloned_subtree.push_as_expr(
465 &LpCompExpr(op, new_left_index, new_right_index)
466 )
467 );
468 }
469 } else {
470 panic!("Found no remaining right index to match the left.")
471 }
472 } else {
473 panic!("Found no parent node to match two new indices I have.");
474 }
475 }
476 } else {
477 new_right_index_stack.push( cloned_subtree.push_as_expr(&expr) );
478 }
479 }
480 }
481
482 if let Some(root_index) = new_right_index_stack.pop() {
483 cloned_subtree.set_root_to_index(root_index);
484 cloned_subtree
485 } else {
486 panic!("Got an empty new_right_index_stack. This is a bug.");
487 }
488 }
489
490 pub(crate) fn show(&self, e: &LpExprArenaIndex, with_parenthesis: bool) -> String {
491 #[derive(Clone, Copy)]
492 enum Part {
493 None,
494 Char(char),
495 Str(&'static str),
496 Elem(LpExprArenaIndex),
497 }
498 let left = if with_parenthesis { Part::Char('(') } else { Part::None };
499 let right = if with_parenthesis { Part::Char(')') } else { Part::None };
500 let op_mult = if with_parenthesis { Part::Str(" * ") } else { Part::Char(' ') };
501
502 let mut remaining: Vec<Part> = vec![Part::Elem(*e)];
503 let mut result = String::new();
504 while let Some(e) = remaining.pop() {
505 match e {
506 Part::None => {}
507 Part::Char(c) => { result.push(c) }
508 Part::Str(s) => { result.push_str(s) }
509 Part::Elem(e) => {
510 match self.expr_ref_at(e) {
511 LitVal(n) => write!(result, "{}", n).unwrap(),
512 LpCompExpr(Addition, e1, e2) => {
513 remaining.push(right);
514 remaining.push(Part::Elem(*e2));
515 remaining.push(Part::Str(" + "));
516 remaining.push(Part::Elem(*e1));
517 remaining.push(left);
518 }
519 LpCompExpr(Subtraction, e1, e2) => {
520 remaining.push(right);
521 remaining.push(Part::Elem(*e2));
522 remaining.push(Part::Str(" - "));
523 remaining.push(Part::Elem(*e1));
524 remaining.push(left);
525 }
526 LpCompExpr(Multiplication, e1, e2) => {
527 match self.expr_ref_at(*e1) {
528 &LitVal(c) if c == 1.0 => {
529 remaining.push(right);
530 remaining.push(Part::Elem(*e2));
531 remaining.push(Part::Char(' '));
532 remaining.push(left);
533 },
534 &LitVal(c) if c == -1.0 => {
535 remaining.push(right);
536 remaining.push(Part::Elem(*e2));
537 remaining.push(Part::Str("-"));
538 remaining.push(left);
539 }
540 _ => {
541 remaining.push(right);
542 remaining.push(Part::Elem(*e2));
543 remaining.push(op_mult);
544 remaining.push(Part::Elem(*e1));
545 remaining.push(left);
546 }
547 }
548 }
549 ConsBin(LpBinary { name: ref n, .. }) => result += n,
550 ConsInt(LpInteger { name: ref n, .. }) => result += n,
551 ConsCont(LpContinuous { name: ref n, .. }) => result += n,
552 EmptyExpr => { result += "EmptyExpr!!!" }
553 }
554 }
555 }
556 }
557 result
558 }
559
560 pub(crate) fn simplify(&mut self) -> &mut Self {
561 let mut stop = false;
562 let mut lp_expr_stack: Vec<LpExprArenaIndex> = Vec::new();
563 while !stop {
564 stop = true;
565 lp_expr_stack.push(self.get_root_index());
566 while let Some(handled_expr_index) = lp_expr_stack.pop() {
567 match self.expr_clone_at(handled_expr_index) {
568 LpCompExpr(Multiplication, left_index, right_index) => {
569 match (self.expr_clone_at(left_index), self.expr_clone_at(right_index)) {
570 (_, LitVal(c))
572 | (LitVal(c), _) if c == 0.0 => {
573 stop = false;
574 self.overwrite_expr_at(
575 handled_expr_index,
576 LitVal(0.0),
577 )
578 },
579
580 (LitVal(c1), LitVal(c2)) => {
582 stop = false;
583 self.overwrite_expr_at(
584 handled_expr_index,
585 LitVal(c1 * c2)
586 )
587 },
588
589 (i, LpCompExpr(Addition, a_index, b_index)) => {
592 stop = false;
593 let i_new_index: LpExprArenaIndex;
594 if let LpCompExpr(_, _, _) = i {
595 let new_subtree = self.clone_subtree_at_index_and_push(left_index);
596 i_new_index = self.push_arena_at_root(&new_subtree);
597 } else {
598 i_new_index = self.clone_expr_at_and_push(left_index);
600 }
601 let new_left_index = self.push_as_expr(
602 &LpCompExpr(Multiplication, left_index, a_index)
603 );
604 self.overwrite_expr_at(
605 right_index,
606 LpCompExpr(Multiplication, i_new_index, b_index)
607 );
608 self.overwrite_expr_at(
609 handled_expr_index,
610 LpCompExpr(Addition, new_left_index, right_index)
611 );
612 lp_expr_stack.push(handled_expr_index);
613 },
614 (LpCompExpr(Addition, a_index, b_index), i) => {
616 stop = false;
617 let i_new_index: LpExprArenaIndex;
618 if let LpCompExpr(_, _, _) = i {
619 let new_subtree = self.clone_subtree_at_index_and_push(right_index);
620 i_new_index = self.push_arena_at_root(&new_subtree);
621 } else {
622 i_new_index = self.clone_expr_at_and_push(right_index);
624 }
625 let new_right_index = self.push_as_expr(
626 &LpCompExpr(Multiplication, right_index, b_index)
627 );
628 self.overwrite_expr_at(
629 left_index,
630 LpCompExpr(Multiplication, i_new_index, a_index)
631 );
632 self.overwrite_expr_at(
633 handled_expr_index,
634 LpCompExpr(Addition, left_index, new_right_index)
635 );
636 lp_expr_stack.push(handled_expr_index);
637 },
638
639 (LpCompExpr(Subtraction, a_index, b_index), i) => {
641 stop = false;
642 let i_new_index: LpExprArenaIndex;
643 if let LpCompExpr(_, _, _) = i {
644 let new_subtree = self.clone_subtree_at_index_and_push(right_index);
645 i_new_index = self.push_arena_at_root(&new_subtree);
646 } else {
647 i_new_index = self.clone_expr_at_and_push(right_index);
649 }
650 let new_right_index = self.push_as_expr(
651 &LpCompExpr(Multiplication, right_index, b_index)
652 );
653 self.overwrite_expr_at(
654 left_index,
655 LpCompExpr(Multiplication, i_new_index, a_index)
656 );
657 self.overwrite_expr_at(
658 handled_expr_index,
659 LpCompExpr(Subtraction, left_index, new_right_index)
660 );
661 lp_expr_stack.push(handled_expr_index);
662 },
663 (i, LpCompExpr(Subtraction, a_index, b_index)) => {
665 stop = false;
666 let i_new_index: LpExprArenaIndex;
667 if let LpCompExpr(_, _, _) = i {
668 let new_subtree = self.clone_subtree_at_index_and_push(left_index);
669 i_new_index = self.push_arena_at_root(&new_subtree);
670 } else {
671 i_new_index = self.clone_expr_at_and_push(left_index);
673 }
674 let new_left_index = self.push_as_expr(
675 &LpCompExpr(Multiplication, left_index, a_index)
676 );
677 self.overwrite_expr_at(
678 right_index,
679 LpCompExpr(Multiplication, i_new_index, b_index)
680 );
681 self.overwrite_expr_at(
682 handled_expr_index,
683 LpCompExpr(Subtraction, new_left_index, right_index)
684 );
685 lp_expr_stack.push(handled_expr_index);
686 },
687
688
689 (LitVal(c1), LpCompExpr(Multiplication, a_index, b_index)) => {
692 match (self.expr_clone_at(a_index), self.expr_clone_at(b_index)) {
693 (LitVal(c2), _) => {
695 stop = false;
696 self.overwrite_expr_at(
697 left_index,
698 LitVal(c1 * c2),
699 );
700 self.overwrite_expr_at(
701 handled_expr_index,
702 LpCompExpr(
703 Multiplication,
704 left_index,
705 b_index
706 )
707 );
708 lp_expr_stack.push(handled_expr_index);
709 },
710 (_, LitVal(c2)) => {
712 stop = false;
713 self.overwrite_expr_at(
714 left_index,
715 LitVal(c1 * c2),
716 );
717 self.overwrite_expr_at(
718 handled_expr_index,
719 LpCompExpr(
720 Multiplication,
721 left_index,
722 a_index
723 )
724 );
725 lp_expr_stack.push(handled_expr_index);
726 },
727 (_, _) => {
729 stop = false;
730 let lit_new_index = self.push_as_expr(&LitVal(c1));
731 self.overwrite_expr_at(
732 left_index,
733 LpCompExpr(
734 Multiplication,
735 lit_new_index,
736 a_index
737 )
738 );
739 self.overwrite_expr_at(
740 handled_expr_index,
741 LpCompExpr(
742 Multiplication,
743 left_index,
744 b_index
745 )
746 );
747 lp_expr_stack.push(handled_expr_index);
748 }
749 }
750 },
751
752 (_, LpCompExpr(Multiplication, a_index, b_index)) => {
758 stop = false;
759 let left_new_index = self.clone_expr_at_and_push(left_index);
760 self.overwrite_expr_at(
761 left_index,
762 LpCompExpr(Multiplication, left_new_index, a_index),
763 );
764 self.overwrite_expr_at(
765 right_index,
766 self.expr_clone_at(b_index)
767 );
768 lp_expr_stack.push(handled_expr_index);
769 },
770
771 (_, LitVal(_)) => {
773 stop = false;
774 self.overwrite_expr_at(
775 handled_expr_index,
776 LpCompExpr(
777 Multiplication,
778 right_index,
779 left_index
780 )
781 );
782 lp_expr_stack.push(handled_expr_index);
783 },
784
785 (LitVal(_c1), _) => { },
787 (LpCompExpr(_, _, _), _) => {
789 lp_expr_stack.push(left_index);
790 },
791 (_, _) => { }
792 }
793 },
794 LpCompExpr(Addition, left_index, right_index) => {
795 match (self.expr_clone_at(left_index), self.expr_clone_at(right_index)) {
796 (LitVal(c), a)
798 | (a, LitVal(c)) if c == 0.0 => {
800 stop = false;
801 self.overwrite_expr_at(handled_expr_index, a.clone());
802 lp_expr_stack.push(handled_expr_index);
803 },
804
805 (LitVal(c1), LitVal(c2)) => {
807 stop = false;
808 self.overwrite_expr_at(
809 handled_expr_index,
810 LitVal(c1 + c2)
811 );
812 },
813
814 (LitVal(_c), _x) => {
816 stop = false;
817 self.overwrite_expr_at(
818 handled_expr_index,
819 LpCompExpr(Addition, right_index, left_index)
820 );
821 lp_expr_stack.push(right_index);
822 },
823
824 (a, LpCompExpr(Addition, b_index, c_index)) => {
827 stop = false;
828 let new_a_index = self.push_as_expr(&a.clone());
829 self.overwrite_expr_at(
830 left_index,
831 LpCompExpr(Addition, new_a_index, b_index),
832 );
833 self.overwrite_expr_at(
834 right_index,
835 self.expr_clone_at(c_index)
836 );
837 lp_expr_stack.push(handled_expr_index);
838 },
839
840 (a, LpCompExpr(Subtraction, b_index, c_index)) => {
842 stop = false;
843 let new_a_index = self.push_as_expr(&a.clone());
844 self.overwrite_expr_at(
845 left_index,
846 LpCompExpr(Addition, new_a_index, b_index),
847 );
848 self.overwrite_expr_at(
849 right_index,
850 self.expr_clone_at(c_index)
851 );
852 self.overwrite_expr_at(
853 handled_expr_index,
854 LpCompExpr(Subtraction, left_index, right_index)
855 );
856 lp_expr_stack.push(handled_expr_index);
857 },
858
859 (LpCompExpr(Addition, a_index, b_index), LitVal(c2)) => {
862 match self.expr_clone_at(b_index) {
863 LitVal(c1) => {
864 stop = false;
865 self.overwrite_expr_at(
866 left_index,
867 self.expr_clone_at(a_index)
868 );
869 self.overwrite_expr_at(
870 right_index,
871 LitVal(c1 + c2)
872 );
873 lp_expr_stack.push(handled_expr_index);
874 },
875 _ => {
876 lp_expr_stack.push(left_index);
877 },
878 }
879 },
880 (LpCompExpr(Subtraction, a_index, b_index), LitVal(c2)) => {
881 match (self.expr_clone_at(a_index), self.expr_clone_at(b_index)) {
882 (_a, LitVal(c1)) => {
884 stop = false;
885 self.overwrite_expr_at(
886 right_index,
887 LitVal(c2 - c1)
888 );
889 self.overwrite_expr_at(
890 handled_expr_index,
891 LpCompExpr(Addition, a_index, right_index)
892 );
893 lp_expr_stack.push(a_index);
894 },
895 (LitVal(c1), _b) => {
897 stop = false;
898 let lit_new_index = self.push_as_expr(&LitVal(-1.0));
899 self.overwrite_expr_at(
900 left_index,
901 LpCompExpr(
902 Multiplication,
903 lit_new_index,
904 b_index
905 )
906 );
907 self.overwrite_expr_at(
908 right_index,
909 LitVal(c1 + c2)
910 );
911 lp_expr_stack.push(handled_expr_index);
912 },
913 _ => {
914 lp_expr_stack.push(left_index);
915 },
916 }
917 },
918
919 (LpCompExpr(Addition, a_index, b_index), _x) => {
921 match (self.expr_clone_at(a_index), self.expr_clone_at(b_index)) {
922 (_, LitVal(_c1)) => {
924 stop = false;
925 self.overwrite_expr_at(
926 left_index,
927 LpCompExpr(Addition, a_index, right_index)
928 );
929 self.overwrite_expr_at(
930 handled_expr_index,
931 LpCompExpr(Addition, left_index, b_index)
932 );
933 lp_expr_stack.push(left_index);
934 },
935 _ => {
948 lp_expr_stack.push(right_index);
949 lp_expr_stack.push(left_index);
950 }
951 }
952 },
953 (LpCompExpr(Subtraction, a_index, b_index), _x) => {
954 match (self.expr_clone_at(a_index), self.expr_clone_at(b_index)) {
955 (_a, LitVal(_c1)) => {
957 stop = false;
958 self.overwrite_expr_at(
959 left_index,
960 LpCompExpr(Addition, a_index, right_index)
961 );
962 self.overwrite_expr_at(
963 handled_expr_index,
964 LpCompExpr(Subtraction, left_index, b_index)
965 );
966 lp_expr_stack.push(left_index);
967 },
968 (LitVal(_c1), _b) => {
970 stop = false;
971 self.overwrite_expr_at(
972 left_index,
973 LpCompExpr(Subtraction, right_index, b_index)
974 );
975 self.overwrite_expr_at(
976 handled_expr_index,
977 LpCompExpr(Addition, left_index, a_index)
978 );
979 lp_expr_stack.push(left_index);
980 },
981 (_a, _b) => {
982 lp_expr_stack.push(left_index);
983 lp_expr_stack.push(right_index);
984 }
985 }
986 },
987
988 (a, b) => {
1004 if a == b {
1006 stop = false;
1007 let new_lit_index = self.push_as_expr(&LitVal(2.0));
1008 self.overwrite_expr_at(
1009 handled_expr_index,
1010 LpCompExpr(
1011 Multiplication,
1012 new_lit_index,
1013 left_index
1014 )
1015 );
1016 lp_expr_stack.push(left_index);
1017 } else {
1018 match (a, b) {
1019 (LpCompExpr(_, _, _), LpCompExpr(_, _, _)) => {
1020 lp_expr_stack.push(left_index);
1021 lp_expr_stack.push(right_index);
1022 },
1023 (LpCompExpr(_, _, _), _) => {
1024 lp_expr_stack.push(left_index);
1025 },
1026 (_, LpCompExpr(_, _, _)) => {
1027 lp_expr_stack.push(right_index);
1028 },
1029 (_, _) => { }
1030 }
1031 }
1032 }
1033 }
1034 },
1035 LpCompExpr(Subtraction, left_index, right_index) => {
1036 match (self.expr_clone_at(left_index), self.expr_clone_at(right_index)) {
1037 (a, LitVal(c)) if c == 0.0 => {
1039 stop = false;
1040 self.overwrite_expr_at(
1041 handled_expr_index,
1042 a.clone()
1043 );
1044 lp_expr_stack.push(handled_expr_index);
1045 },
1046
1047 (_, LpCompExpr(Addition, b_index, c_index)) => {
1049 stop = false;
1050 let a_new_index = self.clone_expr_at_and_push(left_index);
1051 self.overwrite_expr_at(
1052 left_index,
1053 LpCompExpr(Subtraction, a_new_index, b_index)
1054 );
1055 self.overwrite_expr_at(
1056 handled_expr_index,
1057 LpCompExpr(Subtraction, left_index, c_index)
1058 );
1059 lp_expr_stack.push(handled_expr_index);
1060 },
1061
1062 (_, LpCompExpr(Subtraction, b_index, c_index)) => {
1064 stop = false;
1065 let a_new_index = self.clone_expr_at_and_push(left_index);
1066 self.overwrite_expr_at(
1067 left_index,
1068 LpCompExpr(Subtraction, a_new_index, b_index),
1069
1070 );
1071 self.overwrite_expr_at(
1072 handled_expr_index,
1073 LpCompExpr(Addition, left_index, c_index)
1074 );
1075 lp_expr_stack.push(handled_expr_index);
1076 },
1077
1078 (LitVal(_), _) => {
1081 stop = false;
1082 let lit_new_index = self.push_as_expr(&LitVal(-1.0));
1083 let new_index = self.push_as_expr(
1084 &LpCompExpr(
1085 Multiplication,
1086 lit_new_index,
1087 right_index
1088 )
1089 );
1090 self.overwrite_expr_at(
1091 handled_expr_index,
1092 LpCompExpr(Addition, new_index, left_index)
1093 );
1094 lp_expr_stack.push(handled_expr_index);
1095 },
1096
1097 (LpCompExpr(Subtraction, a_index, b_index), LitVal(c2)) => {
1101 match (self.expr_clone_at(a_index), self.expr_clone_at(b_index)) {
1102 (a, LitVal(c1)) => {
1103 stop = false;
1104 self.overwrite_expr_at(
1105 left_index,
1106 a.clone()
1107 );
1108 self.overwrite_expr_at(
1109 right_index,
1110 LitVal(c1 + c2)
1111 );
1112 lp_expr_stack.push(handled_expr_index);
1113 },
1114 (LitVal(c1), _) => {
1115 stop = false;
1116 let lit_new_index = self.push_as_expr(&LitVal(-1.0));
1117 self.overwrite_expr_at(
1118 left_index,
1119 LpCompExpr(
1120 Multiplication,
1121 lit_new_index,
1122 b_index
1123 )
1124 );
1125 self.overwrite_expr_at(
1126 right_index,
1127 LitVal(c1 - c2)
1128 );
1129 self.overwrite_expr_at(
1130 handled_expr_index,
1131 LpCompExpr(
1132 Addition,
1133 left_index,
1134 right_index
1135 )
1136 );
1137 lp_expr_stack.push(handled_expr_index);
1138 },
1139 _ => {
1140 lp_expr_stack.push(left_index);
1141 },
1142 }
1143 },
1144
1145 (LpCompExpr(Addition, a_index, c1_index), LitVal(c2)) => {
1147 match self.expr_clone_at(c1_index) {
1148 LitVal(c1) => {
1149 stop = false;
1150 self.overwrite_expr_at(
1151 right_index,
1152 LitVal(c1 - c2)
1153 );
1154 self.overwrite_expr_at(
1155 handled_expr_index,
1156 LpCompExpr(Addition, a_index, right_index)
1157 );
1158 lp_expr_stack.push(handled_expr_index);
1159 },
1160 _ => {
1161 lp_expr_stack.push(left_index);
1162 }
1163 }
1164 },
1165
1166 (LpCompExpr(Addition, a_index, b_index), _x) => {
1169 match self.expr_clone_at(b_index) {
1170 LitVal(_c1) => {
1171 stop = false;
1172 self.overwrite_expr_at(
1173 left_index,
1174 LpCompExpr(Subtraction, a_index, right_index),
1175 );
1176 self.overwrite_expr_at(
1177 handled_expr_index,
1178 LpCompExpr(Addition, left_index, b_index)
1179 );
1180 lp_expr_stack.push(handled_expr_index);
1181 },
1182 _ => {
1183 lp_expr_stack.push(left_index);
1184 lp_expr_stack.push(right_index);
1185 }
1186 }
1187 }
1188 (LpCompExpr(Subtraction, a_index, b_index), _x) => {
1189 match (self.expr_clone_at(a_index), self.expr_clone_at(b_index)) {
1190 (_a, LitVal(_c1)) => {
1192 stop = false;
1193 self.overwrite_expr_at(
1194 left_index,
1195 LpCompExpr(Subtraction, a_index, right_index)
1196 );
1197 self.overwrite_expr_at(
1198 handled_expr_index,
1199 LpCompExpr(Subtraction, left_index, b_index)
1200 );
1201 lp_expr_stack.push(left_index);
1202 },
1203 (LitVal(_c1), _b) => {
1205 stop = false;
1206 let minus_one_new_index = self.push_as_expr(&LitVal(-1.0));
1207 let minus_b_new_index = self.push_as_expr(
1208 &LpCompExpr(Multiplication, minus_one_new_index, b_index)
1209 );
1210 self.overwrite_expr_at(
1211 left_index,
1212 LpCompExpr(Subtraction, minus_b_new_index, right_index)
1213 );
1214 self.overwrite_expr_at(
1215 handled_expr_index,
1216 LpCompExpr(Addition, left_index, a_index)
1217 );
1218 lp_expr_stack.push(left_index);
1219 },
1220 _ => {
1221 lp_expr_stack.push(right_index);
1222 lp_expr_stack.push(left_index);
1223 }
1224 }
1225 },
1226 (a, b) => {
1227 if a == b {
1229 stop = false;
1230 self.overwrite_expr_at(
1231 handled_expr_index,
1232 LitVal(0.0)
1233 );
1234 } else {
1235 match (a, b) {
1236 (LpCompExpr(_, _, _), LpCompExpr(_, _, _)) => {
1238 lp_expr_stack.push(left_index);
1239 lp_expr_stack.push(right_index);
1240 },
1241 (LpCompExpr(_, _, _), _) => {
1242 lp_expr_stack.push(left_index);
1243 },
1244 (_, LpCompExpr(_, _, _)) => {
1245 lp_expr_stack.push(right_index);
1246 },
1247 (_, _) => { }
1248 }
1249 }
1250 }
1251 }
1252 },
1253 ConsBin(_)
1254 | ConsInt(_)
1255 | ConsCont(_)
1256 | LitVal(_)
1257 | LpExprNode::EmptyExpr => { }
1258 };
1259 }
1260 }
1261 self
1262 }
1263}
1264
1265
1266#[derive(Debug, Clone, PartialEq)]
1267pub enum Constraint {
1268 GreaterOrEqual,
1273 LessOrEqual,
1274 Equal,
1275}
1276
1277impl ToTokens for Constraint {
1278 fn to_tokens(&self, stream: &mut TokenStream) {
1279 stream.extend(
1280 match self {
1281 Constraint::GreaterOrEqual => quote!(Constraint::GreaterOrEqual),
1282 Constraint::LessOrEqual => quote!(Constraint::LessOrEqual),
1283 Constraint::Equal => quote!(Constraint::Equal),
1284 });
1285 }
1286}
1287
1288#[derive(Debug, Clone, PartialEq)]
1289pub struct LpConstraint(pub LpExpression, pub Constraint, pub LpExpression);
1290
1291impl LpConstraint {
1292 pub(crate) fn generalize(&self) -> LpConstraint {
1293 let &LpConstraint(ref lhs, ref op, ref rhs) = self;
1295 let mut new_lhs_expr = lhs.merge_cloned_arenas(rhs, Subtraction);
1296 let constant = new_lhs_expr.simplify().split_off_constant();
1297 let new_rhs_expr_arena: LpExpression = LitVal(-constant).into();
1298 LpConstraint(new_lhs_expr, (*op).clone(), new_rhs_expr_arena)
1299 }
1300
1301 pub(crate) fn var(&self, expr_index: LpExprArenaIndex, constraint_index: usize, lst: &mut HashMap<String, (usize, LpExprArenaIndex)>) {
1302 match self.0.expr_ref_at(expr_index) {
1303 ConsBin(LpBinary { ref name, .. })
1304 | ConsInt(LpInteger { ref name, .. })
1305 | ConsCont(LpContinuous { ref name, .. }) => {
1306 lst.insert(name.clone(), (constraint_index, expr_index) );
1307 },
1308 LpCompExpr(Multiplication, _, e) => {
1309 self.var(*e, constraint_index, lst);
1310 },
1311 LpCompExpr(Addition, e1, e2)
1312 | LpCompExpr(Subtraction, e1, e2) => {
1313 self.var(*e1, constraint_index, lst);
1314 self.var(*e2, constraint_index, lst);
1315 }
1316 _ => (),
1317 }
1318 }
1319}
1320
1321impl ToTokens for LpConstraint {
1322 fn to_tokens(&self, stream: &mut TokenStream) {
1323 let lhs = &self.0;
1324 let constraint = &self.1;
1325 let rhs = &self.2;
1326 stream.extend(quote!(
1327 LpConstraint(
1328 #lhs, #constraint, #rhs
1329 )
1330 ));
1331 }
1332}
1333
1334
1335pub fn lp_sum<T>(expr: &Vec<T>) -> LpExpression
1352 where T: Into<LpExpression> + Clone {
1353 let mut results: Vec<LpExpression> = expr.iter().map(|e| e.clone().into()).collect();
1354 let mut next = Vec::with_capacity(results.len() / 2);
1355 while results.len() > 1 {
1356 while results.len() >= 2 {
1357 let right = results.pop().expect("impossible because len>2");
1358 let left = results.pop().expect("impossible because len>2");
1359 next.push(left + right)
1360 }
1361 next.append(&mut results);
1362 next.reverse(); std::mem::swap(&mut results, &mut next)
1364 }
1365 results.into_iter().next().unwrap_or( LpExpression::literal(0.0) )
1366}
1367
1368pub fn sum<'a, T: 'a,U: 'a>(expr: &'a Vec<T>, f: impl Fn(&'a T) -> U) -> LpExpression where U: Into<LpExpression> + Clone {
1369 return lp_sum(&expr.iter().map(|t| f(t.into())).collect());
1370}
1371
1372pub trait SummableExp {
1373 fn sum(&self) -> LpExpression;
1374}
1375
1376impl<T> SummableExp for Vec<T> where T: Into<LpExpression> + Clone {
1392 fn sum(&self) -> LpExpression {
1393 lp_sum(self)
1394 }
1395}
1396#[cfg(test)]
1397mod tests {
1398 use super::*;
1400
1401 #[test]
1402 fn expressions_creation() {
1403 let ref a = LpInteger::new("a").lower_bound(10.0).upper_bound(20.0);
1404 let ref b = LpInteger::new("b");
1405
1406 assert_eq!(
1407 a + b,
1408 LpExpression::build(
1409 2,
1410 vec![LpExprNode::ConsInt(a.clone()), LpExprNode::ConsInt(b.clone()), LpExprNode::LpCompExpr(LpExprOp::Addition, 0, 1)]
1411 )
1412 );
1413 }
1414
1415 #[test]
1416 fn simplifications() {
1417 let a = &LpInteger::new("a");
1418
1419 let expr1 = a - 2f32;
1420 let expr2 = 1f32 - a;
1421
1422 let c = (expr1.clone() + expr2.clone()).simplify().split_off_constant();
1423 assert_eq!(c, -1f32);
1424
1425 let c = (expr2.clone() + expr1.clone()).simplify().split_off_constant();
1426 assert_eq!(c, -1f32);
1427 }
1428
1429 #[test]
1430 fn simplify_deep_sum() {
1431 let count = 1000;
1432 let vars: Vec<LpExpression> = (0..count)
1433 .map(|i|
1434 &LpInteger::new(&format!("v{}", i)) * 2 + 1
1435 )
1436 .collect();
1437 let mut sum = lp_sum(&vars);
1438 assert_eq!(sum.simplify().split_off_constant(), count as f32);
1439 }
1440
1441 #[test]
1442 fn test_quotations() {
1443 let a = LpInteger { name: "a".to_string(), lower_bound: None, upper_bound: None };
1444 let quoted_a = quote!(#a);
1445 let quoted_a_str = "LpInteger { name : \"a\" . to_string () , lower_bound : None , upper_bound : None }";
1446 assert_eq!(quoted_a.to_string(), quoted_a_str);
1447
1448 let exp: LpExprNode = a.clone().into();
1449 let quoted_exp = quote!(#exp);
1450 let quoted_exp_str = "LpExprNode :: ConsInt (".to_owned() + quoted_a_str + ")";
1451 assert_eq!(quoted_exp.to_string(), quoted_exp_str);
1452
1453 let full_exp_arena = LpExpression::build (0, vec![LpExprNode:: LpCompExpr (LpExprOp :: Multiplication, 1, 2), LpExprNode:: LpCompExpr (LpExprOp :: Subtraction, 3, 4 ), LpExprNode:: LpCompExpr (LpExprOp :: Addition, 5, 6), LpExprNode:: LitVal (1f32), LpExprNode:: EmptyExpr, LpExprNode:: ConsCont (LpContinuous { name : "x".to_string() , lower_bound : None , upper_bound : None }), LpExprNode:: ConsInt (LpInteger { name : "y".to_string() , lower_bound : None , upper_bound : None }) ] );
1454
1455
1456 let full_exp_quoted = quote!(#full_exp_arena);
1457 let full_exp_str = "LpExpression { root : 0usize , arena : struct LpExprNode :: LpCompExpr (LpExprOp :: Multiplication , 1usize , 2usize) ; , struct LpExprNode :: LpCompExpr (LpExprOp :: Subtraction , 3usize , 4usize) ; , struct LpExprNode :: LpCompExpr (LpExprOp :: Addition , 5usize , 6usize) ; , struct LpExprNode :: LitVal (1f32) ; , struct LpExprNode :: EmptyExpr ; , struct LpExprNode :: ConsCont (LpContinuous { name : \"x\" . to_string () , lower_bound : None , upper_bound : None }) ; , struct LpExprNode :: ConsInt (LpInteger { name : \"y\" . to_string () , lower_bound : None , upper_bound : None }) ; }";
1458 assert_eq!(full_exp_quoted.to_string(), full_exp_str);
1459
1460 let a_eq_b = LpConstraint(LpExpression::build(0, vec![LpExprNode:: LpCompExpr(LpExprOp :: Subtraction, 1, 2), LpExprNode::ConsInt (LpInteger { name : "a".to_string() , lower_bound : None , upper_bound : None }), LpExprNode::ConsInt (LpInteger { name : "b".to_string() , lower_bound : None , upper_bound : None }) ] ), Constraint::Equal, LitVal(0f32).into());
1462
1463 let quoted_a_eq_b = quote!(#a_eq_b);
1464 let a_eq_b_str = "LpConstraint (LpExpression { root : 0usize , arena : struct LpExprNode :: LpCompExpr (LpExprOp :: Subtraction , 1usize , 2usize) ; , struct LpExprNode :: ConsInt (LpInteger { name : \"a\" . to_string () , lower_bound : None , upper_bound : None }) ; , struct LpExprNode :: ConsInt (LpInteger { name : \"b\" . to_string () , lower_bound : None , upper_bound : None }) ; } , Constraint :: Equal , LpExpression { root : 0usize , arena : struct LpExprNode :: LitVal (0f32) ; })";
1465 assert_eq!(quoted_a_eq_b.to_string(), a_eq_b_str);
1466 }
1467}