Skip to content

Commit 5440779

Browse files
committed
compiler: add AstElemExt::and_or function
This totally eliminates the type_check method, and stops using the branch_prob field of AstElemExt. The next commit will delete a ton of unused stuff, which I didn't do here to minimize the amount of noise in this commit. Then I will start converting to use PositiveF64 rather than f64 everywhere. Then I will double-back and clean up this repetitive code.
1 parent 066bf99 commit 5440779

1 file changed

Lines changed: 107 additions & 46 deletions

File tree

src/policy/compiler.rs

Lines changed: 107 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
//! Optimizing compiler from concrete policies to Miniscript
66
//!
77
8+
#![allow(dead_code)] // will be removed in next commit
9+
#![allow(unused_variables)] // will be removed in next commit
10+
811
use core::num::NonZeroU32;
912
use core::{f64, fmt, mem};
1013
#[cfg(feature = "std")]
@@ -98,62 +101,114 @@ fn best_compilations_or<Pk: MiniscriptKey, Ctx: ScriptContext>(
98101
sat_prob: f64,
99102
dissat_prob: Option<f64>,
100103
) -> Result<(), CompilerError> {
101-
macro_rules! compile_tern {
102-
($a:expr, $b:expr, $c: expr, $w: expr) => {
103-
compile_tern(policy_cache, policy, ret, $a, $b, $c, $w, sat_prob, dissat_prob)?
104-
};
105-
}
106-
107104
let total = u32::from(subs[0].0) as f64 + u32::from(subs[1].0) as f64;
108105
let lw = u32::from(subs[0].0) as f64 / total;
109106
let rw = u32::from(subs[1].0) as f64 / total;
110107

111108
//and-or
112109
if let (Concrete::And(x), _) = (subs[0].1.as_ref(), subs[1].1.as_ref()) {
113-
let mut a1 = best_compilations(
110+
let a1 = best_compilations(
114111
policy_cache,
115112
x[0].as_ref(),
116113
lw * sat_prob,
117114
Some(dissat_prob.unwrap_or(0 as f64) + rw * sat_prob),
118115
)?;
119-
let mut a2 = best_compilations(policy_cache, x[0].as_ref(), lw * sat_prob, None)?;
116+
let a2 = best_compilations(policy_cache, x[0].as_ref(), lw * sat_prob, None)?;
120117

121-
let mut b1 = best_compilations(
118+
let b1 = best_compilations(
122119
policy_cache,
123120
x[1].as_ref(),
124121
lw * sat_prob,
125122
Some(dissat_prob.unwrap_or(0 as f64) + rw * sat_prob),
126123
)?;
127-
let mut b2 = best_compilations(policy_cache, x[1].as_ref(), lw * sat_prob, None)?;
124+
let b2 = best_compilations(policy_cache, x[1].as_ref(), lw * sat_prob, None)?;
128125

129-
let mut c =
130-
best_compilations(policy_cache, subs[1].1.as_ref(), rw * sat_prob, dissat_prob)?;
126+
let c = best_compilations(policy_cache, subs[1].1.as_ref(), rw * sat_prob, dissat_prob)?;
131127

132-
compile_tern!(&mut a1, &mut b2, &mut c, [lw, rw]);
133-
compile_tern!(&mut b1, &mut a2, &mut c, [lw, rw]);
128+
for a in a1.values() {
129+
for b in b2.values() {
130+
for c in c.values() {
131+
if let Ok(new_ext) = AstElemExt::and_or(a, b, c, lw, rw) {
132+
insert_best_wrapped(
133+
policy_cache,
134+
policy,
135+
ret,
136+
new_ext,
137+
sat_prob,
138+
dissat_prob,
139+
)?;
140+
}
141+
}
142+
}
143+
}
144+
for b in b1.values() {
145+
for a in a2.values() {
146+
for c in c.values() {
147+
if let Ok(new_ext) = AstElemExt::and_or(b, a, c, lw, rw) {
148+
insert_best_wrapped(
149+
policy_cache,
150+
policy,
151+
ret,
152+
new_ext,
153+
sat_prob,
154+
dissat_prob,
155+
)?;
156+
}
157+
}
158+
}
159+
}
134160
};
135161
if let (_, Concrete::And(x)) = (&subs[0].1.as_ref(), subs[1].1.as_ref()) {
136-
let mut a1 = best_compilations(
162+
let a1 = best_compilations(
137163
policy_cache,
138164
x[0].as_ref(),
139165
rw * sat_prob,
140166
Some(dissat_prob.unwrap_or(0 as f64) + lw * sat_prob),
141167
)?;
142-
let mut a2 = best_compilations(policy_cache, x[0].as_ref(), rw * sat_prob, None)?;
168+
let a2 = best_compilations(policy_cache, x[0].as_ref(), rw * sat_prob, None)?;
143169

144-
let mut b1 = best_compilations(
170+
let b1 = best_compilations(
145171
policy_cache,
146172
x[1].as_ref(),
147173
rw * sat_prob,
148174
Some(dissat_prob.unwrap_or(0 as f64) + lw * sat_prob),
149175
)?;
150-
let mut b2 = best_compilations(policy_cache, x[1].as_ref(), rw * sat_prob, None)?;
176+
let b2 = best_compilations(policy_cache, x[1].as_ref(), rw * sat_prob, None)?;
151177

152-
let mut c =
153-
best_compilations(policy_cache, subs[0].1.as_ref(), lw * sat_prob, dissat_prob)?;
178+
let c = best_compilations(policy_cache, subs[0].1.as_ref(), lw * sat_prob, dissat_prob)?;
154179

155-
compile_tern!(&mut a1, &mut b2, &mut c, [rw, lw]);
156-
compile_tern!(&mut b1, &mut a2, &mut c, [rw, lw]);
180+
for a in a1.values() {
181+
for b in b2.values() {
182+
for c in c.values() {
183+
if let Ok(new_ext) = AstElemExt::and_or(a, b, c, rw, lw) {
184+
insert_best_wrapped(
185+
policy_cache,
186+
policy,
187+
ret,
188+
new_ext,
189+
sat_prob,
190+
dissat_prob,
191+
)?;
192+
}
193+
}
194+
}
195+
}
196+
for b in b1.values() {
197+
for a in a2.values() {
198+
for c in c.values() {
199+
if let Ok(new_ext) = AstElemExt::and_or(b, a, c, rw, lw) {
200+
insert_best_wrapped(
201+
policy_cache,
202+
policy,
203+
ret,
204+
new_ext,
205+
sat_prob,
206+
dissat_prob,
207+
)?;
208+
}
209+
}
210+
}
211+
}
157212
};
158213

159214
let dissat_probs = |w: f64| -> Vec<Option<f64>> {
@@ -485,18 +540,13 @@ impl CompilerExtData {
485540
}
486541
}
487542

488-
fn and_or(a: Self, b: Self, c: Self) -> Self {
489-
let aprob = a.branch_prob.expect("andor, a prob must be set");
490-
let bprob = b.branch_prob.expect("andor, b prob must be set");
491-
let cprob = c.branch_prob.unwrap_or(0.0);
492-
543+
fn and_or(a: Self, b: Self, c: Self, lprob: f64, rprob: f64) -> Self {
493544
let adis = a
494545
.dissat_cost
495546
.expect("BUG: and_or first arg(a) must be dissatisfiable");
496-
debug_assert_eq!(aprob, bprob); //A and B must have same branch prob.
497547
Self {
498548
branch_prob: None,
499-
sat_cost: aprob * (a.sat_cost + b.sat_cost) + cprob * (adis + c.sat_cost),
549+
sat_cost: lprob * (a.sat_cost + b.sat_cost) + rprob * (adis + c.sat_cost),
500550
dissat_cost: c.dissat_cost.map(|cdis| adis + cdis),
501551
}
502552
}
@@ -543,18 +593,7 @@ impl CompilerExtData {
543593
Pk: MiniscriptKey,
544594
Ctx: ScriptContext,
545595
{
546-
match *fragment {
547-
Terminal::AndOr(ref a, ref b, ref c) => {
548-
let atype = get_child(&a.node, 0);
549-
let btype = get_child(&b.node, 1);
550-
let ctype = get_child(&c.node, 2);
551-
Self::and_or(atype, btype, ctype)
552-
}
553-
Terminal::Thresh(ref thresh) => {
554-
Self::threshold(thresh.k(), thresh.n(), |n| get_child(&thresh.data()[n].node, n))
555-
}
556-
_ => unreachable!(),
557-
}
596+
unreachable!()
558597
}
559598
}
560599

@@ -679,19 +718,41 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> AstElemExt<Pk, Ctx> {
679718

680719
/// andor(a,b,0) is a conjunction of a and b
681720
fn and_or_0(left: &Self, right: &Self) -> Result<Self, types::Error> {
682-
let left_ext_data = CompilerExtData { branch_prob: Some(1.0), ..left.comp_ext_data };
683-
let right_ext_data = CompilerExtData { branch_prob: Some(1.0), ..right.comp_ext_data };
684-
685721
Ok(Self {
686722
ms: Self::compose_typeck_only(Terminal::AndOr(
687723
Arc::clone(&left.ms),
688724
Arc::clone(&right.ms),
689725
Arc::new(Miniscript::FALSE),
690726
))?,
691727
comp_ext_data: CompilerExtData::and_or(
692-
left_ext_data,
693-
right_ext_data,
728+
left.comp_ext_data,
729+
right.comp_ext_data,
694730
CompilerExtData::FALSE,
731+
1.0,
732+
0.0,
733+
),
734+
})
735+
}
736+
737+
fn and_or(
738+
a: &Self,
739+
b: &Self,
740+
c: &Self,
741+
l_weight: f64,
742+
r_weight: f64,
743+
) -> Result<Self, types::Error> {
744+
Ok(Self {
745+
ms: Self::compose_typeck_only(Terminal::AndOr(
746+
Arc::clone(&a.ms),
747+
Arc::clone(&b.ms),
748+
Arc::clone(&c.ms),
749+
))?,
750+
comp_ext_data: CompilerExtData::and_or(
751+
a.comp_ext_data,
752+
b.comp_ext_data,
753+
c.comp_ext_data,
754+
l_weight,
755+
r_weight,
695756
),
696757
})
697758
}

0 commit comments

Comments
 (0)