@@ -15,8 +15,7 @@ export function get_contradiction(
1515 unsatisfied_properties : Set < string > ,
1616) : string [ ] | null {
1717 for ( const p of satisfied_properties ) {
18- if ( unsatisfied_properties . has ( p ) )
19- return [ `${ p } cannot be both satisfied and unsatisfied` ]
18+ if ( unsatisfied_properties . has ( p ) ) return [ `${ p } ⟹ ${ p } ` ]
2019 }
2120
2221 const implications = get_normalized_category_implications ( )
@@ -34,74 +33,63 @@ function contradiction_worker(
3433 implications : NormalizedCategoryImplication [ ] ,
3534) : string [ ] | null {
3635 for ( const p of satisfied_properties ) {
37- if ( unsatisfied_properties . has ( p ) ) {
38- return [ `${ p } cannot be both satisfied and unsatisfied` ]
39- }
36+ if ( unsatisfied_properties . has ( p ) ) return [ `${ p } ⟹ ${ p } ` ]
4037 }
4138
42- let contradictory_property : string | null = null
39+ const deduction_dict : Record < string , NormalizedCategoryImplication > = { }
40+ const deduced_satisfied_properties = new Set ( satisfied_properties )
4341
44- const used_implications : {
45- implication : NormalizedCategoryImplication
46- relevant : boolean
47- } [ ] = [ ]
42+ // bfs to find contradiction
4843
49- const deduced_satisfied_properties = new Set ( satisfied_properties )
44+ let contradictory_property : string | null = null
45+
46+ while ( ! contradictory_property ) {
47+ const new_properties = new Set < string > ( )
5048
51- function get_next_implication ( ) {
5249 for ( const implication of implications ) {
5350 const is_valid =
5451 is_subset ( implication . assumptions , deduced_satisfied_properties ) &&
55- ! deduced_satisfied_properties . has ( implication . conclusion )
56- if ( is_valid ) return implication
57- }
58- return null
59- }
52+ ! deduced_satisfied_properties . has ( implication . conclusion ) &&
53+ ! new_properties . has ( implication . conclusion )
54+ if ( ! is_valid ) continue
6055
61- while ( true ) {
62- const implication = get_next_implication ( )
63- if ( ! implication ) break
56+ new_properties . add ( implication . conclusion )
57+ deduction_dict [ implication . conclusion ] = implication
6458
65- used_implications . push ( { implication, relevant : false } )
66- deduced_satisfied_properties . add ( implication . conclusion )
67-
68- if ( unsatisfied_properties . has ( implication . conclusion ) ) {
69- contradictory_property = implication . conclusion
70- break
59+ if ( unsatisfied_properties . has ( implication . conclusion ) ) {
60+ contradictory_property = implication . conclusion
61+ break
62+ }
7163 }
64+
65+ if ( ! new_properties . size ) break
66+
67+ for ( const p of new_properties ) deduced_satisfied_properties . add ( p )
7268 }
7369
7470 if ( ! contradictory_property ) return null
7571
76- // remove irrelevant implications
72+ // build minimal contradiction proof
7773
78- const relevant_properties = new Set ( [ contradictory_property ] )
74+ const contradiction : string [ ] = [ ]
7975
80- for ( let i = used_implications . length - 1 ; i >= 0 ; i -- ) {
81- const { implication } = used_implications [ i ]
82- const is_relevant = relevant_properties . has ( implication . conclusion )
76+ const visited_properties = new Set < string > ( )
8377
84- if ( is_relevant ) {
85- used_implications [ i ] . relevant = is_relevant
86- for ( const p of implication . assumptions ) {
87- if ( ! satisfied_properties . has ( p ) ) relevant_properties . add ( p )
88- }
89- }
90- }
78+ function build_proof ( property : string ) {
79+ if ( visited_properties . has ( property ) ) return
80+ if ( satisfied_properties . has ( property ) ) return
81+ visited_properties . add ( property )
9182
92- const relevant_implications = used_implications
93- . filter ( ( item ) => item . relevant )
94- . map ( ( item ) => item . implication )
83+ const implication = deduction_dict [ property ]
84+ if ( ! implication ) throw new Error ( `Missing deduction for property: ${ property } ` )
9585
96- const contradiction : string [ ] = [ ]
86+ for ( const p of implication . assumptions ) build_proof ( p )
9787
98- for ( let i = 0 ; i < relevant_implications . length ; i ++ ) {
99- const implication = relevant_implications [ i ]
100- let segment = `${ [ ...implication . assumptions ] . join ( ' ∧ ' ) } ⟹ ${ implication . conclusion } `
101- if ( i === relevant_implications . length - 1 ) segment += ` ↯`
102- contradiction . push ( segment )
88+ contradiction . push ( stringify_implication ( implication ) )
10389 }
10490
91+ build_proof ( contradictory_property )
92+
10593 return contradiction
10694}
10795
@@ -145,6 +133,10 @@ function get_normalized_category_implications() {
145133 return implications
146134}
147135
136+ function stringify_implication ( implication : NormalizedCategoryImplication ) {
137+ return `${ [ ...implication . assumptions ] . join ( ' ∧ ' ) } ⟹ ${ implication . conclusion } `
138+ }
139+
148140export function get_missing_combinations ( ) {
149141 const implications = get_normalized_category_implications ( )
150142
0 commit comments