-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simplify eggspressions #210
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is rad, @genos !! Sure, it is a little funny to simplify via stringification, but it's a lot cleaner than having to rewrite all that logic using the enums directly. Two things:
- I'd be interested in simple benchmarks to track performance. I'm not too worried about regression here but would be good to know, given how often it's invoked elsewhere.
- (see other comment)
Thanks, @kalzoo! Re:
What did you have in mind? A |
That could work, so long as it's only randomly generated once and then committed - maybe a few of them for good measure. We'd want benchmark inputs to be static so that they can provide meaningful feedback to development. |
This would be easier if Edit: see 6b83e53 |
Actually, why not just reuse the |
@kalzoo re: generating random expressions to benchmark simplifying, I've tried adding
main.rsuse quil_rs::{
expression::{Expression, ExpressionFunction, InfixOperator, PrefixOperator},
instruction::MemoryReference,
};
use rand::{rngs::StdRng, Rng, SeedableRng};
use std::{fs::File, io::Write, str::FromStr};
// rand::dists::Alphanumeric isn't what we need
fn rand_string(rng: &mut impl Rng) -> String {
(0..10).map(|_| rng.gen_range('a'..'z')).collect()
}
fn rand_expr(rng: &mut impl Rng, max_depth: usize) -> Expression {
if max_depth == 0 {
Expression::PiConstant
} else {
match rng.gen_range(0..7) {
0 => {
let name = rand_string(rng);
let index = rng.gen();
Expression::Address(MemoryReference { name, index })
}
1 => {
let function = match rng.gen_range(0..5) {
0 => ExpressionFunction::Cis,
1 => ExpressionFunction::Cosine,
2 => ExpressionFunction::Exponent,
3 => ExpressionFunction::Sine,
_ => ExpressionFunction::SquareRoot,
};
let expression = Box::new(rand_expr(rng, max_depth / 2));
Expression::FunctionCall {
function,
expression,
}
}
2 => {
let left = Box::new(rand_expr(rng, max_depth / 2));
let operator = match rng.gen_range(0..5) {
0 => InfixOperator::Caret,
1 => InfixOperator::Plus,
2 => InfixOperator::Minus,
3 => InfixOperator::Slash,
_ => InfixOperator::Star,
};
let right = Box::new(rand_expr(rng, max_depth / 2));
Expression::Infix {
left,
operator,
right,
}
}
3 => {
let re = rng.gen::<f64>();
let im = rng.gen::<f64>();
Expression::Number(num_complex::Complex64 { re, im })
}
4 => Expression::PiConstant,
5 => {
let operator = if rng.gen() {
PrefixOperator::Plus
} else {
PrefixOperator::Minus
};
let expression = Box::new(rand_expr(rng, max_depth / 2));
Expression::Prefix {
operator,
expression,
}
}
_ => Expression::Variable(rand_string(rng)),
}
}
}
fn main() {
let mut rng = StdRng::seed_from_u64(8675309);
let mut out = File::create("expressions.txt").expect("We should be able to create a file.");
for _ in 0..1_000 {
let expression = rand_expr(&mut rng, 256);
match Expression::from_str(&expression.to_string()) {
Ok(_) => write!(out, "{}", expression).expect("We should be able to write to the file"),
Err(e) => panic!("{expression} => {e}"),
}
}
} |
Further |
Ok! This now passes all my local testing and is about where I think it should be. Pinging folks for re-reviews. In order to get round-tripping to go (#215), I've added the |
Even simpler now; I removed the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small comments - I think it's just about good to go! We can add benchmarks with a follow-on PR - it'll be good to have some focused on simplification.
Perhaps related: we still have |
I'm not too worried about that, both of the warnings are safely ignorable at the moment, even if they add noise to CI results. We can fix them off
nvm, was quick to get |
17f8b17
to
81f3193
Compare
🚨 Squashing and merging 🚨 |
Thanks for your great work on this @genos ! This is both more thorough and more maintainable than we would have made any simplification rules by hand. And now we're using |
This
is a DRAFT of usingusesegg
to tackle #208.TODO:
egg
in a private module to doExpression::simplify
"(neg <number>)"
edge case in simplification, not withif let Ok(number) = …
workaround†panic!
orexpect!
†
I haven't figured out how to manage this one; any help from reviewers would be much appreciated.Fixed in d4f7fbf