Skip to content

Commit 8888a0d

Browse files
committed
updated visualization page
1 parent 729108d commit 8888a0d

3 files changed

Lines changed: 94 additions & 4 deletions

File tree

docusaurus-site/src/components/ProofSearchCanvas.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const LIGHT_COLORS = {
2323
tooltipSym: '#f8f4f4',
2424
tooltipPunct: '#c0b0b0',
2525
subsumed: '#ff4d4d',
26+
negated: '#7c3aed',
2627
highlight: '#fff59d',
2728
};
2829

@@ -48,6 +49,7 @@ const DARK_COLORS = {
4849
tooltipSym: '#f3eaea',
4950
tooltipPunct: '#b9aaaa',
5051
subsumed: '#ff4d4d',
52+
negated: '#c084fc',
5153
highlight: '#fff59d',
5254
};
5355

@@ -133,6 +135,7 @@ export default function ProofSearchCanvas({
133135
prevStatus: null,
134136
statusChangedAt: now,
135137
subsumed: Boolean(clause.subsumed),
138+
negated: Boolean(clause.negated),
136139
x: baseX + Math.cos(angle) * radius,
137140
y: baseY + Math.sin(angle) * radius,
138141
vx: 0,
@@ -157,6 +160,7 @@ export default function ProofSearchCanvas({
157160
node.statusChangedAt = now;
158161
}
159162
node.subsumed = Boolean(clause.subsumed);
163+
node.negated = Boolean(clause.negated);
160164
}
161165
});
162166
// Remove nodes that are no longer in the current clause set
@@ -475,6 +479,17 @@ export default function ProofSearchCanvas({
475479
ctx.restore();
476480
}
477481

482+
if (node.negated) {
483+
ctx.save();
484+
ctx.globalAlpha = 0.9;
485+
ctx.strokeStyle = palette.negated;
486+
ctx.lineWidth = 2;
487+
ctx.beginPath();
488+
ctx.arc(node.x, node.y, radius * pulse - 4, 0, Math.PI * 2);
489+
ctx.stroke();
490+
ctx.restore();
491+
}
492+
478493
// Label
479494
ctx.globalAlpha = 1;
480495
ctx.fillStyle = palette.text;

docusaurus-site/src/pages/proof-search-visualization.jsx

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ export default function ProofSearchVisualization() {
241241
const runIdRef = useRef(0);
242242
const cancelRunRef = useRef(null);
243243
const szsDoneRef = useRef(false);
244+
const negatedRef = useRef(new Set());
244245

245246
useEffect(() => {
246247
outputRef.current = output;
@@ -284,6 +285,7 @@ export default function ProofSearchVisualization() {
284285
const resetRunState = () => {
285286
clauseMapRef.current.clear();
286287
edgeMapRef.current.clear();
288+
negatedRef.current.clear();
287289
setClauses([]);
288290
setEdges([]);
289291
setSelectedId(null);
@@ -302,10 +304,21 @@ export default function ProofSearchVisualization() {
302304
text: text ?? existing?.text ?? '',
303305
status: status ?? existing?.status ?? 'new',
304306
subsumed: existing?.subsumed ?? false,
307+
negated: existing?.negated ?? negatedRef.current.has(key),
305308
};
306309
map.set(key, next);
307310
};
308311

312+
const markNegated = (id) => {
313+
const key = String(id);
314+
negatedRef.current.add(key);
315+
const map = clauseMapRef.current;
316+
const existing = map.get(key);
317+
if (existing) {
318+
map.set(key, {...existing, negated: true});
319+
}
320+
};
321+
309322
const markSubsumed = (id) => {
310323
const key = String(id);
311324
const map = clauseMapRef.current;
@@ -328,10 +341,12 @@ export default function ProofSearchVisualization() {
328341
ids: [],
329342
statusById: new Map(),
330343
subsumedById: new Map(),
344+
negatedById: new Map(),
331345
};
332346
entry.ids.push(String(clause.id));
333347
entry.statusById.set(String(clause.id), clause.status || 'new');
334348
entry.subsumedById.set(String(clause.id), Boolean(clause.subsumed));
349+
entry.negatedById.set(String(clause.id), Boolean(clause.negated));
335350
grouped.set(textKey, entry);
336351
});
337352

@@ -354,12 +369,14 @@ export default function ProofSearchVisualization() {
354369
? 'passive'
355370
: (activeIds.length ? 'active' : 'new');
356371
const subsumed = entry.subsumedById.get(displayId) || false;
372+
const negated = entry.negatedById.get(displayId) || false;
357373
entry.ids.forEach((id) => idToDisplay.set(id, displayId));
358374
displayClauses.push({
359375
id: displayId,
360376
text: entry.text,
361377
status,
362378
subsumed,
379+
negated,
363380
});
364381
});
365382

@@ -415,6 +432,12 @@ export default function ProofSearchVisualization() {
415432
};
416433

417434
const parseOutputLine = (line) => {
435+
if (/negated conjecture/i.test(line)) {
436+
const idMatch = line.match(/:\s*(\d+)\.\s/);
437+
if (idMatch) {
438+
markNegated(idMatch[1]);
439+
}
440+
}
418441
const reduceMatch = line.match(REDUCE_RE);
419442
if (reduceMatch) {
420443
markSubsumed(reduceMatch[2]);
@@ -431,6 +454,16 @@ export default function ProofSearchVisualization() {
431454
bracket = bracketMatches[bracketMatches.length - 1][1];
432455
text = text.replace(/\s*\[[^\]]+\]\s*$/, '');
433456
}
457+
if (bracket) {
458+
if (/negated conjecture/i.test(bracket)) {
459+
markNegated(id);
460+
} else {
461+
const refs = Array.from(bracket.matchAll(/\b(\d+)\b/g)).map((m) => m[1]);
462+
if (refs.some((ref) => negatedRef.current.has(String(ref)))) {
463+
markNegated(id);
464+
}
465+
}
466+
}
434467
if (tag === 'SA') {
435468
const status = normalizePhaseStatus(phase);
436469
if (status === 'new') {
@@ -577,25 +610,29 @@ export default function ProofSearchVisualization() {
577610
<div className={styles.canvasFooter}>
578611
<div className={styles.legend}>
579612
<span className={styles.legendItem}>
580-
<span className={styles.dot} style={{background: '#ff9fb2'}} />
613+
<span className={`${styles.dot} ${styles.legendDotNew}`} />
581614
New
582615
</span>
583616
<span className={styles.legendItem}>
584-
<span className={styles.dot} style={{background: '#b62929'}} />
617+
<span className={`${styles.dot} ${styles.legendDotActive}`} />
585618
Active
586619
</span>
587620
<span className={styles.legendItem}>
588-
<span className={styles.dot} style={{background: '#8a8a8a'}} />
621+
<span className={`${styles.dot} ${styles.legendDotPassive}`} />
589622
Passive
590623
</span>
591624
<span className={styles.legendItem}>
592-
<span className={styles.dot} style={{background: '#f97316'}} />
625+
<span className={`${styles.dot} ${styles.legendDotSelected}`} />
593626
Selected
594627
</span>
595628
<span className={styles.legendItem}>
596629
<span className={`${styles.dot} ${styles.subsumedDot}`} />
597630
Subsumed
598631
</span>
632+
<span className={styles.legendItem}>
633+
<span className={`${styles.dot} ${styles.negatedDot}`} />
634+
Negated conjecture
635+
</span>
599636
</div>
600637
<div className={styles.hint}>
601638
{awaitingInput ? 'Waiting for your clause choice…' : 'Awaiting run'}

docusaurus-site/src/pages/proof-search-visualization.module.css

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,47 @@
299299
border-radius: 50%;
300300
}
301301

302+
.legendDotNew {
303+
background: #ff9fb2;
304+
}
305+
306+
.legendDotActive {
307+
background: #b62929;
308+
}
309+
310+
.legendDotPassive {
311+
background: #8a8a8a;
312+
}
313+
314+
.legendDotSelected {
315+
background: #f97316;
316+
}
317+
318+
:global([data-theme='dark']) .legendDotNew {
319+
background: #ff3b5c;
320+
}
321+
322+
:global([data-theme='dark']) .legendDotActive {
323+
background: #9a1b1b;
324+
}
325+
326+
:global([data-theme='dark']) .legendDotPassive {
327+
background: #5f5f5f;
328+
}
329+
330+
:global([data-theme='dark']) .legendDotSelected {
331+
background: #f59e0b;
332+
}
333+
302334
.subsumedDot {
303335
background: rgba(154, 166, 178, 0.6);
304336
border: 2px solid #ff6b6b;
337+
border-style: dashed;
338+
}
339+
340+
.negatedDot {
341+
background: transparent;
342+
border: 2px solid #7c3aed;
305343
}
306344

307345
.modalBackdrop {

0 commit comments

Comments
 (0)