From bbb0a12f8d9f314846aec5de994f4482a4ded749 Mon Sep 17 00:00:00 2001 From: Kieranoski702 Date: Tue, 2 Apr 2024 12:15:55 +0100 Subject: [PATCH 1/5] Add first attempt at optimisation --- conjure_oxide/src/main.rs | 2 + crates/conjure_core/src/ast/expressions.rs | 154 ++++++++++++++++++ crates/conjure_core/src/metadata.rs | 12 +- .../conjure_core/src/rule_engine/rewrite.rs | 31 +++- crates/conjure_core/src/stats/mod.rs | 1 + 5 files changed, 184 insertions(+), 16 deletions(-) diff --git a/conjure_oxide/src/main.rs b/conjure_oxide/src/main.rs index d15f9f31ca..a67af93043 100644 --- a/conjure_oxide/src/main.rs +++ b/conjure_oxide/src/main.rs @@ -139,6 +139,8 @@ pub fn main() -> AnyhowResult<()> { model = rewrite_model(&model, &rule_sets)?; log::info!("Rewritten model: {}", to_string_pretty(&json!(model))?); + println!("\nRewritten model:"); + println!("{:#?}", model); let solutions = get_minion_solutions(model)?; log::info!("Solutions: {}", minion_solutions_to_json(&solutions)); diff --git a/crates/conjure_core/src/ast/expressions.rs b/crates/conjure_core/src/ast/expressions.rs index 8dd8a8b633..8f8e811394 100644 --- a/crates/conjure_core/src/ast/expressions.rs +++ b/crates/conjure_core/src/ast/expressions.rs @@ -127,6 +127,160 @@ impl Expression { _ => todo!(), } } + + pub fn is_clean(&self) -> bool { + match self { + Expression::Nothing => true, + Expression::Constant(metadata, _) => metadata.clean, + Expression::Reference(metadata, _) => metadata.clean, + Expression::Sum(metadata, exprs) => { + metadata.clean && exprs.iter().all(|e| e.is_clean()) + } + Expression::Min(metadata, exprs) => { + metadata.clean && exprs.iter().all(|e| e.is_clean()) + } + Expression::Not(metadata, expr) => metadata.clean && expr.is_clean(), + Expression::Or(metadata, exprs) => { + metadata.clean && exprs.iter().all(|e| e.is_clean()) + } + Expression::And(metadata, exprs) => { + metadata.clean && exprs.iter().all(|e| e.is_clean()) + } + Expression::Eq(metadata, box1, box2) => { + metadata.clean && box1.is_clean() && box2.is_clean() + } + Expression::Neq(metadata, box1, box2) => { + metadata.clean && box1.is_clean() && box2.is_clean() + } + Expression::Geq(metadata, box1, box2) => { + metadata.clean && box1.is_clean() && box2.is_clean() + } + Expression::Leq(metadata, box1, box2) => { + metadata.clean && box1.is_clean() && box2.is_clean() + } + Expression::Gt(metadata, box1, box2) => { + metadata.clean && box1.is_clean() && box2.is_clean() + } + Expression::Lt(metadata, box1, box2) => { + metadata.clean && box1.is_clean() && box2.is_clean() + } + Expression::SumGeq(metadata, box1, box2) => { + metadata.clean && box1.iter().all(|e| e.is_clean()) && box2.is_clean() + } + Expression::SumLeq(metadata, box1, box2) => { + metadata.clean && box1.iter().all(|e| e.is_clean()) && box2.is_clean() + } + Expression::Ineq(metadata, box1, box2, box3) => { + metadata.clean && box1.is_clean() && box2.is_clean() && box3.is_clean() + } + Expression::AllDiff(metadata, exprs) => { + metadata.clean && exprs.iter().all(|e| e.is_clean()) + } + Expression::SumEq(metadata, exprs, expr) => { + metadata.clean && exprs.iter().all(|e| e.is_clean()) && expr.is_clean() + } + _ => false, + } + } + + pub fn set_clean(&mut self, bool_value: bool) { + match self { + Expression::Nothing => {} + Expression::Constant(metadata, _) => metadata.clean = bool_value, + Expression::Reference(metadata, _) => metadata.clean = bool_value, + Expression::Sum(metadata, exprs) => { + metadata.clean =bool_value; + for e in exprs { + e.set_clean(bool_value); + } + } + Expression::Min(metadata, exprs) => { + metadata.clean =bool_value; + for e in exprs { + e.set_clean(bool_value); + } + } + Expression::Not(metadata, expr) => { + metadata.clean =bool_value; + expr.set_clean(bool_value); + } + Expression::Or(metadata, exprs) => { + metadata.clean =bool_value; + for e in exprs { + e.set_clean(bool_value); + } + } + Expression::And(metadata, exprs) => { + metadata.clean =bool_value; + for e in exprs { + e.set_clean(bool_value); + } + } + Expression::Eq(metadata, box1, box2) => { + metadata.clean =bool_value; + box1.set_clean(bool_value); + box2.set_clean(bool_value); + } + Expression::Neq(metadata, box1, box2) => { + metadata.clean =bool_value; + box1.set_clean(bool_value); + box2.set_clean(bool_value); + } + Expression::Geq(metadata, box1, box2) => { + metadata.clean =bool_value; + box1.set_clean(bool_value); + box2.set_clean(bool_value); + } + Expression::Leq(metadata, box1, box2) => { + metadata.clean =bool_value; + box1.set_clean(bool_value); + box2.set_clean(bool_value); + } + Expression::Gt(metadata, box1, box2) => { + metadata.clean =bool_value; + box1.set_clean(bool_value); + box2.set_clean(bool_value); + } + Expression::Lt(metadata, box1, box2) => { + metadata.clean =bool_value; + box1.set_clean(bool_value); + box2.set_clean(bool_value); + } + Expression::SumGeq(metadata, box1, box2) => { + metadata.clean =bool_value; + for e in box1 { + e.set_clean(bool_value); + } + box2.set_clean(bool_value); + } + Expression::SumLeq(metadata, box1, box2) => { + metadata.clean =bool_value; + for e in box1 { + e.set_clean(bool_value); + } + box2.set_clean(bool_value); + } + Expression::Ineq(metadata, box1, box2, box3) => { + metadata.clean =bool_value; + box1.set_clean(bool_value); + box2.set_clean(bool_value); + box3.set_clean(bool_value); + } + Expression::AllDiff(metadata, exprs) => { + metadata.clean =bool_value; + for e in exprs { + e.set_clean(bool_value); + } + } + Expression::SumEq(metadata, exprs, expr) => { + metadata.clean =bool_value; + for e in exprs { + e.set_clean(bool_value); + } + expr.set_clean(bool_value); + } + } + } } fn display_expressions(expressions: &[Expression]) -> String { diff --git a/crates/conjure_core/src/metadata.rs b/crates/conjure_core/src/metadata.rs index f4f35f9393..ee5c9a2ec2 100644 --- a/crates/conjure_core/src/metadata.rs +++ b/crates/conjure_core/src/metadata.rs @@ -2,20 +2,14 @@ use std::fmt::{Debug, Display}; use serde::{Deserialize, Serialize}; -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] pub struct Metadata { - pub dirtyclean: bool, -} - -impl Default for Metadata { - fn default() -> Self { - Self::new() - } + pub clean: bool, } impl Metadata { pub fn new() -> Metadata { - Metadata { dirtyclean: false } + Metadata { clean: false } } } diff --git a/crates/conjure_core/src/rule_engine/rewrite.rs b/crates/conjure_core/src/rule_engine/rewrite.rs index 55f8b8056a..f3ab8a2153 100644 --- a/crates/conjure_core/src/rule_engine/rewrite.rs +++ b/crates/conjure_core/src/rule_engine/rewrite.rs @@ -48,6 +48,7 @@ pub fn rewrite_model<'a>( model: &Model, rule_sets: &Vec<&'a RuleSet<'a>>, ) -> Result { + let start = std::time::Instant::now(); let rule_priorities = get_rule_priorities(rule_sets)?; let rules = get_rules_vec(&rule_priorities); let mut new_model = model.clone(); @@ -55,6 +56,8 @@ pub fn rewrite_model<'a>( while let Some(step) = rewrite_iteration(&new_model.constraints, &new_model, &rules) { step.apply(&mut new_model); // Apply side-effects (e.g. symbol table updates) } + // Now - start time + model.context.write().unwrap().stats.rewriter_run_time = Some(start.elapsed()); Ok(new_model) } @@ -66,21 +69,35 @@ fn rewrite_iteration<'a>( model: &'a Model, rules: &'a Vec<&'a Rule<'a>>, ) -> Option { - let rule_results = apply_all_rules(expression, model, rules); - if let Some(new) = choose_rewrite(&rule_results) { - return Some(new); - } else { - let mut sub = expression.children(); + if expression.is_clean() { + // Skip processing this expression if it's clean + return None; + } + + // Mark the expression as clean - will be marked dirty if any rule is applied + let mut expression = expression.clone(); + expression.set_clean(true); - for i in 0..sub.len() { + let rule_results = apply_all_rules(&expression, model, rules); + if let Some(mut new) = choose_rewrite(&rule_results) { + // If a rule is applied, mark the expression as dirty + new.new_expression.set_clean(false); + return Some(new); + } + + let mut sub = expression.children(); + for i in 0..sub.len() { if let Some(red) = rewrite_iteration(&sub[i], model, rules) { sub[i] = red.new_expression; + // If child is dirty, make this expression dirty + if !sub[i].is_clean() { + expression.set_clean(false); + } if let Ok(res) = expression.with_children(sub.clone()) { return Some(Reduction::new(res, red.new_top, red.symbols)); } } } - } None // No rules applicable to this branch of the expression } diff --git a/crates/conjure_core/src/stats/mod.rs b/crates/conjure_core/src/stats/mod.rs index fb2c7734ec..0ca5f9ce73 100644 --- a/crates/conjure_core/src/stats/mod.rs +++ b/crates/conjure_core/src/stats/mod.rs @@ -11,6 +11,7 @@ pub use solver_stats::SolverStats; #[serde(rename_all = "camelCase")] pub struct Stats { pub solver_runs: Vec, + pub rewriter_run_time : Option, } impl Stats { From fd78c77480ad0db4a29ee44ba3ef02b8cc44f1cb Mon Sep 17 00:00:00 2001 From: kieranoski Date: Tue, 2 Apr 2024 16:27:41 +0100 Subject: [PATCH 2/5] Add working version of optimisations, add new test to rewrite tests --- conjure_oxide/src/main.rs | 2 - .../03/bool-03.expected-parse.serialised.json | 6 +- .../bool-03.expected-rewrite.serialised.json | 6 +- .../01/input.expected-parse.serialised.json | 10 +- .../01/input.expected-rewrite.serialised.json | 98 ++++++------- .../02/input.expected-parse.serialised.json | 10 +- .../02/input.expected-rewrite.serialised.json | 98 ++++++------- .../03/input.expected-parse.serialised.json | 10 +- .../03/input.expected-rewrite.serialised.json | 98 ++++++------- .../04/input.expected-parse.serialised.json | 10 +- .../04/input.expected-rewrite.serialised.json | 98 ++++++------- .../05/input.expected-parse.serialised.json | 10 +- .../05/input.expected-rewrite.serialised.json | 98 ++++++------- .../xyz/input.expected-parse.serialised.json | 22 +-- .../input.expected-rewrite.serialised.json | 30 ++-- conjure_oxide/tests/rewrite_tests.rs | 134 ++++++++++++++++++ crates/conjure_core/src/ast/expressions.rs | 87 +++--------- .../conjure_core/src/rule_engine/rewrite.rs | 84 ++++++++--- crates/conjure_core/src/stats/mod.rs | 8 +- .../conjure_core/src/stats/rewriter_stats.rs | 15 ++ 20 files changed, 544 insertions(+), 390 deletions(-) create mode 100644 crates/conjure_core/src/stats/rewriter_stats.rs diff --git a/conjure_oxide/src/main.rs b/conjure_oxide/src/main.rs index a67af93043..d15f9f31ca 100644 --- a/conjure_oxide/src/main.rs +++ b/conjure_oxide/src/main.rs @@ -139,8 +139,6 @@ pub fn main() -> AnyhowResult<()> { model = rewrite_model(&model, &rule_sets)?; log::info!("Rewritten model: {}", to_string_pretty(&json!(model))?); - println!("\nRewritten model:"); - println!("{:#?}", model); let solutions = get_minion_solutions(model)?; log::info!("Solutions: {}", minion_solutions_to_json(&solutions)); diff --git a/conjure_oxide/tests/integration/basic/bool/03/bool-03.expected-parse.serialised.json b/conjure_oxide/tests/integration/basic/bool/03/bool-03.expected-parse.serialised.json index 5e7a35b7c2..b95b81b273 100644 --- a/conjure_oxide/tests/integration/basic/bool/03/bool-03.expected-parse.serialised.json +++ b/conjure_oxide/tests/integration/basic/bool/03/bool-03.expected-parse.serialised.json @@ -2,12 +2,12 @@ "constraints": { "Neq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "x" @@ -17,7 +17,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "y" diff --git a/conjure_oxide/tests/integration/basic/bool/03/bool-03.expected-rewrite.serialised.json b/conjure_oxide/tests/integration/basic/bool/03/bool-03.expected-rewrite.serialised.json index bb17d7bfcf..29b1c529e1 100644 --- a/conjure_oxide/tests/integration/basic/bool/03/bool-03.expected-rewrite.serialised.json +++ b/conjure_oxide/tests/integration/basic/bool/03/bool-03.expected-rewrite.serialised.json @@ -2,13 +2,13 @@ "constraints": { "AllDiff": [ { - "dirtyclean": false + "clean": false }, [ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "x" @@ -18,7 +18,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "y" diff --git a/conjure_oxide/tests/integration/basic/min/01/input.expected-parse.serialised.json b/conjure_oxide/tests/integration/basic/min/01/input.expected-parse.serialised.json index f5e8dfb6bd..6c8c382b02 100644 --- a/conjure_oxide/tests/integration/basic/min/01/input.expected-parse.serialised.json +++ b/conjure_oxide/tests/integration/basic/min/01/input.expected-parse.serialised.json @@ -2,18 +2,18 @@ "constraints": { "Geq": [ { - "dirtyclean": false + "clean": false }, { "Min": [ { - "dirtyclean": false + "clean": false }, [ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -23,7 +23,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -36,7 +36,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 3 diff --git a/conjure_oxide/tests/integration/basic/min/01/input.expected-rewrite.serialised.json b/conjure_oxide/tests/integration/basic/min/01/input.expected-rewrite.serialised.json index 5d9be7c8b8..ddde4ec5d5 100644 --- a/conjure_oxide/tests/integration/basic/min/01/input.expected-rewrite.serialised.json +++ b/conjure_oxide/tests/integration/basic/min/01/input.expected-rewrite.serialised.json @@ -2,18 +2,18 @@ "constraints": { "And": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 3 @@ -23,7 +23,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -33,7 +33,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -45,12 +45,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -60,7 +60,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -70,7 +70,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -82,12 +82,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -97,7 +97,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -107,7 +107,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -119,18 +119,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -140,7 +140,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -150,7 +150,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -162,12 +162,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -177,7 +177,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -187,7 +187,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -202,18 +202,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -223,7 +223,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -233,7 +233,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -245,12 +245,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -260,7 +260,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -270,7 +270,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -285,18 +285,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -306,7 +306,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -316,7 +316,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -328,12 +328,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -343,7 +343,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -353,7 +353,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -368,18 +368,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -389,7 +389,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -399,7 +399,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -411,12 +411,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -426,7 +426,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -436,7 +436,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 diff --git a/conjure_oxide/tests/integration/basic/min/02/input.expected-parse.serialised.json b/conjure_oxide/tests/integration/basic/min/02/input.expected-parse.serialised.json index a517276a99..7de41298a2 100644 --- a/conjure_oxide/tests/integration/basic/min/02/input.expected-parse.serialised.json +++ b/conjure_oxide/tests/integration/basic/min/02/input.expected-parse.serialised.json @@ -2,18 +2,18 @@ "constraints": { "Leq": [ { - "dirtyclean": false + "clean": false }, { "Min": [ { - "dirtyclean": false + "clean": false }, [ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -23,7 +23,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -36,7 +36,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 2 diff --git a/conjure_oxide/tests/integration/basic/min/02/input.expected-rewrite.serialised.json b/conjure_oxide/tests/integration/basic/min/02/input.expected-rewrite.serialised.json index c10d730cf2..bb5392dbfe 100644 --- a/conjure_oxide/tests/integration/basic/min/02/input.expected-rewrite.serialised.json +++ b/conjure_oxide/tests/integration/basic/min/02/input.expected-rewrite.serialised.json @@ -2,18 +2,18 @@ "constraints": { "And": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -23,7 +23,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 2 @@ -33,7 +33,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -45,12 +45,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -60,7 +60,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -70,7 +70,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -82,12 +82,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -97,7 +97,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -107,7 +107,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -119,18 +119,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -140,7 +140,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -150,7 +150,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -162,12 +162,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -177,7 +177,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -187,7 +187,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -202,18 +202,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -223,7 +223,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -233,7 +233,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -245,12 +245,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -260,7 +260,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -270,7 +270,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -285,18 +285,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -306,7 +306,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -316,7 +316,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -328,12 +328,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -343,7 +343,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -353,7 +353,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -368,18 +368,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -389,7 +389,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -399,7 +399,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -411,12 +411,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -426,7 +426,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -436,7 +436,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 diff --git a/conjure_oxide/tests/integration/basic/min/03/input.expected-parse.serialised.json b/conjure_oxide/tests/integration/basic/min/03/input.expected-parse.serialised.json index 75c5f63472..4d7011796c 100644 --- a/conjure_oxide/tests/integration/basic/min/03/input.expected-parse.serialised.json +++ b/conjure_oxide/tests/integration/basic/min/03/input.expected-parse.serialised.json @@ -2,18 +2,18 @@ "constraints": { "Leq": [ { - "dirtyclean": false + "clean": false }, { "Min": [ { - "dirtyclean": false + "clean": false }, [ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -23,7 +23,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -36,7 +36,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 2 diff --git a/conjure_oxide/tests/integration/basic/min/03/input.expected-rewrite.serialised.json b/conjure_oxide/tests/integration/basic/min/03/input.expected-rewrite.serialised.json index 489147654e..c7e8483ff2 100644 --- a/conjure_oxide/tests/integration/basic/min/03/input.expected-rewrite.serialised.json +++ b/conjure_oxide/tests/integration/basic/min/03/input.expected-rewrite.serialised.json @@ -2,18 +2,18 @@ "constraints": { "And": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -23,7 +23,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 2 @@ -33,7 +33,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -45,12 +45,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -60,7 +60,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -70,7 +70,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -82,12 +82,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -97,7 +97,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -107,7 +107,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -119,18 +119,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -140,7 +140,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -150,7 +150,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -162,12 +162,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -177,7 +177,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -187,7 +187,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -202,18 +202,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -223,7 +223,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -233,7 +233,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -245,12 +245,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -260,7 +260,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -270,7 +270,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -285,18 +285,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -306,7 +306,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -316,7 +316,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -328,12 +328,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -343,7 +343,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -353,7 +353,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -368,18 +368,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -389,7 +389,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -399,7 +399,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -411,12 +411,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -426,7 +426,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -436,7 +436,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 diff --git a/conjure_oxide/tests/integration/basic/min/04/input.expected-parse.serialised.json b/conjure_oxide/tests/integration/basic/min/04/input.expected-parse.serialised.json index b75d3cdf54..c953cd89fd 100644 --- a/conjure_oxide/tests/integration/basic/min/04/input.expected-parse.serialised.json +++ b/conjure_oxide/tests/integration/basic/min/04/input.expected-parse.serialised.json @@ -2,18 +2,18 @@ "constraints": { "Geq": [ { - "dirtyclean": false + "clean": false }, { "Min": [ { - "dirtyclean": false + "clean": false }, [ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -23,7 +23,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -36,7 +36,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 3 diff --git a/conjure_oxide/tests/integration/basic/min/04/input.expected-rewrite.serialised.json b/conjure_oxide/tests/integration/basic/min/04/input.expected-rewrite.serialised.json index 7b25f22b99..f7af2402c3 100644 --- a/conjure_oxide/tests/integration/basic/min/04/input.expected-rewrite.serialised.json +++ b/conjure_oxide/tests/integration/basic/min/04/input.expected-rewrite.serialised.json @@ -2,18 +2,18 @@ "constraints": { "And": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 3 @@ -23,7 +23,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -33,7 +33,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -45,12 +45,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -60,7 +60,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -70,7 +70,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -82,12 +82,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -97,7 +97,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -107,7 +107,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -119,18 +119,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -140,7 +140,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -150,7 +150,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -162,12 +162,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -177,7 +177,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -187,7 +187,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -202,18 +202,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -223,7 +223,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -233,7 +233,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -245,12 +245,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -260,7 +260,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -270,7 +270,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -285,18 +285,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -306,7 +306,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -316,7 +316,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -328,12 +328,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -343,7 +343,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -353,7 +353,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -368,18 +368,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -389,7 +389,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -399,7 +399,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -411,12 +411,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -426,7 +426,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -436,7 +436,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 diff --git a/conjure_oxide/tests/integration/basic/min/05/input.expected-parse.serialised.json b/conjure_oxide/tests/integration/basic/min/05/input.expected-parse.serialised.json index 48469cfaaa..98fbcfcbf8 100644 --- a/conjure_oxide/tests/integration/basic/min/05/input.expected-parse.serialised.json +++ b/conjure_oxide/tests/integration/basic/min/05/input.expected-parse.serialised.json @@ -2,18 +2,18 @@ "constraints": { "Leq": [ { - "dirtyclean": false + "clean": false }, { "Min": [ { - "dirtyclean": false + "clean": false }, [ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -23,7 +23,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -36,7 +36,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 2 diff --git a/conjure_oxide/tests/integration/basic/min/05/input.expected-rewrite.serialised.json b/conjure_oxide/tests/integration/basic/min/05/input.expected-rewrite.serialised.json index d7fc2f974e..2f42044ffe 100644 --- a/conjure_oxide/tests/integration/basic/min/05/input.expected-rewrite.serialised.json +++ b/conjure_oxide/tests/integration/basic/min/05/input.expected-rewrite.serialised.json @@ -2,18 +2,18 @@ "constraints": { "And": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -23,7 +23,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 2 @@ -33,7 +33,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -45,12 +45,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -60,7 +60,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -70,7 +70,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -82,12 +82,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -97,7 +97,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -107,7 +107,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -119,18 +119,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -140,7 +140,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -150,7 +150,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -162,12 +162,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -177,7 +177,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -187,7 +187,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -202,18 +202,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -223,7 +223,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -233,7 +233,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -245,12 +245,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -260,7 +260,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -270,7 +270,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -285,18 +285,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -306,7 +306,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -316,7 +316,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -328,12 +328,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -343,7 +343,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -353,7 +353,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -368,18 +368,18 @@ { "Or": [ { - "dirtyclean": false + "clean": false }, [ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -389,7 +389,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -399,7 +399,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 @@ -411,12 +411,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -426,7 +426,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "MachineName": 0 @@ -436,7 +436,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 diff --git a/conjure_oxide/tests/integration/xyz/input.expected-parse.serialised.json b/conjure_oxide/tests/integration/xyz/input.expected-parse.serialised.json index e3678f74ee..d759fc847e 100644 --- a/conjure_oxide/tests/integration/xyz/input.expected-parse.serialised.json +++ b/conjure_oxide/tests/integration/xyz/input.expected-parse.serialised.json @@ -2,30 +2,30 @@ "constraints": { "And": [ { - "dirtyclean": false + "clean": false }, [ { "Eq": [ { - "dirtyclean": false + "clean": false }, { "Sum": [ { - "dirtyclean": false + "clean": false }, [ { "Sum": [ { - "dirtyclean": false + "clean": false }, [ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -35,7 +35,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -48,7 +48,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "c" @@ -61,7 +61,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 4 @@ -73,12 +73,12 @@ { "Geq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -88,7 +88,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" diff --git a/conjure_oxide/tests/integration/xyz/input.expected-rewrite.serialised.json b/conjure_oxide/tests/integration/xyz/input.expected-rewrite.serialised.json index baaae96e37..79ee6ea133 100644 --- a/conjure_oxide/tests/integration/xyz/input.expected-rewrite.serialised.json +++ b/conjure_oxide/tests/integration/xyz/input.expected-rewrite.serialised.json @@ -2,19 +2,19 @@ "constraints": { "And": [ { - "dirtyclean": false + "clean": false }, [ { "SumGeq": [ { - "dirtyclean": false + "clean": true }, [ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -24,7 +24,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -34,7 +34,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "c" @@ -45,7 +45,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": true }, { "Int": 4 @@ -57,13 +57,13 @@ { "SumLeq": [ { - "dirtyclean": false + "clean": true }, [ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -73,7 +73,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -83,7 +83,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "c" @@ -94,7 +94,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": true }, { "Int": 4 @@ -106,12 +106,12 @@ { "Ineq": [ { - "dirtyclean": false + "clean": false }, { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "b" @@ -121,7 +121,7 @@ { "Reference": [ { - "dirtyclean": false + "clean": false }, { "UserName": "a" @@ -131,7 +131,7 @@ { "Constant": [ { - "dirtyclean": false + "clean": false }, { "Int": 0 diff --git a/conjure_oxide/tests/rewrite_tests.rs b/conjure_oxide/tests/rewrite_tests.rs index 147d54ea5a..3175ad02a4 100644 --- a/conjure_oxide/tests/rewrite_tests.rs +++ b/conjure_oxide/tests/rewrite_tests.rs @@ -1,5 +1,6 @@ use core::panic; use std::collections::HashMap; +use std::env; use std::process::exit; use conjure_core::context::Context; @@ -914,6 +915,139 @@ fn rewrite_solve_xyz() { solver.solve(Box::new(|_| true)).unwrap(); } +#[test] +fn rewrite_solve_xyz_parameterized() { + println!("Rules: {:?}", get_rules()); + + let rule_sets = match resolve_rule_sets(SolverFamily::Minion, &vec!["Constant"]) { + Ok(rs) => rs, + Err(e) => { + eprintln!("Error resolving rule sets: {}", e); + exit(1); + } + }; + println!("Rule sets: {:?}", rule_sets); + + // Create variables and domain + let variable_a = Name::UserName(String::from("a")); + let variable_b = Name::UserName(String::from("b")); + let variable_c = Name::UserName(String::from("c")); + let domain = Domain::IntDomain(vec![Range::Bounded(1, 3)]); + + // Create a vector of test cases with varying number of OR clauses + let test_cases = vec![1, 2, 3, 4]; + + for num_or_clauses in test_cases { + // Construct OR'd expression + let mut or_exprs = Vec::new(); + for i in 0..num_or_clauses { + let expr = Expression::And( + Metadata::new(), + vec![ + Expression::Eq( + Metadata::new(), + Box::new(Expression::Sum( + Metadata::new(), + vec![ + Expression::Reference(Metadata::new(), variable_a.clone()), + Expression::Reference(Metadata::new(), variable_b.clone()), + Expression::Reference(Metadata::new(), variable_c.clone()), + ], + )), + Box::new(Expression::Constant(Metadata::new(), Constant::Int(4))), + ), + Expression::Lt( + Metadata::new(), + Box::new(Expression::Reference(Metadata::new(), variable_a.clone())), + Box::new(Expression::Reference(Metadata::new(), variable_b.clone())), + ), + ], + ); + or_exprs.push(expr); + } + let nested_expr = Expression::Or(Metadata::new(), or_exprs); + + // Apply rewrite function to the nested expression + let rewritten_expr = rewrite_model( + &Model::new(HashMap::new(), nested_expr.clone(), Default::default()), + &rule_sets, + ) + .unwrap() + .constraints; + + env::set_var("OPTIMIZATION", "0"); + + let rewritten_expr_unoptimized = rewrite_model( + &Model::new(HashMap::new(), nested_expr, Default::default()), + &rule_sets, + ) + .unwrap() + .constraints; + + // Check if the expression is in its simplest form + let expr = rewritten_expr.clone(); + assert!(is_simple(&expr)); + + let expr_unoptimized = rewritten_expr_unoptimized.clone(); + assert!(is_simple(&expr_unoptimized)); + + // Create model with variables and constraints + let mut model = Model::new(HashMap::new(), rewritten_expr, Default::default()); + let mut model_unoptimized = Model::new( + HashMap::new(), + rewritten_expr_unoptimized, + Default::default(), + ); + + // Insert variables and domains + model.variables.insert( + variable_a.clone(), + DecisionVariable { + domain: domain.clone(), + }, + ); + model.variables.insert( + variable_b.clone(), + DecisionVariable { + domain: domain.clone(), + }, + ); + model.variables.insert( + variable_c.clone(), + DecisionVariable { + domain: domain.clone(), + }, + ); + + model_unoptimized.variables.insert( + variable_a.clone(), + DecisionVariable { + domain: domain.clone(), + }, + ); + model_unoptimized.variables.insert( + variable_b.clone(), + DecisionVariable { + domain: domain.clone(), + }, + ); + model_unoptimized.variables.insert( + variable_c.clone(), + DecisionVariable { + domain: domain.clone(), + }, + ); + + let solver: Solver = Solver::new(adaptors::Minion::new()); + let solver = solver.load_model(model).unwrap(); + solver.solve(Box::new(|_| true)).unwrap(); + + let solver_unoptimized: Solver = Solver::new(adaptors::Minion::new()); + let solver_unoptimized = solver_unoptimized.load_model(model_unoptimized).unwrap(); + solver_unoptimized.solve(Box::new(|_| true)).unwrap(); + } +} + struct RuleResult<'a> { #[allow(dead_code)] rule: &'a Rule<'a>, diff --git a/crates/conjure_core/src/ast/expressions.rs b/crates/conjure_core/src/ast/expressions.rs index 8f8e811394..f20e355c88 100644 --- a/crates/conjure_core/src/ast/expressions.rs +++ b/crates/conjure_core/src/ast/expressions.rs @@ -140,9 +140,7 @@ impl Expression { metadata.clean && exprs.iter().all(|e| e.is_clean()) } Expression::Not(metadata, expr) => metadata.clean && expr.is_clean(), - Expression::Or(metadata, exprs) => { - metadata.clean && exprs.iter().all(|e| e.is_clean()) - } + Expression::Or(metadata, exprs) => metadata.clean && exprs.iter().all(|e| e.is_clean()), Expression::And(metadata, exprs) => { metadata.clean && exprs.iter().all(|e| e.is_clean()) } @@ -188,96 +186,55 @@ impl Expression { Expression::Nothing => {} Expression::Constant(metadata, _) => metadata.clean = bool_value, Expression::Reference(metadata, _) => metadata.clean = bool_value, - Expression::Sum(metadata, exprs) => { - metadata.clean =bool_value; - for e in exprs { - e.set_clean(bool_value); - } + Expression::Sum(metadata, _) => { + metadata.clean = bool_value; } - Expression::Min(metadata, exprs) => { - metadata.clean =bool_value; - for e in exprs { - e.set_clean(bool_value); - } + Expression::Min(metadata, _) => { + metadata.clean = bool_value; } - Expression::Not(metadata, expr) => { - metadata.clean =bool_value; - expr.set_clean(bool_value); + Expression::Not(metadata, _) => { + metadata.clean = bool_value; } - Expression::Or(metadata, exprs) => { - metadata.clean =bool_value; - for e in exprs { - e.set_clean(bool_value); - } + Expression::Or(metadata, _) => { + metadata.clean = bool_value; } - Expression::And(metadata, exprs) => { - metadata.clean =bool_value; - for e in exprs { - e.set_clean(bool_value); - } + Expression::And(metadata, _) => { + metadata.clean = bool_value; } Expression::Eq(metadata, box1, box2) => { - metadata.clean =bool_value; + metadata.clean = bool_value; box1.set_clean(bool_value); box2.set_clean(bool_value); } Expression::Neq(metadata, box1, box2) => { - metadata.clean =bool_value; - box1.set_clean(bool_value); - box2.set_clean(bool_value); + metadata.clean = bool_value; } Expression::Geq(metadata, box1, box2) => { - metadata.clean =bool_value; - box1.set_clean(bool_value); - box2.set_clean(bool_value); + metadata.clean = bool_value; } Expression::Leq(metadata, box1, box2) => { - metadata.clean =bool_value; - box1.set_clean(bool_value); - box2.set_clean(bool_value); + metadata.clean = bool_value; } Expression::Gt(metadata, box1, box2) => { - metadata.clean =bool_value; - box1.set_clean(bool_value); - box2.set_clean(bool_value); + metadata.clean = bool_value; } Expression::Lt(metadata, box1, box2) => { - metadata.clean =bool_value; - box1.set_clean(bool_value); - box2.set_clean(bool_value); + metadata.clean = bool_value; } Expression::SumGeq(metadata, box1, box2) => { - metadata.clean =bool_value; - for e in box1 { - e.set_clean(bool_value); - } - box2.set_clean(bool_value); + metadata.clean = bool_value; } Expression::SumLeq(metadata, box1, box2) => { - metadata.clean =bool_value; - for e in box1 { - e.set_clean(bool_value); - } - box2.set_clean(bool_value); + metadata.clean = bool_value; } Expression::Ineq(metadata, box1, box2, box3) => { - metadata.clean =bool_value; - box1.set_clean(bool_value); - box2.set_clean(bool_value); - box3.set_clean(bool_value); + metadata.clean = bool_value; } Expression::AllDiff(metadata, exprs) => { - metadata.clean =bool_value; - for e in exprs { - e.set_clean(bool_value); - } + metadata.clean = bool_value; } Expression::SumEq(metadata, exprs, expr) => { - metadata.clean =bool_value; - for e in exprs { - e.set_clean(bool_value); - } - expr.set_clean(bool_value); + metadata.clean = bool_value; } } } diff --git a/crates/conjure_core/src/rule_engine/rewrite.rs b/crates/conjure_core/src/rule_engine/rewrite.rs index f3ab8a2153..8473b6c9a4 100644 --- a/crates/conjure_core/src/rule_engine/rewrite.rs +++ b/crates/conjure_core/src/rule_engine/rewrite.rs @@ -1,7 +1,9 @@ +use std::env; use std::fmt::Display; use thiserror::Error; +use crate::stats::RewriterStats; use uniplate::uniplate::Uniplate; use crate::rule_engine::{Reduction, Rule, RuleSet}; @@ -38,6 +40,18 @@ impl From for RewriteError { } } +/// Checks if the OPTIMIZATIONS environment variable is set to "0". +/// +/// # Returns +/// - true if the environment variable is set to "0". +/// - false if the environment variable is not set or set to any other value. +fn optimizations_disabled() -> bool { + match env::var("OPTIMIZATIONS") { + Ok(val) => val == "0", + Err(_) => false, // Assume optimizations are enabled if the variable is not set + } +} + /// Rewrites the model by applying the rules to all constraints. /// /// Any side-effects such as symbol table updates and top-level constraints are applied to the returned model. @@ -48,16 +62,32 @@ pub fn rewrite_model<'a>( model: &Model, rule_sets: &Vec<&'a RuleSet<'a>>, ) -> Result { - let start = std::time::Instant::now(); let rule_priorities = get_rule_priorities(rule_sets)?; let rules = get_rules_vec(&rule_priorities); let mut new_model = model.clone(); + let mut stats = RewriterStats { + is_optimization_enabled: Some(!optimizations_disabled()), + rewriter_run_time: None, + rewriter_rule_application_attempts: Some(0), + rewriter_rule_applications: Some(0), + }; - while let Some(step) = rewrite_iteration(&new_model.constraints, &new_model, &rules) { + // Check if optimizations are disabled + let apply_optimizations = !optimizations_disabled(); + + let start = std::time::Instant::now(); + + while let Some(step) = rewrite_iteration( + &new_model.constraints, + &new_model, + &rules, + apply_optimizations, + &mut stats, + ) { step.apply(&mut new_model); // Apply side-effects (e.g. symbol table updates) } - // Now - start time - model.context.write().unwrap().stats.rewriter_run_time = Some(start.elapsed()); + stats.rewriter_run_time = Some(start.elapsed()); + model.context.write().unwrap().stats.add_rewriter_run(stats); Ok(new_model) } @@ -68,36 +98,43 @@ fn rewrite_iteration<'a>( expression: &'a Expression, model: &'a Model, rules: &'a Vec<&'a Rule<'a>>, + apply_optimizations: bool, + stats: &mut RewriterStats, ) -> Option { - if expression.is_clean() { + if apply_optimizations && expression.is_clean() { // Skip processing this expression if it's clean return None; } // Mark the expression as clean - will be marked dirty if any rule is applied let mut expression = expression.clone(); - expression.set_clean(true); + if apply_optimizations { + expression.set_clean(true); + } - let rule_results = apply_all_rules(&expression, model, rules); + let rule_results = apply_all_rules(&expression, model, rules, stats); if let Some(mut new) = choose_rewrite(&rule_results) { // If a rule is applied, mark the expression as dirty - new.new_expression.set_clean(false); + if apply_optimizations { + new.new_expression.set_clean(false); + } return Some(new); } - + let mut sub = expression.children(); for i in 0..sub.len() { - if let Some(red) = rewrite_iteration(&sub[i], model, rules) { - sub[i] = red.new_expression; - // If child is dirty, make this expression dirty - if !sub[i].is_clean() { - expression.set_clean(false); - } - if let Ok(res) = expression.with_children(sub.clone()) { - return Some(Reduction::new(res, red.new_top, red.symbols)); - } + if let Some(red) = rewrite_iteration(&sub[i], model, rules, apply_optimizations, stats) { + sub[i] = red.new_expression; + // If child is dirty, make this expression dirty + + if apply_optimizations && !sub[i].is_clean() { + expression.set_clean(false); + } + if let Ok(res) = expression.with_children(sub.clone()) { + return Some(Reduction::new(res, red.new_top, red.symbols)); } } + } None // No rules applicable to this branch of the expression } @@ -108,19 +145,26 @@ fn apply_all_rules<'a>( expression: &'a Expression, model: &'a Model, rules: &'a Vec<&'a Rule<'a>>, + stats: &mut RewriterStats, ) -> Vec> { let mut results = Vec::new(); for rule in rules { match rule.apply(expression, model) { Ok(red) => { + log::trace!(target: "file", "Rule applied: {:?}, to Expression: {:?}, resulting in: {:?}", rule, expression, red.new_expression); + stats.rewriter_rule_application_attempts = + Some(stats.rewriter_rule_application_attempts.unwrap() + 1); + stats.rewriter_rule_applications = + Some(stats.rewriter_rule_applications.unwrap() + 1); results.push(RuleResult { rule, reduction: red, }); - log::trace!(target: "file", "Rule applied: {:?}", rule); } Err(_) => { - log::trace!(target: "file", "Rule attempted but not applied: {:?}", rule); + log::trace!(target: "file", "Rule attempted but not applied: {:?}, to Expression: {:?}", rule, expression); + stats.rewriter_rule_application_attempts = + Some(stats.rewriter_rule_application_attempts.unwrap() + 1); continue; } } diff --git a/crates/conjure_core/src/stats/mod.rs b/crates/conjure_core/src/stats/mod.rs index 0ca5f9ce73..dec475fd6e 100644 --- a/crates/conjure_core/src/stats/mod.rs +++ b/crates/conjure_core/src/stats/mod.rs @@ -1,5 +1,7 @@ +mod rewriter_stats; mod solver_stats; +pub use rewriter_stats::RewriterStats; use schemars::JsonSchema; use serde::Serialize; use serde_with::skip_serializing_none; @@ -11,7 +13,7 @@ pub use solver_stats::SolverStats; #[serde(rename_all = "camelCase")] pub struct Stats { pub solver_runs: Vec, - pub rewriter_run_time : Option, + pub rewriter_runs: Vec, } impl Stats { @@ -22,4 +24,8 @@ impl Stats { pub fn add_solver_run(&mut self, solver_stats: SolverStats) { self.solver_runs.push(solver_stats); } + + pub fn add_rewriter_run(&mut self, rewriter_stats: RewriterStats) { + self.rewriter_runs.push(rewriter_stats); + } } diff --git a/crates/conjure_core/src/stats/rewriter_stats.rs b/crates/conjure_core/src/stats/rewriter_stats.rs new file mode 100644 index 0000000000..7facbd048d --- /dev/null +++ b/crates/conjure_core/src/stats/rewriter_stats.rs @@ -0,0 +1,15 @@ +use schemars::JsonSchema; +use serde::Serialize; +use serde_with::skip_serializing_none; + +#[skip_serializing_none] +#[derive(Default, Serialize, Clone, JsonSchema)] +#[serde(rename_all = "camelCase")] +#[allow(dead_code)] + +pub struct RewriterStats { + pub is_optimization_enabled: Option, + pub rewriter_run_time: Option, + pub rewriter_rule_application_attempts: Option, + pub rewriter_rule_applications: Option, +} From 31b8d34add2d5f24288c627676e8f99d0913f247 Mon Sep 17 00:00:00 2001 From: Kieranoski702 Date: Tue, 2 Apr 2024 17:02:38 +0100 Subject: [PATCH 3/5] Fix tests --- conjure_oxide/tests/rewrite_tests.rs | 30 ++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/conjure_oxide/tests/rewrite_tests.rs b/conjure_oxide/tests/rewrite_tests.rs index 3175ad02a4..06c5c9be3e 100644 --- a/conjure_oxide/tests/rewrite_tests.rs +++ b/conjure_oxide/tests/rewrite_tests.rs @@ -11,6 +11,7 @@ use conjure_oxide::{ get_rule_by_name, get_rules, rule_engine::{resolve_rule_sets, rewrite_model}, solver::{adaptors, Solver, SolverAdaptor as _}, + utils::testing::save_stats_json, Metadata, Model, Rule, }; use uniplate::uniplate::Uniplate; @@ -940,7 +941,7 @@ fn rewrite_solve_xyz_parameterized() { for num_or_clauses in test_cases { // Construct OR'd expression let mut or_exprs = Vec::new(); - for i in 0..num_or_clauses { + for _i in 0..num_or_clauses { let expr = Expression::And( Metadata::new(), vec![ @@ -967,23 +968,42 @@ fn rewrite_solve_xyz_parameterized() { } let nested_expr = Expression::Or(Metadata::new(), or_exprs); + let model_for_rewrite = Model::new(HashMap::new(), nested_expr.clone(), Default::default()); + let model_for_rewrite_unoptimized = Model::new(HashMap::new(), nested_expr.clone(), Default::default()); + // Apply rewrite function to the nested expression let rewritten_expr = rewrite_model( - &Model::new(HashMap::new(), nested_expr.clone(), Default::default()), + &model_for_rewrite, &rule_sets, ) .unwrap() .constraints; - env::set_var("OPTIMIZATION", "0"); + env::set_var("OPTIMIZATIONS", "0"); let rewritten_expr_unoptimized = rewrite_model( - &Model::new(HashMap::new(), nested_expr, Default::default()), + &model_for_rewrite_unoptimized, &rule_sets, ) .unwrap() .constraints; + env::remove_var("OPTIMIZATIONS"); + + let info_file_name_optimized = format!("rewrite_solve_xyz_optimized_{}", num_or_clauses); + let info_file_name_unoptimized = format!("rewrite_solve_xyz_unoptimized_{}", num_or_clauses); + + save_stats_json( + model_for_rewrite.context, + "tests", + &info_file_name_optimized, + ); + save_stats_json( + model_for_rewrite_unoptimized.context, + "tests", + &info_file_name_unoptimized, + ); + // Check if the expression is in its simplest form let expr = rewritten_expr.clone(); assert!(is_simple(&expr)); @@ -1038,6 +1058,8 @@ fn rewrite_solve_xyz_parameterized() { }, ); + + let solver: Solver = Solver::new(adaptors::Minion::new()); let solver = solver.load_model(model).unwrap(); solver.solve(Box::new(|_| true)).unwrap(); From da2751dd1f7f7da3a89819e3004b9d8bcd92ec72 Mon Sep 17 00:00:00 2001 From: Kieranoski702 Date: Tue, 2 Apr 2024 17:06:27 +0100 Subject: [PATCH 4/5] Format --- conjure_oxide/tests/rewrite_tests.rs | 32 +++++++++++----------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/conjure_oxide/tests/rewrite_tests.rs b/conjure_oxide/tests/rewrite_tests.rs index 06c5c9be3e..7f4a8d04b7 100644 --- a/conjure_oxide/tests/rewrite_tests.rs +++ b/conjure_oxide/tests/rewrite_tests.rs @@ -969,34 +969,30 @@ fn rewrite_solve_xyz_parameterized() { let nested_expr = Expression::Or(Metadata::new(), or_exprs); let model_for_rewrite = Model::new(HashMap::new(), nested_expr.clone(), Default::default()); - let model_for_rewrite_unoptimized = Model::new(HashMap::new(), nested_expr.clone(), Default::default()); + let model_for_rewrite_unoptimized = + Model::new(HashMap::new(), nested_expr.clone(), Default::default()); // Apply rewrite function to the nested expression - let rewritten_expr = rewrite_model( - &model_for_rewrite, - &rule_sets, - ) - .unwrap() - .constraints; + let rewritten_expr = rewrite_model(&model_for_rewrite, &rule_sets) + .unwrap() + .constraints; env::set_var("OPTIMIZATIONS", "0"); - let rewritten_expr_unoptimized = rewrite_model( - &model_for_rewrite_unoptimized, - &rule_sets, - ) - .unwrap() - .constraints; + let rewritten_expr_unoptimized = rewrite_model(&model_for_rewrite_unoptimized, &rule_sets) + .unwrap() + .constraints; env::remove_var("OPTIMIZATIONS"); - let info_file_name_optimized = format!("rewrite_solve_xyz_optimized_{}", num_or_clauses); - let info_file_name_unoptimized = format!("rewrite_solve_xyz_unoptimized_{}", num_or_clauses); - + let info_file_name_optimized = format!("rewrite_solve_xyz_optimized_{}", num_or_clauses); + let info_file_name_unoptimized = + format!("rewrite_solve_xyz_unoptimized_{}", num_or_clauses); + save_stats_json( model_for_rewrite.context, "tests", - &info_file_name_optimized, + &info_file_name_optimized, ); save_stats_json( model_for_rewrite_unoptimized.context, @@ -1058,8 +1054,6 @@ fn rewrite_solve_xyz_parameterized() { }, ); - - let solver: Solver = Solver::new(adaptors::Minion::new()); let solver = solver.load_model(model).unwrap(); solver.solve(Box::new(|_| true)).unwrap(); From 02e9234cc7072759e1adc0fd6fcf6902f7a0efd9 Mon Sep 17 00:00:00 2001 From: Kieranoski702 Date: Tue, 2 Apr 2024 17:52:31 +0100 Subject: [PATCH 5/5] Add python script for generating graphs in test dir --- .gitignore | 1 + .../plot_rewriter_optimization_performance.py | 97 +++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 conjure_oxide/tests/plot_rewriter_optimization_performance.py diff --git a/.gitignore b/.gitignore index 025ddfe0f3..7c5eb067d3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ conjure_oxide/tests/**/*.generated.* conjure_oxide/tests/**/*.generated-parse.* conjure_oxide/tests/**/*.generated-rewrite.* conjure_oxide/tests/**/*.generated-minion.* +conjure_oxide/tests/*.png *-stats.json diff --git a/conjure_oxide/tests/plot_rewriter_optimization_performance.py b/conjure_oxide/tests/plot_rewriter_optimization_performance.py new file mode 100644 index 0000000000..5b8f7d6726 --- /dev/null +++ b/conjure_oxide/tests/plot_rewriter_optimization_performance.py @@ -0,0 +1,97 @@ +import json +import matplotlib.pyplot as plt + + +def load_data_from_file(file_path): + with open(file_path, "r") as file: + return json.load(file) + + +def plot_performance_gain(data): + x = [key for key in sorted(data.keys())] + y = [data[key]["performance_gain"] for key in sorted(data.keys())] + + plt.figure(figsize=(8, 6)) + plt.plot(x, y, marker="o") + plt.xlabel("Number of OR Clauses") + plt.ylabel("Performance Gain (%)") + plt.title("Performance Gain between Optimized and Unoptimized Versions") + plt.grid(True) + plt.savefig("performance_gain.png") + plt.close() + + +def plot_rule_application_savings(data): + x = [key for key in sorted(data.keys())] + y = [data[key]["rule_application_savings"] for key in sorted(data.keys())] + + plt.figure(figsize=(8, 6)) + plt.plot(x, y, marker="o", color="g") + plt.xlabel("Number of OR Clauses") + plt.ylabel("Rule Application Savings (%)") + plt.title("Rule Application Savings between Optimized and Unoptimized Versions") + plt.grid(True) + plt.savefig("rule_application_savings.png") + plt.close() + + +def main(): + output_files = [ + "rewrite_solve_xyz_optimized_1-stats.json", + "rewrite_solve_xyz_optimized_2-stats.json", + "rewrite_solve_xyz_optimized_3-stats.json", + "rewrite_solve_xyz_optimized_4-stats.json", + "rewrite_solve_xyz_unoptimized_1-stats.json", + "rewrite_solve_xyz_unoptimized_2-stats.json", + "rewrite_solve_xyz_unoptimized_3-stats.json", + "rewrite_solve_xyz_unoptimized_4-stats.json", + ] + + results = {} + optimized_performance = [] + unoptimized_performance = [] + optimized_rule_applications = [] + unoptimized_rule_applications = [] + + for file_name in output_files: + with open(file_name, "r") as file: + data = json.load(file) + if "unoptimized" in file_name: + unoptimized_performance.append( + data["stats"]["rewriterRuns"][0]["rewriterRunTime"]["nanos"] + + data["stats"]["rewriterRuns"][0]["rewriterRunTime"]["secs"] * 1e9 + ) + unoptimized_rule_applications.append( + data["stats"]["rewriterRuns"][0]["rewriterRuleApplicationAttempts"] + ) + else: + optimized_performance.append( + data["stats"]["rewriterRuns"][0]["rewriterRunTime"]["nanos"] + + data["stats"]["rewriterRuns"][0]["rewriterRunTime"]["secs"] * 1e9 + ) + optimized_rule_applications.append( + data["stats"]["rewriterRuns"][0]["rewriterRuleApplicationAttempts"] + ) + + for i in range(4): + performance_gain = ( + (unoptimized_performance[i] - optimized_performance[i]) + / optimized_performance[i] + * 100 + ) + rule_application_savings = ( + (unoptimized_rule_applications[i] - optimized_rule_applications[i]) + / unoptimized_rule_applications[i] + * 100 + ) + results[i + 1] = { + "performance_gain": performance_gain, + "rule_application_savings": rule_application_savings, + } + + plot_performance_gain(results) + plot_rule_application_savings(results) + + +if __name__ == "__main__": + main()