-
Notifications
You must be signed in to change notification settings - Fork 9
/
trig.rs
160 lines (132 loc) · 5.66 KB
/
trig.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
use super::*;
use crate::test::prior_rules;
use ruler::{
enumo::{Filter, Ruleset, Workload},
recipe_utils::run_fast_forwarding,
Limits,
};
pub fn trig_rules() -> Ruleset<Trig> {
let limits = Limits {
iter: 3,
node: 2000000,
match_: 200_000,
};
let mut prior: Ruleset<Trig> = Ruleset::from_file("scripts/oopsla21/trig/complex.rules");
prior.extend(prior_rules());
let no_trig_2x = Filter::Invert(Box::new(Filter::Or(vec![
Filter::Contains("(sin (+ ?a ?a))".parse().unwrap()),
Filter::Contains("(cos (+ ?a ?a))".parse().unwrap()),
Filter::Contains("(tan (+ ?a ?a))".parse().unwrap()),
])));
let valid_trig = Filter::Invert(Box::new(Filter::Contains(
"(tan (/ PI 2))".parse().unwrap(),
)));
let t_ops = Workload::new(["sin", "cos", "tan"]);
let consts = Workload::new([
"0", "(/ PI 6)", "(/ PI 4)", "(/ PI 3)", "(/ PI 2)", "PI", "(* PI 2)",
]);
let app = Workload::new(["(op v)"]);
let trig_constants = app
.clone()
.plug("op", &t_ops)
.plug("v", &consts)
.filter(valid_trig);
let simple_terms = app.clone().plug("op", &t_ops).plug(
"v",
&Workload::new(["a", "(~ a)", "(+ PI a)", "(- PI a)", "(+ a a)"]),
);
let neg_terms = Workload::new(["(~ x)"]).plug("x", &simple_terms);
let squares = Workload::new(["(sqr x)"])
.plug("x", &app)
.plug("op", &t_ops)
.plug("v", &Workload::new(["a", "b"]));
let add = Workload::new(["(+ e e)", "(- e e)"]);
let sum_of_squares = add.plug("e", &squares);
let mut all = prior.clone();
let mut new = Ruleset::<Trig>::default();
let wkld1 = trig_constants;
println!("Starting 1");
let rules1 = run_fast_forwarding(wkld1.clone(), all.clone(), limits, limits);
all.extend(rules1.clone());
new.extend(rules1.clone());
let wkld2 = Workload::Append(vec![wkld1, simple_terms, neg_terms]);
println!("Starting 2");
let rules2 = run_fast_forwarding(wkld2.clone(), all.clone(), limits, limits);
all.extend(rules2.clone());
new.extend(rules2.clone());
let trimmed_wkld2 = wkld2.clone().filter(no_trig_2x);
let wkld3 = Workload::Append(vec![trimmed_wkld2.clone(), sum_of_squares.clone()]);
println!("Starting 3");
let rules3 = run_fast_forwarding(wkld3, all.clone(), limits, limits);
all.extend(rules3.clone());
new.extend(rules3.clone());
let non_square_filter = Filter::Invert(Box::new(Filter::Or(vec![
Filter::Contains("(* (cos ?x) (cos ?x))".parse().unwrap()),
Filter::Contains("(* (sin ?x) (sin ?x))".parse().unwrap()),
])));
let two_x_filter = Filter::Invert(Box::new(Filter::Contains("(+ ?x ?x)".parse().unwrap())));
let trivial_trig_filter = Filter::Invert(Box::new(Filter::Or(vec![
Filter::Contains("(cos (?op ?a ?b))".parse().unwrap()),
Filter::Contains("(sin (?op ?a ?b))".parse().unwrap()),
])));
let trig_no_sub_filter = Filter::Invert(Box::new(Filter::Or(vec![
Filter::Contains("(cos (- ?a ?b))".parse().unwrap()),
Filter::Contains("(sin (- ?a ?b))".parse().unwrap()),
])));
let t_ops = Workload::new(["sin", "cos"]);
let app = Workload::new(["(op v)"]);
let shift = Workload::new(["x", "(- 1 x)", "(+ 1 x)"]);
let scale_down = Workload::new(["x", "(/ x 2)"]);
let consts = Workload::new(["-2", "-1", "0", "1", "2"]);
let simple = app.clone().plug("op", &t_ops).plug(
"v",
&Workload::new(["a", "(- (/ PI 2) a)", "(+ (/ PI 2) a)", "(* 2 a)"]),
);
let trivial_squares = Workload::new(["(sqr x)"])
.plug("x", &app)
.plug("op", &t_ops)
.plug("v", &Workload::new(["a"]));
let two_var = app
.clone()
.plug("op", &t_ops)
.plug("v", &Workload::new(["a", "b", "(+ a b)", "(- a b)"]));
let sum_two_vars = Workload::new(["(+ x y)", "(- x y)"])
.plug("x", &two_var)
.plug("y", &two_var);
let prod_two_vars = Workload::new(["(* x y)"])
.plug("x", &two_var)
.plug("y", &two_var)
.filter(non_square_filter);
let sum_of_prod = Workload::new(["(+ x y)", "(- x y)"])
.plug("x", &prod_two_vars)
.plug("y", &prod_two_vars)
.filter(two_x_filter)
.filter(trivial_trig_filter);
let shifted_simple = shift.clone().plug("x", &simple);
let sum_and_prod = Workload::Append(vec![sum_two_vars.clone(), prod_two_vars.clone()]);
let shifted_simple_sqrs = Workload::Append(vec![shifted_simple, trivial_squares]);
let scaled_shifted_sqrs = scale_down.clone().plug("x", &shifted_simple_sqrs);
let scaled_sum_prod = scale_down.clone().plug("x", &sum_and_prod);
let two_var_no_sub = two_var.clone().filter(trig_no_sub_filter);
// Coangles
let wkld1 = Workload::Append(vec![simple, consts.clone()]);
let rules1 = run_fast_forwarding(wkld1.clone(), all.clone(), limits, limits);
all.extend(rules1.clone());
new.extend(rules1.clone());
// Power reduction
let wkld2 = Workload::Append(vec![scaled_shifted_sqrs, consts.clone()]);
let rules2 = run_fast_forwarding(wkld2.clone(), all.clone(), limits, limits);
all.extend(rules2.clone());
new.extend(rules2.clone());
// Product-to-sum
let wkld3 = Workload::Append(vec![scaled_sum_prod, consts.clone()]);
let rules3 = run_fast_forwarding(wkld3.clone(), all.clone(), limits, limits);
all.extend(rules3.clone());
new.extend(rules3.clone());
// Sums
let wkld4 = Workload::Append(vec![two_var_no_sub, sum_of_prod, consts.clone()]);
let rules4 = run_fast_forwarding(wkld4.clone(), all.clone(), limits, limits);
all.extend(rules4.clone());
new.extend(rules4.clone());
new
}