Skip to content

Commit 7621e91

Browse files
committed
Don't show prompt if contraction/weakening is obvious
1 parent 2bc0bbf commit 7621e91

1 file changed

Lines changed: 40 additions & 20 deletions

File tree

src/app.js

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ const saveProof = i => {
170170
pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text))
171171
pom.setAttribute('download', `${goal}.proof`)
172172
pom.click()
173-
};
173+
}
174174

175175
const refreshList = () => {
176176
let ol = document.querySelector('#left-bar ol')
@@ -318,8 +318,8 @@ const help = () => {
318318
</p>
319319
<br>
320320
<p>
321-
Our Hoare triples are based on a simple imperative language (SIL).
322-
SIL has only 4 kinds of statements:
321+
Our Hoare triples are based on a simple imperative language (SIL).
322+
SIL has only 4 kinds of statements:
323323
<ul class="help-list">
324324
<li>assignments <code>x := t</code> where <code>t</code> is a term</li>
325325
<li>conditionals <code>if c then s1 else s2</code> where <code>c</code> is a formula and <code>s1</code> and <code>s2</code> are statements</li>
@@ -334,7 +334,7 @@ const help = () => {
334334
<br>
335335
<h2>General usage</h2>
336336
<p>
337-
You can click on the <span style="color: ${incompleteColor}">orange</span> plus buttons next to incomplete proof trees, then choose a proof rules to apply.
337+
You can click on the <span style="color: ${incompleteColor}">orange</span> plus buttons next to incomplete proof trees, then choose a proof rules to apply.
338338
</p>
339339
<p>
340340
You can click on the <span style="color: ${failureColor}">red</span> minus button to unapply proof rules that are already applied.
@@ -362,7 +362,7 @@ For rules with premises, you can click on the <span style="background: ${foldCol
362362
<br>
363363
<h3>Z3 support</h3>
364364
<p>
365-
The proof assistant currently cannot evaluate functions or relations. For example, if there is a term <code>1 + 1</code>, it will get stuck, it will not evaluate to <code>2</code>. Therefore you cannot prove <code>P(1 + 1) |- P(2)</code> by normal proof rules. For these cases, you can use the <strong>Z3</strong> pseudo-rule. This rule runs the Z3 theorem prover in the background to check if the goal is valid. You can also use this rule for other logical goals you do not want to write the full proof for, but still want to check.
365+
The proof assistant currently cannot evaluate functions or relations. For example, if there is a term <code>1 + 1</code>, it will get stuck, it will not evaluate to <code>2</code>. Therefore you cannot prove <code>P(1 + 1) |- P(2)</code> by normal proof rules. For these cases, you can use the <strong>Z3</strong> pseudo-rule. This rule runs the Z3 theorem prover in the background to check if the goal is valid. You can also use this rule for other logical goals you do not want to write the full proof for, but still want to check.
366366
</p>
367367
<p>
368368
If Z3 finds the goal to be valid, it will draw a <span style="color: ${successColor}">green</span> line over it. If Z3 finds the goal to be not valid, it will draw a <span style="color: ${failureColor}">red</span> line over it.
@@ -379,7 +379,7 @@ For rules with premises, you can click on the <span style="background: ${foldCol
379379
let ex = document.querySelectorAll('ul.help-examples')
380380
Array.from(ex[0].children).forEach(li => {
381381
let but = toNodes(`<button>Try this!</button>`)[0]
382-
but.addEventListener('click', e => {
382+
but.addEventListener('click', e => {
383383
addProof(new LKIncomplete(peg.parse(li.children[0].innerText, { startRule: "Sequent" }) ))
384384
but.style.background = successColor
385385
but.innerText = "✓"
@@ -390,7 +390,7 @@ For rules with premises, you can click on the <span style="background: ${foldCol
390390
})
391391
Array.from(ex[1].children).forEach(li => {
392392
let but = toNodes(`<button>Try this!</button>`)[0]
393-
but.addEventListener('click', e => {
393+
but.addEventListener('click', e => {
394394
addProof(new HoareIncomplete(peg.parse(li.children[0].innerText, { startRule: "HoareTriple" }) ))
395395
but.style.background = successColor
396396
but.innerText = "✓"
@@ -430,7 +430,7 @@ ProofTree.prototype.image = function (root) {
430430
}
431431
let isIncomplete = this instanceof LKIncomplete || this instanceof HoareIncomplete
432432

433-
433+
434434
premiseImages.forEach((image, i) => {
435435
if (i === 0) return
436436

@@ -607,38 +607,58 @@ ProofTree.prototype.image = function (root) {
607607
if(updated === this) { return }
608608
} else if (rule === WeakeningLeft) {
609609
if (this.conclusion.precedents.length < 1) throw new Error('There is no formula on the left side to drop.')
610-
const i = await modalRadio('For weakening, select a formula from the left side to drop:', this.conclusion.precedents.map(x => x.unicode()))
610+
let i
611+
if (this.conclusion.precedents.length === 1) {
612+
i = 0
613+
} else {
614+
i = await modalRadio('For weakening, select a formula from the left side to drop:', this.conclusion.precedents.map(x => x.unicode()))
615+
}
611616
updated = await applyLK(this.conclusion, rule, i)
612617
} else if (rule === WeakeningRight) {
613618
if (this.conclusion.antecedents.length < 1) throw new Error('There is no formula on the right side to drop.')
614-
const i = await modalRadio('For weakening, select a formula from the right side to drop:', this.conclusion.antecedents.map(x => x.unicode()))
619+
let i
620+
if (this.conclusion.antecedents.length === 1) {
621+
i = 0
622+
} else {
623+
i = await modalRadio('For weakening, select a formula from the right side to drop:', this.conclusion.antecedents.map(x => x.unicode()))
624+
}
615625
updated = await applyLK(this.conclusion, rule, i)
616626
} else if (rule === ContractionLeft) {
617627
if (this.conclusion.precedents.length < 1) throw new Error('There is no formula on the left side to repeat.')
618-
const i = await modalRadio('For contraction, select a formula from the left side to repeat:', this.conclusion.precedents.map(x => x.unicode()))
628+
let i
629+
if (this.conclusion.precedents.length === 1) {
630+
i = 0
631+
} else {
632+
i = await modalRadio('For contraction, select a formula from the left side to repeat:', this.conclusion.precedents.map(x => x.unicode()))
633+
}
619634
updated = await applyLK(this.conclusion, rule, i)
620635
} else if (rule === ContractionRight) {
621636
if (this.conclusion.antecedents.length < 1) throw new Error('There is no formula on the right side to repeat.')
622-
const i = await modalRadio('For contraction, select a formula from the right side to repeat:', this.conclusion.antecedents.map(x => x.unicode()))
637+
let i
638+
if (this.conclusion.antecedents.length === 1) {
639+
i = 0
640+
} else {
641+
i = await modalRadio('For contraction, select a formula from the right side to repeat:', this.conclusion.antecedents.map(x => x.unicode()))
642+
}
623643
updated = await applyLK(this.conclusion, rule, i)
624644
} else if (rule === Cut) {
625645
const parsed = await modalFormulaPrompt('Enter the formula to prove:')
626646
updated = await applyLK(this.conclusion, rule, parsed)
627647
} else if (rule === ForallLeft) {
628-
if (!this.conclusion.precedents.some(e => e instanceof Forall)) throw new Error('There are no ∀-quantified formula on the left side.')
648+
if (!this.conclusion.precedents.some(e => e instanceof Forall)) throw new Error('There is no ∀-quantified formula on the left side.')
629649
const parsed = await modalTermPrompt('Enter the term to substitute for the variable currently bound by ∀:')
630650
updated = await applyLK(this.conclusion, rule, parsed)
631651
} else if (rule === ExistsRight) {
632-
console.log(this.conclusion.antecedents);
633-
if (!this.conclusion.antecedents.some(e => e instanceof Exists)) throw new Error('There are no ∃-quantified formula on the right side.')
652+
console.log(this.conclusion.antecedents)
653+
if (!this.conclusion.antecedents.some(e => e instanceof Exists)) throw new Error('There is no ∃-quantified formula on the right side.')
634654
const parsed = await modalTermPrompt('Enter the term to substitute for the variable currently bound by ∃:')
635655
updated = await applyLK(this.conclusion, rule, parsed)
636656
} else if (rule === ForallRight) {
637-
if (!this.conclusion.antecedents.some(e => e instanceof Forall)) throw new Error('There are no ∀-quantified formula on the right side.')
657+
if (!this.conclusion.antecedents.some(e => e instanceof Forall)) throw new Error('There is no ∀-quantified formula on the right side.')
638658
const parsed = await modalNamePrompt('Enter a fresh variable to substitute for the variable currently bound by ∀:')
639659
updated = await applyLK(this.conclusion, rule, new TermVar(parsed))
640660
} else if (rule === ExistsLeft) {
641-
if (!this.conclusion.precedents.some(e => e instanceof Exists)) throw new Error('There are no ∃-quantified formula on the left side.')
661+
if (!this.conclusion.precedents.some(e => e instanceof Exists)) throw new Error('There is no ∃-quantified formula on the left side.')
642662
const parsed = await modalNamePrompt('Enter a fresh variable to substitute for the variable currently bound by ∃:')
643663
updated = await applyLK(this.conclusion, rule, new TermVar(parsed))
644664
} else {
@@ -670,7 +690,7 @@ ProofTree.prototype.image = function (root) {
670690
entry.proof.draw()
671691
} catch(err) {
672692
modalWarning(err.message)
673-
console.log(err);
693+
console.log(err)
674694
}
675695
})
676696
})
@@ -702,7 +722,7 @@ ProofTree.prototype.image = function (root) {
702722
deleteLabel.on('mousedown', async (e) => {
703723
const msg = `Are you sure you want to <strong>unapply</strong> the ${this.unicodeName} rule
704724
for the conclusion <br>${this.conclusion.unicode()}<br> and the rules applied after/above?`
705-
console.log(this);
725+
console.log(this)
706726
if(await modalConfirm(msg)) {
707727
this.toDelete = true
708728
refreshAll()
@@ -713,7 +733,7 @@ ProofTree.prototype.image = function (root) {
713733
const msg = `Are you sure you want to <strong>detach</strong> the proof at the ${this.unicodeName} rule
714734
for the conclusion <br>${this.conclusion.unicode()} ?<br>
715735
This will unapply the ${this.unicodeName} rule in the current proof tree, and also will create an extra proof tree with the ${this.unicodeName} rule at the bottom, followed by the rest of this branch of the proof tree.`
716-
console.log(this);
736+
console.log(this)
717737
if(await modalConfirm(msg)) {
718738
let deepCopy = eval(this.reconstructor())
719739
addProof(deepCopy)

0 commit comments

Comments
 (0)