@@ -497,14 +497,16 @@ impl<Pk: MiniscriptKey, Ctx: ScriptContext> AstElemExt<Pk, Ctx> {
497497 /// and a probability of dissatisfaction; if `dissat_prob` is `None`
498498 /// then it is assumed that dissatisfaction never occurs
499499 fn cost_1d ( & self , sat_prob : PositiveF64 , dissat_prob : Option < PositiveF64 > ) -> PositiveF64 {
500- PositiveF64 :: new ( self . ms . ext . pk_cost as f64 )
501- + PositiveF64 :: new ( self . comp_ext_data . sat_cost ) * sat_prob
502- + match ( dissat_prob, self . comp_ext_data . dissat_cost ) {
503- ( Some ( prob) , Some ( cost) ) => prob * PositiveF64 :: new ( cost) ,
504- ( Some ( _) , None ) => PositiveF64 :: new ( f64:: INFINITY ) ,
505- ( None , Some ( _) ) => PositiveF64 :: new ( 0.0 ) ,
506- ( None , None ) => PositiveF64 :: new ( 0.0 ) ,
507- }
500+ let sat_cost = ( self . comp_ext_data . sat_cost > 0.0 )
501+ . then ( || PositiveF64 :: new ( self . comp_ext_data . sat_cost ) * sat_prob) ;
502+ let base = PositiveF64 :: new ( self . ms . ext . pk_cost as f64 ) . conditional_add ( sat_cost) ;
503+ let dissat_cost = match ( dissat_prob, self . comp_ext_data . dissat_cost ) {
504+ ( Some ( _) , Some ( 0.0 ) ) => None ,
505+ ( Some ( prob) , Some ( cost) ) => Some ( prob * PositiveF64 :: new ( cost) ) ,
506+ ( Some ( _) , None ) => Some ( PositiveF64 :: INFINITY ) ,
507+ ( None , _) => None ,
508+ } ;
509+ base. conditional_add ( dissat_cost)
508510 }
509511}
510512
@@ -785,8 +787,19 @@ where
785787 } ;
786788 }
787789 macro_rules! compile_tern {
788- ( $a: expr, $b: expr, $c: expr, $w: expr) => {
789- compile_tern( policy_cache, policy, & mut ret, $a, $b, $c, $w, sat_prob, dissat_prob) ?
790+ ( $a: expr, $b: expr, $c: expr, [ $ab_prob: expr, $c_prob: expr] ) => {
791+ compile_tern(
792+ policy_cache,
793+ policy,
794+ & mut ret,
795+ $a,
796+ $b,
797+ $c,
798+ $ab_prob,
799+ $c_prob,
800+ sat_prob,
801+ dissat_prob,
802+ ) ?
790803 } ;
791804 }
792805
@@ -828,7 +841,6 @@ where
828841 best_compilations ( policy_cache, subs[ 0 ] . as_ref ( ) , sat_prob, None ) ?;
829842
830843 let one = PositiveF64 :: new ( 1.0 ) ;
831- let zero = PositiveF64 :: new ( 0.0 ) ;
832844 compile_binary ! ( & mut left, & mut right, [ one, one] , Terminal :: AndB ) ;
833845 compile_binary ! ( & mut right, & mut left, [ one, one] , Terminal :: AndB ) ;
834846 compile_binary ! ( & mut left, & mut right, [ one, one] , Terminal :: AndV ) ;
@@ -838,28 +850,27 @@ where
838850 CompilationKey :: from_type ( Type :: FALSE , ExtData :: FALSE . has_free_verify , dissat_prob) ,
839851 AstElemExt :: terminal ( Miniscript :: FALSE ) ,
840852 ) ;
841- compile_tern ! ( & mut left, & mut q_zero_right, & mut zero_comp, [ one, zero ] ) ;
842- compile_tern ! ( & mut right, & mut q_zero_left, & mut zero_comp, [ one, zero ] ) ;
853+ compile_tern ! ( & mut left, & mut q_zero_right, & mut zero_comp, [ one, None ] ) ;
854+ compile_tern ! ( & mut right, & mut q_zero_left, & mut zero_comp, [ one, None ] ) ;
843855 }
844856 Concrete :: Or ( ref subs) => {
845857 let ( lw, rw) = PositiveF64 :: normalized ( subs[ 0 ] . 0 , subs[ 1 ] . 0 ) ;
846- let zero = PositiveF64 :: new ( 0.0 ) ;
847858
848859 //and-or
849860 if let ( Concrete :: And ( x) , _) = ( subs[ 0 ] . 1 . as_ref ( ) , subs[ 1 ] . 1 . as_ref ( ) ) {
850861 let mut a1 = best_compilations (
851862 policy_cache,
852863 x[ 0 ] . as_ref ( ) ,
853864 lw * sat_prob,
854- Some ( dissat_prob . unwrap_or ( zero ) + rw * sat_prob) ,
865+ Some ( ( rw * sat_prob) . conditional_add ( dissat_prob ) ) ,
855866 ) ?;
856867 let mut a2 = best_compilations ( policy_cache, x[ 0 ] . as_ref ( ) , lw * sat_prob, None ) ?;
857868
858869 let mut b1 = best_compilations (
859870 policy_cache,
860871 x[ 1 ] . as_ref ( ) ,
861872 lw * sat_prob,
862- Some ( dissat_prob . unwrap_or ( zero ) + rw * sat_prob) ,
873+ Some ( ( rw * sat_prob) . conditional_add ( dissat_prob ) ) ,
863874 ) ?;
864875 let mut b2 = best_compilations ( policy_cache, x[ 1 ] . as_ref ( ) , lw * sat_prob, None ) ?;
865876
@@ -870,23 +881,23 @@ where
870881 dissat_prob,
871882 ) ?;
872883
873- compile_tern ! ( & mut a1, & mut b2, & mut c, [ lw, rw ] ) ;
874- compile_tern ! ( & mut b1, & mut a2, & mut c, [ lw, rw ] ) ;
884+ compile_tern ! ( & mut a1, & mut b2, & mut c, [ lw, Some ( rw ) ] ) ;
885+ compile_tern ! ( & mut b1, & mut a2, & mut c, [ lw, Some ( rw ) ] ) ;
875886 } ;
876887 if let ( _, Concrete :: And ( x) ) = ( & subs[ 0 ] . 1 . as_ref ( ) , subs[ 1 ] . 1 . as_ref ( ) ) {
877888 let mut a1 = best_compilations (
878889 policy_cache,
879890 x[ 0 ] . as_ref ( ) ,
880891 rw * sat_prob,
881- Some ( dissat_prob . unwrap_or ( zero ) + lw * sat_prob) ,
892+ Some ( ( lw * sat_prob) . conditional_add ( dissat_prob ) ) ,
882893 ) ?;
883894 let mut a2 = best_compilations ( policy_cache, x[ 0 ] . as_ref ( ) , rw * sat_prob, None ) ?;
884895
885896 let mut b1 = best_compilations (
886897 policy_cache,
887898 x[ 1 ] . as_ref ( ) ,
888899 rw * sat_prob,
889- Some ( dissat_prob . unwrap_or ( zero ) + lw * sat_prob) ,
900+ Some ( ( lw * sat_prob) . conditional_add ( dissat_prob ) ) ,
890901 ) ?;
891902 let mut b2 = best_compilations ( policy_cache, x[ 1 ] . as_ref ( ) , rw * sat_prob, None ) ?;
892903
@@ -897,13 +908,13 @@ where
897908 dissat_prob,
898909 ) ?;
899910
900- compile_tern ! ( & mut a1, & mut b2, & mut c, [ rw, lw ] ) ;
901- compile_tern ! ( & mut b1, & mut a2, & mut c, [ rw, lw ] ) ;
911+ compile_tern ! ( & mut a1, & mut b2, & mut c, [ rw, Some ( lw ) ] ) ;
912+ compile_tern ! ( & mut b1, & mut a2, & mut c, [ rw, Some ( lw ) ] ) ;
902913 } ;
903914
904915 let dissat_probs = |w : PositiveF64 | -> Vec < Option < PositiveF64 > > {
905916 vec ! [
906- Some ( dissat_prob . unwrap_or ( zero ) + w * sat_prob) ,
917+ Some ( ( w * sat_prob) . conditional_add ( dissat_prob ) ) ,
907918 Some ( w * sat_prob) ,
908919 dissat_prob,
909920 None ,
@@ -953,11 +964,15 @@ where
953964 let k = thresh. k ( ) ;
954965 let n = thresh. n ( ) ;
955966
956- let ( sat_ratio, dissat_ratio) = PositiveF64 :: normalized (
957- PositiveF64 :: new ( k as f64 ) ,
958- PositiveF64 :: new ( ( n - k) as f64 ) ,
959- ) ;
960- let zero = PositiveF64 :: new ( 0.0 ) ;
967+ let ( sat_ratio, dissat_ratio) = if n > k {
968+ let ( s, d) = PositiveF64 :: normalized (
969+ PositiveF64 :: new ( k as f64 ) ,
970+ PositiveF64 :: new ( ( n - k) as f64 ) ,
971+ ) ;
972+ ( s, Some ( d) )
973+ } else {
974+ ( PositiveF64 :: new ( 1.0 ) , None )
975+ } ;
961976
962977 let mut sub_ext_data = Vec :: with_capacity ( n) ;
963978
@@ -968,7 +983,9 @@ where
968983 for ( i, ast) in thresh. iter ( ) . enumerate ( ) {
969984 let sp = sat_prob * sat_ratio;
970985 //Expressions must be dissatisfiable
971- let dp = Some ( dissat_prob. unwrap_or ( zero) + dissat_ratio * sat_prob) ;
986+ let dp = dissat_ratio
987+ . map ( |ratio| ( ratio * sat_prob) . conditional_add ( dissat_prob) )
988+ . or ( dissat_prob) ;
972989 let be = best ( types:: Base :: B , policy_cache, ast. as_ref ( ) , sp, dp) ?;
973990 let bw = best ( types:: Base :: W , policy_cache, ast. as_ref ( ) , sp, dp) ?;
974991
@@ -1111,20 +1128,23 @@ fn compile_tern<Pk: MiniscriptKey, Ctx: ScriptContext>(
11111128 a_comp : & mut BTreeMap < CompilationKey , AstElemExt < Pk , Ctx > > ,
11121129 b_comp : & mut BTreeMap < CompilationKey , AstElemExt < Pk , Ctx > > ,
11131130 c_comp : & mut BTreeMap < CompilationKey , AstElemExt < Pk , Ctx > > ,
1114- weights : [ PositiveF64 ; 2 ] ,
1131+ ab_branch_prob : PositiveF64 ,
1132+ c_branch_prob : Option < PositiveF64 > ,
11151133 sat_prob : PositiveF64 ,
11161134 dissat_prob : Option < PositiveF64 > ,
11171135) -> Result < ( ) , CompilerError > {
1136+ let ab_prob = ab_branch_prob. value ( ) ;
1137+ let c_prob = c_branch_prob. map_or ( 0.0 , |p| p. value ( ) ) ;
11181138 for a in a_comp. values_mut ( ) {
11191139 let aref = Arc :: clone ( & a. ms ) ;
11201140 for b in b_comp. values_mut ( ) {
11211141 let bref = Arc :: clone ( & b. ms ) ;
11221142 for c in c_comp. values_mut ( ) {
11231143 let cref = Arc :: clone ( & c. ms ) ;
11241144 let ast = Terminal :: AndOr ( Arc :: clone ( & aref) , Arc :: clone ( & bref) , Arc :: clone ( & cref) ) ;
1125- a. comp_ext_data . branch_prob = Some ( weights [ 0 ] . value ( ) ) ;
1126- b. comp_ext_data . branch_prob = Some ( weights [ 0 ] . value ( ) ) ;
1127- c. comp_ext_data . branch_prob = Some ( weights [ 1 ] . value ( ) ) ;
1145+ a. comp_ext_data . branch_prob = Some ( ab_prob ) ;
1146+ b. comp_ext_data . branch_prob = Some ( ab_prob ) ;
1147+ c. comp_ext_data . branch_prob = Some ( c_prob ) ;
11281148 if let Ok ( new_ext) = AstElemExt :: ternary ( ast, a, b, c) {
11291149 insert_best_wrapped ( policy_cache, policy, ret, new_ext, sat_prob, dissat_prob) ?;
11301150 }
0 commit comments