Skip to content

Commit 29ff4e6

Browse files
committed
use BFS to find shortest proof, use deduction dict to simplify proof construction
1 parent 3fdf0d8 commit 29ff4e6

1 file changed

Lines changed: 39 additions & 47 deletions

File tree

src/lib/server/consistency.ts

Lines changed: 39 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
148140
export function get_missing_combinations() {
149141
const implications = get_normalized_category_implications()
150142

0 commit comments

Comments
 (0)