|
5 | 5 | //! Optimizing compiler from concrete policies to Miniscript |
6 | 6 | //! |
7 | 7 |
|
| 8 | +#![allow(dead_code)] // will be removed in next commit |
| 9 | +#![allow(unused_variables)] // will be removed in next commit |
| 10 | + |
8 | 11 | use core::num::NonZeroU32; |
9 | 12 | use core::{f64, fmt, mem}; |
10 | 13 | #[cfg(feature = "std")] |
@@ -98,62 +101,114 @@ fn best_compilations_or<Pk: MiniscriptKey, Ctx: ScriptContext>( |
98 | 101 | sat_prob: f64, |
99 | 102 | dissat_prob: Option<f64>, |
100 | 103 | ) -> 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 | | - |
107 | 104 | let total = u32::from(subs[0].0) as f64 + u32::from(subs[1].0) as f64; |
108 | 105 | let lw = u32::from(subs[0].0) as f64 / total; |
109 | 106 | let rw = u32::from(subs[1].0) as f64 / total; |
110 | 107 |
|
111 | 108 | //and-or |
112 | 109 | 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( |
114 | 111 | policy_cache, |
115 | 112 | x[0].as_ref(), |
116 | 113 | lw * sat_prob, |
117 | 114 | Some(dissat_prob.unwrap_or(0 as f64) + rw * sat_prob), |
118 | 115 | )?; |
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)?; |
120 | 117 |
|
121 | | - let mut b1 = best_compilations( |
| 118 | + let b1 = best_compilations( |
122 | 119 | policy_cache, |
123 | 120 | x[1].as_ref(), |
124 | 121 | lw * sat_prob, |
125 | 122 | Some(dissat_prob.unwrap_or(0 as f64) + rw * sat_prob), |
126 | 123 | )?; |
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)?; |
128 | 125 |
|
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)?; |
131 | 127 |
|
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 | + } |
134 | 160 | }; |
135 | 161 | 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( |
137 | 163 | policy_cache, |
138 | 164 | x[0].as_ref(), |
139 | 165 | rw * sat_prob, |
140 | 166 | Some(dissat_prob.unwrap_or(0 as f64) + lw * sat_prob), |
141 | 167 | )?; |
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)?; |
143 | 169 |
|
144 | | - let mut b1 = best_compilations( |
| 170 | + let b1 = best_compilations( |
145 | 171 | policy_cache, |
146 | 172 | x[1].as_ref(), |
147 | 173 | rw * sat_prob, |
148 | 174 | Some(dissat_prob.unwrap_or(0 as f64) + lw * sat_prob), |
149 | 175 | )?; |
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)?; |
151 | 177 |
|
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)?; |
154 | 179 |
|
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 | + } |
157 | 212 | }; |
158 | 213 |
|
159 | 214 | let dissat_probs = |w: f64| -> Vec<Option<f64>> { |
@@ -485,18 +540,13 @@ impl CompilerExtData { |
485 | 540 | } |
486 | 541 | } |
487 | 542 |
|
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 { |
493 | 544 | let adis = a |
494 | 545 | .dissat_cost |
495 | 546 | .expect("BUG: and_or first arg(a) must be dissatisfiable"); |
496 | | - debug_assert_eq!(aprob, bprob); //A and B must have same branch prob. |
497 | 547 | Self { |
498 | 548 | 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), |
500 | 550 | dissat_cost: c.dissat_cost.map(|cdis| adis + cdis), |
501 | 551 | } |
502 | 552 | } |
@@ -543,18 +593,7 @@ impl CompilerExtData { |
543 | 593 | Pk: MiniscriptKey, |
544 | 594 | Ctx: ScriptContext, |
545 | 595 | { |
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!() |
558 | 597 | } |
559 | 598 | } |
560 | 599 |
|
@@ -679,19 +718,41 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> AstElemExt<Pk, Ctx> { |
679 | 718 |
|
680 | 719 | /// andor(a,b,0) is a conjunction of a and b |
681 | 720 | 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 | | - |
685 | 721 | Ok(Self { |
686 | 722 | ms: Self::compose_typeck_only(Terminal::AndOr( |
687 | 723 | Arc::clone(&left.ms), |
688 | 724 | Arc::clone(&right.ms), |
689 | 725 | Arc::new(Miniscript::FALSE), |
690 | 726 | ))?, |
691 | 727 | comp_ext_data: CompilerExtData::and_or( |
692 | | - left_ext_data, |
693 | | - right_ext_data, |
| 728 | + left.comp_ext_data, |
| 729 | + right.comp_ext_data, |
694 | 730 | 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, |
695 | 756 | ), |
696 | 757 | }) |
697 | 758 | } |
|
0 commit comments