Skip to content
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

Add LP extractor #128

Merged
merged 7 commits into from
Apr 14, 2022
Merged

Add LP extractor #128

merged 7 commits into from
Apr 14, 2022

Conversation

mwillsey
Copy link
Member

This adds an Extractor that can do common subexpression elimination using linear programming. WIP

@mwillsey mwillsey mentioned this pull request Oct 13, 2021
@remysucre
Copy link
Member

It can be worth trying the cycle breaking encoding in https://arxiv.org/pdf/1012.1802.pdf (grep for "There is an additional subtlety in the above encoding"). It introduces n^2 variables where n is the number of enodes, but most of these variables will be inactive during ILP solving. It is complete, but will be slower than cycle-breaking a.la. tensat

@Bastacyclop
Copy link
Contributor

Hi! Do you know when this feature will be merged? Is it usable as-is, if I use this branch as my dependency? I'd like to play around with LP extraction.

@mwillsey
Copy link
Member Author

@Bastacyclop Yes this branch is usable and should be fully functional. I will try to merge it before the next release, and your feedback on using it would be very valuable!

@Bastacyclop
Copy link
Contributor

Bastacyclop commented Apr 8, 2022

Hi @mwillsey. I started using this branch and there might be a useful feature missing: an easy way to add an "expression" with multiple roots back into an e-graph (a DFG really).

let (best, bestRoots) = LpExtractor::new(&runner.egraph, AstSize).solve_multiple(&roots[..]);                  
{ // used to print the outcome
  let mut g: EGraph<SymbolLang, ()> = Default::default();                                    
  g.add_expr(&best); // this function does not work, it would be great to have `add_dfg`                                                       
  g.dot().to_svg("/tmp/final.svg").unwrap();                                                 
}

edit: this is what I implemented, not handling explanations:

fn add_dfg<L: Language, N: Analysis<L>>(dfg: &RecExpr<L>, egraph: &mut EGraph<L, N>) -> Vec<Id> {
    let nodes = dfg.as_ref();
    let mut eclasses = Vec::with_capacity(nodes.len());
    let mut is_root = (0..nodes.len()).map(|_| true).collect::<Vec<_>>(); // could use bit vector
    for node in nodes {
        eclasses.push(egraph.add(node.clone().map_children(|i| {
            is_root[usize::from(i)] = false;
            eclasses[usize::from(i)]
        })));
    }
    eclasses.iter().cloned().zip(is_root.iter().cloned())
        .filter_map(|(e, is_r)| if is_r { Some(e) } else { None }).collect::<Vec<_>>()
}

@Bastacyclop
Copy link
Contributor

Also, I am getting a crash on:

let v = &self.vars[&id];

When extracting from the following graph with 3 roots:
image
Any idea why?

@Bastacyclop
Copy link
Contributor

Bastacyclop commented Apr 8, 2022

Looks like your 'Canonicalize ids' commit was reverted somehow?

edit: canonicalizing the root ids given to the extraction function does fix the issue, but maybe this should be handled under the hood?

@mwillsey
Copy link
Member Author

mwillsey commented Apr 8, 2022

@Bastacyclop great catch, I think I just fixed it.

@mwillsey mwillsey merged commit 1717911 into main Apr 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants