Skip to content

Commit bee0d12

Browse files
committed
deduce implications: refactor
1 parent d13e6f7 commit bee0d12

1 file changed

Lines changed: 102 additions & 49 deletions

File tree

databases/catdat/scripts/deduce-implications.ts

Lines changed: 102 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { StructureType } from './config'
2-
import { get_client } from './utils/helpers'
2+
import { are_equal_sets, get_client } from './utils/helpers'
33

44
const db = get_client()
55

66
/**
77
* Deduces implications from given ones.
88
*/
99
export 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

Comments
 (0)