11import { StructureType } from './config'
2- import { get_client } from './utils/helpers'
2+ import { are_equal_sets , get_client } from './utils/helpers'
33
44const db = get_client ( )
55
66/**
77 * Deduces implications from given ones.
88 */
99export function deduce_implications ( ) {
10+ console . info ( '\n--- Deduce implications ---' )
11+
1012 clear_all_deduced_implications ( )
11- dualize_implications ( )
13+ dualize_implications ( 'category' )
14+ dualize_implications ( 'functor' )
1215 create_self_dual_implications ( )
1316}
1417
@@ -19,26 +22,35 @@ function clear_all_deduced_implications() {
1922 db . prepare ( `DELETE FROM implications WHERE is_deduced = TRUE` ) . run ( )
2023}
2124
25+ type ImplicationProperty = {
26+ id : string
27+ is_equivalence : 0 | 1
28+ kind : 'assumption' | 'conclusion'
29+ structure : 'self' | 'source' | 'target'
30+ property_id : string
31+ dual_property_id : string | null
32+ }
33+
34+ type ImplicationFull = {
35+ id : string
36+ is_equivalence : 0 | 1
37+ properties : {
38+ id : string
39+ dual : string | null
40+ kind : 'assumption' | 'conclusion'
41+ structure : 'self' | 'source' | 'target'
42+ } [ ]
43+ }
44+
2245/**
2346 * Dualizes all implications by dualizing the involved properties
2447 * (in case they have a dual). For example, if P ===> Q holds,
2548 * then P^op ===> Q^op holds as well.
2649 */
27- function dualize_implications ( ) {
28- type ImplicationRow = {
29- id : string
30- type : StructureType
31- is_equivalence : 0 | 1
32- kind : string
33- structure : string
34- property_id : string
35- dual_property_id : string
36- }
37-
38- const implications_query = db . prepare < never [ ] , ImplicationRow > ( `
50+ function dualize_implications ( type : StructureType ) {
51+ const implication_properties_query = db . prepare < [ string ] , ImplicationProperty > ( `
3952 SELECT
4053 i.id,
41- i.type,
4254 i.is_equivalence,
4355 ip.kind,
4456 ip.structure,
@@ -49,62 +61,103 @@ function dualize_implications() {
4961 ON ip.implication_id = i.id
5062 LEFT JOIN dual_properties d
5163 ON d.property_id = ip.property_id
52- WHERE i.is_deduced = FALSE
53- AND NOT EXISTS (
54- SELECT 1 FROM implication_properties ip2
55- LEFT JOIN dual_properties d2
56- ON d2.property_id = ip2.property_id
57- WHERE ip2.implication_id = i.id
58- AND d2.dual_property_id IS NULL
59- )
60- ORDER BY i.type, i.id
64+ WHERE i.is_deduced = FALSE AND i.type = ?
65+ ORDER BY i.id
6166 ` )
6267
63- // TODO: filter out implications that dualize to the same sets of assumptions / conclusions
64-
65- const seen = new Set < string > ( )
66-
67- const dual_implication_query = db . prepare ( `
68+ const dual_implication_insert = db . prepare ( `
6869 INSERT INTO implications
6970 (id, type, is_equivalence, is_deduced, dualized_from, proof)
7071 VALUES (?, ?, ?, TRUE, ?, ?)
7172 ` )
7273
73- const implication_property_query = db . prepare ( `
74+ const implication_property_insert = db . prepare ( `
7475 INSERT INTO implication_properties
7576 (implication_id, property_id, type, kind, structure)
7677 VALUES (?, ?, ?, ?, ?)
7778 ` )
7879
7980 const tx = db . transaction ( ( ) => {
80- const implications = implications_query . all ( )
81+ const implication_properties = implication_properties_query . all ( type )
82+ const implications_dict = get_implications_dict ( implication_properties )
83+ const count = Object . values ( implications_dict ) . length
8184
82- for ( const impl of implications ) {
83- if ( ! seen . has ( impl . id ) ) {
84- dual_implication_query . run (
85+ for ( const impl of Object . values ( implications_dict ) ) {
86+ dual_implication_insert . run (
87+ `dual_${ impl . id } ` ,
88+ type ,
89+ impl . is_equivalence ,
90+ impl . id ,
91+ 'This follows from the dual implication.' ,
92+ )
93+
94+ for ( const p of impl . properties ) {
95+ implication_property_insert . run (
8596 `dual_${ impl . id } ` ,
86- impl . type ,
87- impl . is_equivalence ,
88- impl . id ,
89- 'This follows from the dual implication.' ,
97+ p . dual ,
98+ type ,
99+ p . kind ,
100+ p . structure ,
90101 )
91-
92- seen . add ( impl . id )
93102 }
94-
95- implication_property_query . run (
96- `dual_${ impl . id } ` ,
97- impl . dual_property_id ,
98- impl . type ,
99- impl . kind ,
100- impl . structure ,
101- )
102103 }
104+
105+ console . info ( `Deduced ${ count } ${ type } implications by duality` )
103106 } )
104107
105108 tx ( )
109+ }
110+
111+ /**
112+ * Checks if all properties of an implication have a dual
113+ * and that the dualized implication is different from the original.
114+ */
115+ function is_dualizable ( impl : ImplicationFull ) : boolean {
116+ if ( impl . properties . some ( ( p ) => ! p . dual ) ) return false
117+
118+ const kinds = new Set ( impl . properties . map ( ( p ) => p . kind ) )
119+ const structures = new Set ( impl . properties . map ( ( p ) => p . structure ) )
120+
121+ for ( const kind of kinds ) {
122+ for ( const structure of structures ) {
123+ const props = impl . properties . filter (
124+ ( p ) => p . kind === kind && p . structure === structure ,
125+ )
126+ if ( ! props . length ) continue
127+ const prop_ids = new Set ( props . map ( ( p ) => p . id ) )
128+ const dual_prop_ids = new Set ( props . map ( ( p ) => p . dual ) )
129+ if ( ! are_equal_sets ( prop_ids , dual_prop_ids ) ) return true
130+ }
131+ }
132+
133+ return false
134+ }
135+
136+ function get_implications_dict (
137+ implication_properties : ImplicationProperty [ ] ,
138+ ) : Record < string , ImplicationFull > {
139+ const implications_dict : Record < string , ImplicationFull > = { }
140+
141+ for ( const impl_prop of implication_properties ) {
142+ const { id, is_equivalence, property_id, dual_property_id, kind, structure } =
143+ impl_prop
144+ implications_dict [ id ] ??= { id, is_equivalence, properties : [ ] }
145+
146+ implications_dict [ id ] . properties . push ( {
147+ id : property_id ,
148+ dual : dual_property_id ,
149+ kind,
150+ structure,
151+ } )
152+ }
153+
154+ for ( const id in implications_dict ) {
155+ if ( ! is_dualizable ( implications_dict [ id ] ) ) {
156+ delete implications_dict [ id ]
157+ }
158+ }
106159
107- console . info ( `Deduced ${ seen . size } implications by duality` )
160+ return implications_dict
108161}
109162
110163/**
0 commit comments