Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
2835eec
extract the construction of shared information
kavigupta Jun 2, 2025
b8460a8
Merge remote-tracking branch 'origin/main' into extract-construct-shared
kavigupta Jun 2, 2025
185b5b8
fix clippy errors
kavigupta Jun 2, 2025
8a6947b
Merge branch 'fix-clippy' into extract-construct-shared
kavigupta Jun 2, 2025
338f7ce
fix clippy
kavigupta Jun 2, 2025
b72224e
Merge remote-tracking branch 'origin/main' into extract-construct-shared
kavigupta Jun 3, 2025
17d2a4e
extract the abstraction expansion function
kavigupta Jun 3, 2025
e056ccb
add ability to turn off pruning in the expand operation
kavigupta Jun 3, 2025
4013c8f
add smc stitch
kavigupta Jun 3, 2025
8098ef7
extract
kavigupta Jun 3, 2025
db3b09e
fixes
kavigupta Jun 3, 2025
36cb86b
extract out
kavigupta Jun 4, 2025
58467b7
upadte
kavigupta Jun 4, 2025
9513678
actualy output stuff
kavigupta Jun 4, 2025
b667515
some refactoring
kavigupta Jun 4, 2025
7a13478
use variable
kavigupta Jun 5, 2025
ae3222c
parameters
kavigupta Jun 5, 2025
914b254
bunch of undos
kavigupta Jun 5, 2025
7ab0c3c
update
kavigupta Jun 5, 2025
2fedaf5
fix
kavigupta Jun 5, 2025
64abf0e
update
kavigupta Jun 5, 2025
a03ec19
update
kavigupta Jun 5, 2025
a3872bf
make configurable
kavigupta Jun 5, 2025
507d300
optimizations
kavigupta Jun 5, 2025
fb9b983
update
kavigupta Jun 5, 2025
081cc9f
more optimizations
kavigupta Jun 5, 2025
f66f1ad
fix logweighting
kavigupta Jun 6, 2025
0b396da
clean
kavigupta Jun 6, 2025
e3cdf2d
update rule
kavigupta Jun 10, 2025
a38d81b
add better docs
kavigupta Jun 11, 2025
d4b2de5
fix
kavigupta Jun 11, 2025
a8b25dd
Merge branch 'main' into smc
kavigupta Jun 11, 2025
9e74f26
allow ivars to be rewritten into other ivars (#189)
kavigupta Jun 11, 2025
ecf8b09
revert a bunch of refactoring
kavigupta Jun 11, 2025
05ad0ef
clean up
kavigupta Jun 11, 2025
fdd2582
faster
kavigupta Jun 11, 2025
0313a14
fix clippy
kavigupta Jun 11, 2025
b3be68c
switch to sorting to reduce time spent cloning
kavigupta Jun 11, 2025
508f6b3
remove commented out old code
kavigupta Jun 11, 2025
3819a7d
update
kavigupta Jun 11, 2025
b87e4d6
improve algorithm
kavigupta Jun 11, 2025
a5314a3
fix clippy
kavigupta Jun 12, 2025
fcceff2
Merge branch 'main' into smc
kavigupta Jun 16, 2025
ce35ab0
add back modppl, fix build
kavigupta Jun 16, 2025
980481e
update smc
kavigupta Jun 17, 2025
840a7d9
cache utility so it's not constantly recomputed
kavigupta Jun 17, 2025
6384d17
optimize bottom up utility correction
kavigupta Jun 17, 2025
c5ade13
Merge branch 'optimize-bottom-up-utility-correction' into smc
kavigupta Jun 17, 2025
968bfaf
add slightly harsher stopping condition
kavigupta Jun 17, 2025
5af1b2a
update
kavigupta Jun 18, 2025
8b18d1a
Merge remote-tracking branch 'origin/main' into smc
kavigupta Jun 18, 2025
bd53775
Merge remote-tracking branch 'origin/main' into smc
kavigupta Jun 24, 2025
565287b
fixes
kavigupta Jun 25, 2025
a0a27ff
tdfa using options
kavigupta Jun 25, 2025
4ab8703
fix
kavigupta Jun 25, 2025
144ce33
Merge remote-tracking branch 'origin/main' into smc
kavigupta Jun 25, 2025
38d5db4
Merge branch 'main' into smc
kavigupta Jun 26, 2025
d8df4e1
improve/fix
kavigupta Jun 26, 2025
194bf6c
Merge
kavigupta Jul 15, 2025
71ee5e6
Merge commit '8aca6eb' into smc-merged
kavigupta Jul 15, 2025
8f85f25
add some tests
kavigupta Jul 15, 2025
a4183d4
update dfa (#229)
kavigupta Jul 14, 2025
4a0e33b
Merge branch 'smc' into smc-merged
kavigupta Jul 15, 2025
c157f51
Symvars bug (#224)
kavigupta Jul 11, 2025
d67a722
pull in some changes
kavigupta Jul 15, 2025
052a316
remove test
kavigupta Jul 14, 2025
cc093f8
Merge commit '756d68bbd886ba3e84bf88e1edaa97bc74a87eee' into smc
kavigupta Jul 15, 2025
8d8ce05
Merge branch 'main' into smc
kavigupta Jul 15, 2025
df9e5f8
symbolic variables
kavigupta Jul 23, 2025
f088a64
TDFA support?
kavigupta Jul 23, 2025
b4e5a59
TDFA support try 2?
kavigupta Jul 23, 2025
6003aa1
fix
kavigupta Jul 23, 2025
88b0147
undo a bunch of unnecessary changes
kavigupta Jul 23, 2025
0679dc2
cilppy
kavigupta Jul 23, 2025
7dbfabc
add pruning
kavigupta Jul 23, 2025
6e30072
clippy
kavigupta Jul 23, 2025
a30ea15
clean tdfa
kavigupta Jul 23, 2025
a6a2171
clippy
kavigupta Jul 23, 2025
941cf43
upadte expected output
kavigupta Jul 23, 2025
129325e
Merge remote-tracking branch 'origin/main' into smc
kavigupta Jul 23, 2025
296fb3e
fix
kavigupta Jul 23, 2025
7268752
handle expands to variables separately
kavigupta Jul 23, 2025
16e66a4
more general syntactic expansion
kavigupta Jul 23, 2025
9b3131f
Merge branch 'more-general-syntactic-expansion' into smc
kavigupta Jul 23, 2025
3b9b928
fix
kavigupta Jul 23, 2025
294386b
Merge remote-tracking branch 'origin/main' into smc
kavigupta Jul 23, 2025
a9df3b7
types
kavigupta Jul 23, 2025
0641f27
update
kavigupta Jul 23, 2025
7e4644a
clean up
kavigupta Jul 23, 2025
e91a36c
can just assert, we checked already
kavigupta Jul 23, 2025
8ea8049
clean up
kavigupta Jul 23, 2025
033be27
fix
kavigupta Jul 23, 2025
043e57b
update
kavigupta Jul 23, 2025
548ad60
Merge remote-tracking branch 'origin/main' into smc
kavigupta Jul 23, 2025
9408581
clean
kavigupta Jul 23, 2025
05f1caf
move compatible locations out of expansion (necessary to get speeds c…
kavigupta Jul 23, 2025
0224a54
Merge branch 'move-expansion' into smc
kavigupta Jul 23, 2025
2e08df1
clean
kavigupta Jul 23, 2025
e077c16
Merge remote-tracking branch 'origin/main' into smc
kavigupta Aug 6, 2025
d0aa0c7
Merge remote-tracking branch 'origin/main' into smc
kavigupta Aug 11, 2025
56db6f1
add smc benchmark
kavigupta Aug 11, 2025
cb5c0ae
Merge remote-tracking branch 'origin/main' into smc
kavigupta Aug 13, 2025
e20ce56
update
kavigupta Aug 13, 2025
1100e41
wrap ziptrie in an option rather than unwrapping, lets you handle 0 a…
kavigupta Aug 14, 2025
8db86c3
Merge branch 'zip-trie-option' into smc
kavigupta Aug 14, 2025
0cd2cb6
disable pruning
kavigupta Aug 15, 2025
ab2f141
assertion
kavigupta Aug 15, 2025
ec88f58
Revert "disable pruning"
kavigupta Aug 15, 2025
022e03f
disable SMC
kavigupta Aug 15, 2025
87b422a
Merge remote-tracking branch 'origin/main' into smc
kavigupta Aug 19, 2025
9aa3363
Merge remote-tracking branch 'origin/main' into smc
kavigupta Sep 4, 2025
3b27bd0
fix build issue
kavigupta Sep 4, 2025
fd7d474
Merge remote-tracking branch 'origin/main' into smc
kavigupta Sep 4, 2025
e86c31c
Smc fixes rewrite (#253)
kavigupta Sep 4, 2025
0298fd0
fix clippy
kavigupta Sep 4, 2025
b4405d2
set default to 50
kavigupta Sep 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ rustc-hash = "1.1.0"
# lambdas = "0.2.0"
lambdas = { git = "https://github.com/mlb2251/lambdas", rev = "2c9bfd0"}
test-case = "3.3.1"
modppl = "0.3.0"
rand_chacha = "0.9.0"
shlex = "1.3.0"

Expand Down
1,694 changes: 1,694 additions & 0 deletions data/expected_outputs/10-smc.json

Large diffs are not rendered by default.

1,048 changes: 1,048 additions & 0 deletions data/expected_outputs/smc-dials.json

Large diffs are not rendered by default.

417 changes: 417 additions & 0 deletions data/expected_outputs/smc-furniture-small.json

Large diffs are not rendered by default.

2,119 changes: 2,119 additions & 0 deletions data/expected_outputs/smc-furniture.json

Large diffs are not rendered by default.

964 changes: 964 additions & 0 deletions data/expected_outputs/smc-nuts-bolts.json

Large diffs are not rendered by default.

1,603 changes: 1,603 additions & 0 deletions data/expected_outputs/smc-wheels.json

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions data/regression/furniture-small.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
"(T (repeat (repeat (T (C (C (T (T c (M 2 0 0 0)) (M 1.125 0 0 0)) (T (T c (M 2 0 0 0)) (M 1.625 0 0 0))) (T r (M 0.84375 0 0 0))) (M 1 0 0 0)) 1 (M 1 0 0 0)) 1 (M 1 0 0 0)) (M 1 0 -6.9375 0))",
"(T (repeat (repeat (T (C (T r (M 1.125 0 0 0)) (T c (M 0.84375 0 0 0))) (M 1 0 0 0)) 1 (M 1 0 0 0)) 1 (M 1 0 0 0)) (M 1 0 -7.1875 0))",
"(T (repeat (repeat (T (C (T (T (repeat (T l (M 1 0 -0.5 1.20711)) 8 (M 1 0.785398 0 0)) (M 0.75 0 0 0)) (M 1.125 0 0 0)) (T c (M 0.84375 0 0 0))) (M 1 0 0 0)) 1 (M 1 0 0 0)) 1 (M 1 0 0 0)) (M 1 0 -7.1875 0))",
"(T (repeat (repeat (T (C (T (T (repeat (T l (M 1 0 -0.5 1.20711)) 8 (M 1 0.785398 0 0)) (M 0.75 0 0 0)) (M 1.125 0 0 0)) (T c (M 0.84375 0 0 0))) (M 1 0 0 0)) 2 (M 1 0 14.375 0)) 1 (M 1 0 0 0)) (M 1 0 -7.1875 0))",
"(C (C (T (T (repeat (repeat (T (C (T (T (r_s 13.5 3) (M 1 0 0 0)) (M 1 0 0 0)) (T (repeat (repeat (T (T c (M 0.84375 0 0 0)) (M 1 0 0 0)) 2 (M 1 0 5.625 0)) 1 (M 1 0 0 0)) (M 1 0 -2.8125 0))) (M 1 0 0 1.5)) 1 (M 1 0 0 0)) 2 (M 1 0 0 3.75)) (M 1 0 0 0)) (M 1 0 0 0.75)) (T (T (r_s 15 8.25) (M 1 0 0 4.125)) (M 1 0 0 0))) (T (repeat (repeat (T (T (T (T l (M 1 0 -0.5 0)) (M 1 1.5708 0 0)) (M 3 0 0 0)) (M 1 0 0 -1.5)) 3 (M 1 0 7.5 0)) 1 (M 1 0 0 0)) (M 1 0 -7.5 0)))",
"(C (C (T (T (repeat (repeat (T (C (T (T (r_s 13.5 3) (M 1 0 0 0)) (M 1 0 0 0)) (T (repeat (repeat (T (T c (M 0.84375 0 0 0)) (M 1 0 0 0)) 2 (M 1 0 5.625 0)) 1 (M 1 0 0 0)) (M 1 0 -2.8125 0))) (M 1 0 0 1.5)) 1 (M 1 0 0 0)) 2 (M 1 0 0 3.75)) (M 1 0 0 0)) (M 1 0 0 0.75)) (T (T (r_s 15 8.25) (M 1 0 0 4.125)) (M 1 0 0 0))) (T (repeat (repeat (T (T (T (T l (M 1 0 -0.5 0)) (M 1 1.5708 0 0)) (M 6 0 0 0)) (M 1 0 0 -3)) 2 (M 1 0 15 0)) 1 (M 1 0 0 0)) (M 1 0 -7.5 0)))",
"(C (T (repeat (repeat (T (C (T (T (r_s 9 4) (M 1 0 0 0)) (M 1 0 0 0)) (T (repeat (repeat (T (C (T (T (repeat (T l (M 1 0 -0.5 1.20711)) 8 (M 1 0.785398 0 0)) (M 0.75 0 0 0)) (M 1.125 0 0 0)) (T c (M 0.84375 0 0 0))) (M 1 0 0 0)) 2 (M 1 0 2.875 0)) 1 (M 1 0 0 0)) (M 1 0 -1.4375 0))) (M 1 0 0 0)) 1 (M 1 0 0 0)) 4 (M 1 0 0 5)) (M 1 0 0 -7.5)) (T (T (r_s 11 21) (M 1 0 0 0)) (M 1 0 0 0)))",
"(C (C (T (T (repeat (repeat (T (C (T (T (r_s 13.5 3) (M 1 0 0 0)) (M 1 0 0 0)) (T (repeat (repeat (T (T r (M 0.84375 0 0 0)) (M 1 0 0 0)) 2 (M 1 0 5.625 0)) 1 (M 1 0 0 0)) (M 1 0 -2.8125 0))) (M 1 0 0 1.5)) 1 (M 1 0 0 0)) 2 (M 1 0 0 3.75)) (M 1 0 0 0)) (M 1 0 0 0.75)) (T (T (r_s 15 8.25) (M 1 0 0 4.125)) (M 1 0 0 0))) (T (repeat (repeat (T (T (T (T l (M 1 0 -0.5 0)) (M 1 1.5708 0 0)) (M 6 0 0 0)) (M 1 0 0 -3)) 4 (M 1 0 5 0)) 1 (M 1 0 0 0)) (M 1 0 -7.5 0)))"
]
17 changes: 13 additions & 4 deletions src/bin/benchmark_cogsci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@ struct Args {
/// Number of repetitions
#[clap(short, long, default_value = "1")]
count: usize,
#[clap(short, long, default_value = "false")]
smc: bool,
}

fn main() {
let args = Args::parse();
let mut geomeans = Vec::with_capacity(args.count);
for _ in 0..args.count {
let geo = benchmark_cogsci_geomean();
let geo = benchmark_cogsci_geomean(args.smc);
println!("{geo:.2}");
geomeans.push(geo);
}
Expand All @@ -28,7 +30,7 @@ fn main() {
}
}

fn benchmark_cogsci_geomean() -> f64 {
fn benchmark_cogsci_geomean(smc: bool) -> f64 {
let cogsci_dir = PathBuf::from("data/cogsci");
// Check if directory exists
if !cogsci_dir.exists() {
Expand All @@ -54,8 +56,15 @@ fn benchmark_cogsci_geomean() -> f64 {
}
// Configuration for compression: -a3 -i10
let mut cfg = MultistepCompressionConfig::default();
cfg.step.max_arity = 3; // -a3
cfg.iterations = 10; // -i10
if smc {
cfg.step.smc = true;
cfg.step.smc_particles = 1_000;
cfg.step.smc_extra_steps = 25;
cfg.iterations = 3; // -i3
} else {
cfg.step.max_arity = 3; // -a3
cfg.iterations = 10; // -i10
}
cfg.silent = true; // Reduce output noise
let mut compression_times = Vec::new();
for file_path in json_files.iter() {
Expand Down
101 changes: 83 additions & 18 deletions src/compression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,43 @@ pub struct CompressionStepConfig {
#[clap(long)]
pub quiet: bool,

// Fused lambda tags
/// Fused lambda tags
#[clap(long, value_parser = clap::value_parser!(FusedLambdaTags), default_value="")]
pub fused_lambda_tags: FusedLambdaTags,

/// If true, we will use Sequential Monte Carlo (SMC) to sample patterns
#[clap(long)]
pub smc: bool,

/// Seed for the random number generator used in SMC
#[clap(long, default_value = "0")]
pub seed: u64,

/// Number of particles to use in SMC
#[clap(long, default_value = "1000")]
pub smc_particles: usize,

/// If true, we will use "fast utility" in SMC, which is a heuristic that
/// estimates the utility of a pattern without fully rewriting it.
#[clap(long)]
pub smc_fast_utility: bool,

/// Number of smc steps we will run after finding a best pattern
/// before stopping. e.g., if --smc-extra-step=50, we will stop at
/// step 69 if a best pattern is found at step 19.
#[clap(long, default_value = "50")]
pub smc_extra_steps: usize,

/// Number of expansions to make before recalculating the utility of a pattern
/// in SMC. This is used to control the tradeoff between exploration and exploitation.
#[clap(long, default_value = "1")]
pub smc_expand_per_step: usize,

/// SMC temperature, used to control the exploration-exploitation tradeoff.
/// A higher temperature means more exploration, while a lower temperature means more exploitation.
#[clap(long, default_value = "1.0")]
pub smc_temperature: f32,

/// TDFA settings
#[clap(flatten)]
pub tdfa: TDFAConfig,
Expand Down Expand Up @@ -510,6 +543,28 @@ impl Pattern {
tracked: follow.is_some(),
}
}

#[allow(clippy::too_many_arguments)]
fn single_var(corpus_span: &Span, cost_fn: &ExprCost, cost_of_node_all: &[Cost], num_paths_to_node: &[Cost], tdfa_global_annotations: &Option<TDFAGlobalAnnotations>, set: &ExprSet, cfg: &CompressionStepConfig, follow: &Option<Invention>) -> Self {
let mut pattern = Self::single_hole(corpus_span, cost_fn, cost_of_node_all, num_paths_to_node, tdfa_global_annotations, set, cfg, follow);
let hole_zid = pattern.holes.pop().unwrap();
pattern.pattern_args.add_variable_at(hole_zid, 0);
pattern
}

pub fn single_var_from_shared(shared: &SharedData) -> Self {
Self::single_var(
&shared.corpus_span,
&shared.cost_fn,
&shared.cost_of_node_all,
&shared.num_paths_to_node,
&shared.tdfa_global_annotations,
&shared.set,
&shared.cfg,
&None, // no follow in single var, since this is only used by SMC
)
}

/// convert pattern to an Expr
fn to_expr(&self, shared: &SharedData) -> ExprOwned {
let mut set = ExprSet::empty(Order::ChildFirst, false, false);
Expand Down Expand Up @@ -1172,7 +1227,7 @@ pub struct FinishedPattern {

impl FinishedPattern {
//#[inline(never)]
fn new(pattern: Pattern, shared: &SharedData) -> Self {
pub fn new(pattern: Pattern, shared: &SharedData) -> Self {
let arity = pattern.pattern_args.arity();
let usages = pattern.match_locations.iter().map(|loc| shared.num_paths_to_node[*loc]).sum();
let compressive_utility = compressive_utility(&pattern,shared);
Expand Down Expand Up @@ -1380,7 +1435,7 @@ pub struct CompressionStepResult {
}

impl CompressionStepResult {
fn new(done: FinishedPattern, inv_name: &str, shared: &mut SharedData, very_first_cost: Cost, name_mapping: &[(String,String)], dc_comparison_millis: Option<usize>) -> Self {
pub fn new(done: FinishedPattern, inv_name: &str, shared: &mut SharedData, very_first_cost: Cost, name_mapping: &[(String,String)], dc_comparison_millis: Option<usize>) -> Self {

let inv = done.to_invention(inv_name, shared);
let rewritten = rewrite_fast(&done, shared, &Node::Prim(inv.name.clone().into()), &shared.cost_fn);
Expand Down Expand Up @@ -1504,7 +1559,7 @@ fn utility_upper_bound(
/// to changes in size that come from rewriting with an invention. Currently this is just the
/// size of the abstraction itself
//#[inline(never)]
fn noncompressive_utility(
pub fn noncompressive_utility(
body_utility: Cost,
cfg: &CompressionStepConfig,
) -> Cost {
Expand Down Expand Up @@ -1580,7 +1635,7 @@ pub fn compressive_utility_from_marginals(
}

//#[inline(never)]
fn compressive_utility(pattern: &Pattern, shared: &SharedData) -> UtilityCalculation {
pub fn compressive_utility(pattern: &Pattern, shared: &SharedData) -> UtilityCalculation {

// * BASIC CALCULATION
// Roughly speaking compressive utility is num_usages(invention) * size(invention), however there are a few extra
Expand Down Expand Up @@ -1830,19 +1885,29 @@ pub fn multistep_compression_internal(
} else {
(format!("{}{}", cfg.abstraction_prefix, cfg.previous_abstractions + step_results.len()), cfg.step.follow.as_ref().map(|x| Invention::from_string("inv", x, cfg.step.follow_types.clone())))
};

// call actual compression
let res: Vec<CompressionStepResult> = compression_step(
&rewritten,
&inv_name,
&cfg,
&tasks,
&weights,
very_first_cost,
&name_mapping,
&step_results,
&follow_iter,
);
let res: Vec<CompressionStepResult> = if cfg.step.smc {
assert!(follow_iter.is_none());
smc::compression_step_smc(
&rewritten,
&inv_name,
&cfg,
&tasks,
&weights,
&step_results,
)
} else {
compression_step(
&rewritten,
&inv_name,
&cfg,
&tasks,
&weights,
very_first_cost,
&name_mapping,
&step_results,
&follow_iter,
)
};

if !res.is_empty() {
// rewrite with the invention
Expand Down
96 changes: 93 additions & 3 deletions src/expansion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use itertools::Itertools;
use lambdas::{Idx, Node, Symbol, Tag, ZId, ZNode};
use rustc_hash::{FxHashMap, FxHashSet};

use crate::{invalid_metavar_location, Arg, Cost, LocationsForReusableArgs, Pattern, PatternArgs, SharedData, SymvarInfo, VariableType, ZIdExtension};
use crate::{compatible_locations, invalid_metavar_location, Arg, Cost, LocationsForReusableArgs, Pattern, PatternArgs, SharedData, SymvarInfo, VariableType, ZIdExtension};

/// Tells us what a hole will expand into at this node.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
Expand Down Expand Up @@ -71,7 +71,7 @@ impl ExpandsTo {
#[inline]
pub fn local_expansion_utility(&self, shared: &SharedData) -> Cost {
let ExpandsTo(s) = self;
let res = match &s {
let res = match s {
ExpandsToInner::Lam(_) => shared.cost_fn.cost_lam,
ExpandsToInner::App => shared.cost_fn.cost_app,
ExpandsToInner::Var(_, _) => shared.cost_fn.cost_var,
Expand Down Expand Up @@ -162,11 +162,15 @@ pub fn expands_to_of_node(node: &Node) -> ExpandsTo {
pub fn get_syntactic_expansions(arg_of_loc: &FxHashMap<usize, Arg>, match_locations: Vec<usize>, sym_var_info: &Option<SymvarInfo>) -> Vec<(ExpandsTo, Vec<Idx>)> {
match_locations.into_iter()
.group_by(|loc| &arg_of_loc[loc].expands_to).into_iter()
.filter(|(expands_to, _)| sym_var_info.as_ref().is_none_or(|s| !expands_to.is_prim_symbol(s)))
.filter(|(expands_to, _)| valid_syntactic_expansion_loc(sym_var_info, expands_to))
.map(|(expands_to, locs)| (expands_to.clone(), locs.collect::<Vec<Idx>>()))
.collect::<Vec<_>>()
}

pub fn valid_syntactic_expansion_loc(sym_var_info: &Option<SymvarInfo>, expands_to: &ExpandsTo) -> bool {
sym_var_info.as_ref().is_none_or(|s| !expands_to.is_prim_symbol(s))
}


//#[inline(never)]
/// Return options for what abstraction arguments (aka ivars, #i) can expand into. When expanding to an ivar that
Expand Down Expand Up @@ -211,6 +215,92 @@ pub fn get_ivars_expansions(original_pattern: &Pattern, arg_of_loc: &FxHashMap<I
}


/* Perform expansions on variables -- largely for SMC */

pub fn perform_expansion_variable(
pattern: Pattern,
shared: &SharedData,
variable_ivar: i32,
expands_to: ExpandsTo,
) -> Option<Pattern> {
let mut pattern = pattern;
let mut expands_to = expands_to;

let variable_zids: Vec<usize> = pattern.pattern_args.remove_variable_at(variable_ivar, match &mut expands_to {
ExpandsTo(ExpandsToInner::IVar(i, _)) => {
Some(i)
}
_ => None,

});

let body_utility = pattern.body_utility + expands_to.local_expansion_utility(shared) * variable_zids.len() as Cost;
pattern.body_utility = body_utility;

let num_vars = pattern.pattern_args.arity() as i32;

for variable_zid in &variable_zids {
expands_to.add_variables(*variable_zid, &mut pattern.pattern_args);
expands_to.syntactic_expansion(&shared.extensions_of_zid[*variable_zid], |zid, i| {
pattern.pattern_args.add_variable_at(zid, num_vars + (i as i32));
});
}
Some (pattern)
}


pub fn get_num_variables(pattern: &Pattern) -> usize {
pattern.pattern_args.arity()
}


fn sample_in_range_without_value(max_range_excl: usize, avoid: i32, rng: &mut impl rand::Rng) -> Option<i32> {
if max_range_excl <= 1 {
return None; // no other variable to expand to
}
let mut new_ivar = rng.gen_range(0..max_range_excl - 1) as i32;
if new_ivar >= avoid {
new_ivar += 1; // skip the variable we are expanding
}
Some(new_ivar)
}

pub fn sample_variable_reuse_expansion(
pattern: &Pattern,
shared: &SharedData,
variable_ivar: i32,
match_location: usize,
rng: &mut impl rand::Rng,
) -> Option<(Pattern, ExpandsTo)> {
let new_ivar = sample_in_range_without_value(get_num_variables(pattern), variable_ivar, rng)?;
let zid_original = pattern.pattern_args.zid_for_ivar(variable_ivar);
let zid_new = pattern.pattern_args.zid_for_ivar(new_ivar);
let arg_of_loc_original = &shared.arg_of_zid_node[zid_original];
let arg_of_loc_new = &shared.arg_of_zid_node[zid_new];
if compatible_locations(
shared,
&[match_location],
arg_of_loc_original,
arg_of_loc_new,
pattern.pattern_args.type_for_ivar(new_ivar)
).is_empty() {
return None; // no compatible locations for the new ivar
}

let locs = compatible_locations(
shared,
&pattern.match_locations,
arg_of_loc_original,
arg_of_loc_new,
pattern.pattern_args.type_for_ivar(new_ivar)
);
assert!(!locs.is_empty());
let mut pattern = pattern.clone();
pattern.match_locations = locs;
let expands_to = ExpandsTo(ExpandsToInner::IVar(new_ivar, pattern.pattern_args.type_for_ivar(new_ivar)));
Some((pattern, expands_to))
}

pub fn svar_locations(original_pattern: &Pattern, arg_of_loc: &FxHashMap<Idx,Arg>, reusable_locs: FxHashSet<Idx>, sym_var_info: &SymvarInfo) -> Vec<Idx> {

let mut locations = vec![];
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub mod rewriting;
pub mod egraphs;
pub mod util;
pub mod formats;
pub mod smc;
pub mod tdfa;
pub mod expansion;
pub mod pattern_args;
Expand All @@ -18,6 +19,7 @@ pub use {
util::*,
formats::*,
lambdas::*,
smc::*,
tdfa::*,
expansion::*,
pattern_args::*,
Expand Down
Loading