@stevenvo780/st-lang 3.1.1 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/lexer/lexer.d.ts.map +1 -1
- package/dist/lexer/lexer.js +8 -0
- package/dist/lexer/lexer.js.map +1 -1
- package/dist/lexer/tokens.d.ts +2 -0
- package/dist/lexer/tokens.d.ts.map +1 -1
- package/dist/lexer/tokens.js +6 -0
- package/dist/lexer/tokens.js.map +1 -1
- package/dist/parser/parser.d.ts.map +1 -1
- package/dist/parser/parser.js +11 -0
- package/dist/parser/parser.js.map +1 -1
- package/dist/profiles/aristotelian/syllogistic.d.ts +1 -1
- package/dist/profiles/aristotelian/syllogistic.d.ts.map +1 -1
- package/dist/profiles/aristotelian/syllogistic.js +26 -8
- package/dist/profiles/aristotelian/syllogistic.js.map +1 -1
- package/dist/profiles/arithmetic/index.d.ts +1 -1
- package/dist/profiles/arithmetic/index.d.ts.map +1 -1
- package/dist/profiles/arithmetic/index.js +29 -7
- package/dist/profiles/arithmetic/index.js.map +1 -1
- package/dist/profiles/classical/first-order.d.ts +1 -1
- package/dist/profiles/classical/first-order.d.ts.map +1 -1
- package/dist/profiles/classical/first-order.js +20 -3
- package/dist/profiles/classical/first-order.js.map +1 -1
- package/dist/profiles/classical/propositional.d.ts +1 -1
- package/dist/profiles/classical/propositional.d.ts.map +1 -1
- package/dist/profiles/classical/propositional.js +200 -51
- package/dist/profiles/classical/propositional.js.map +1 -1
- package/dist/profiles/intuitionistic/propositional.d.ts +1 -1
- package/dist/profiles/intuitionistic/propositional.d.ts.map +1 -1
- package/dist/profiles/intuitionistic/propositional.js +33 -5
- package/dist/profiles/intuitionistic/propositional.js.map +1 -1
- package/dist/profiles/paraconsistent/belnap.d.ts +1 -2
- package/dist/profiles/paraconsistent/belnap.d.ts.map +1 -1
- package/dist/profiles/paraconsistent/belnap.js +25 -11
- package/dist/profiles/paraconsistent/belnap.js.map +1 -1
- package/dist/profiles/probabilistic/basic.d.ts +1 -1
- package/dist/profiles/probabilistic/basic.d.ts.map +1 -1
- package/dist/profiles/probabilistic/basic.js +29 -5
- package/dist/profiles/probabilistic/basic.js.map +1 -1
- package/dist/profiles/shared/base-profile.d.ts +1 -1
- package/dist/profiles/shared/base-profile.d.ts.map +1 -1
- package/dist/profiles/shared/base-profile.js +20 -3
- package/dist/profiles/shared/base-profile.js.map +1 -1
- package/dist/profiles/shared/tableau-engine.d.ts.map +1 -1
- package/dist/profiles/shared/tableau-engine.js +6 -0
- package/dist/profiles/shared/tableau-engine.js.map +1 -1
- package/dist/repl/repl.d.ts.map +1 -1
- package/dist/repl/repl.js +5 -1
- package/dist/repl/repl.js.map +1 -1
- package/dist/runtime/compat.d.ts.map +1 -1
- package/dist/runtime/compat.js +2 -4
- package/dist/runtime/compat.js.map +1 -1
- package/dist/runtime/interpreter.d.ts.map +1 -1
- package/dist/runtime/interpreter.js +7 -4
- package/dist/runtime/interpreter.js.map +1 -1
- package/dist/tests/cli.test.js +5 -1
- package/dist/tests/cli.test.js.map +1 -1
- package/dist/tests/core.test.js +4 -1
- package/dist/tests/core.test.js.map +1 -1
- package/dist/tests/stress-exhaustive.test.js +5 -1
- package/dist/tests/stress-exhaustive.test.js.map +1 -1
- package/dist/types/index.d.ts +10 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +36 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -3
|
@@ -38,6 +38,10 @@ function computeCollectAtoms(f) {
|
|
|
38
38
|
}
|
|
39
39
|
function evaluateClassical(f, v) {
|
|
40
40
|
switch (f.kind) {
|
|
41
|
+
case 'true':
|
|
42
|
+
return true;
|
|
43
|
+
case 'false':
|
|
44
|
+
return false;
|
|
41
45
|
case 'atom':
|
|
42
46
|
return f.name ? (v[f.name] ?? false) : false;
|
|
43
47
|
case 'not':
|
|
@@ -311,6 +315,10 @@ function formulaToString(f) {
|
|
|
311
315
|
}
|
|
312
316
|
function computeFormulaToString(f) {
|
|
313
317
|
switch (f.kind) {
|
|
318
|
+
case 'true':
|
|
319
|
+
return '⊤';
|
|
320
|
+
case 'false':
|
|
321
|
+
return '⊥';
|
|
314
322
|
case 'atom':
|
|
315
323
|
return f.name || '?';
|
|
316
324
|
case 'not': {
|
|
@@ -425,6 +433,8 @@ function computeNNF(f) {
|
|
|
425
433
|
const args = node.args || [];
|
|
426
434
|
if (!negated) {
|
|
427
435
|
switch (k) {
|
|
436
|
+
case 'true':
|
|
437
|
+
case 'false':
|
|
428
438
|
case 'atom':
|
|
429
439
|
case 'predicate':
|
|
430
440
|
return node;
|
|
@@ -468,6 +478,10 @@ function computeNNF(f) {
|
|
|
468
478
|
}
|
|
469
479
|
else {
|
|
470
480
|
switch (k) {
|
|
481
|
+
case 'true':
|
|
482
|
+
return { kind: 'false' };
|
|
483
|
+
case 'false':
|
|
484
|
+
return { kind: 'true' };
|
|
471
485
|
case 'atom':
|
|
472
486
|
case 'predicate':
|
|
473
487
|
return { kind: 'not', args: [node] };
|
|
@@ -637,18 +651,105 @@ function getSubFormulas(f) {
|
|
|
637
651
|
// Remove atoms and the full formula itself
|
|
638
652
|
return result.filter((n) => n.kind !== 'atom' && formulaToString(n) !== formulaToString(f));
|
|
639
653
|
}
|
|
654
|
+
/**
|
|
655
|
+
* Igualdad estructural con alpha-equivalencia sobre variables cuantificadas.
|
|
656
|
+
* Cubre átomos, predicados, cuantificadores (∀/∃), modales y constantes.
|
|
657
|
+
*/
|
|
640
658
|
function formulasEqual(a, b) {
|
|
659
|
+
return alphaEqualFormulas(a, b, new Map(), new Map());
|
|
660
|
+
}
|
|
661
|
+
function alphaEqualFormulas(a, b, bindA, bindB, depth = 0) {
|
|
641
662
|
if (a.kind !== b.kind)
|
|
642
663
|
return false;
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
664
|
+
switch (a.kind) {
|
|
665
|
+
case 'true':
|
|
666
|
+
case 'false':
|
|
667
|
+
return true;
|
|
668
|
+
case 'atom': {
|
|
669
|
+
const nameA = a.name;
|
|
670
|
+
const nameB = b.name;
|
|
671
|
+
if (nameA === undefined || nameB === undefined)
|
|
672
|
+
return nameA === nameB;
|
|
673
|
+
const bA = bindA.get(nameA);
|
|
674
|
+
const bB = bindB.get(nameB);
|
|
675
|
+
if (bA !== undefined || bB !== undefined)
|
|
676
|
+
return bA === bB;
|
|
677
|
+
return nameA === nameB;
|
|
678
|
+
}
|
|
679
|
+
case 'number':
|
|
680
|
+
return a.value === b.value;
|
|
681
|
+
case 'predicate': {
|
|
682
|
+
if (a.name !== b.name)
|
|
683
|
+
return false;
|
|
684
|
+
const paramsA = a.params || a.terms || [];
|
|
685
|
+
const paramsB = b.params || b.terms || [];
|
|
686
|
+
if (paramsA.length !== paramsB.length)
|
|
687
|
+
return false;
|
|
688
|
+
for (let i = 0; i < paramsA.length; i++) {
|
|
689
|
+
const pA = paramsA[i];
|
|
690
|
+
const pB = paramsB[i];
|
|
691
|
+
const bndA = bindA.get(pA);
|
|
692
|
+
const bndB = bindB.get(pB);
|
|
693
|
+
if (bndA !== undefined || bndB !== undefined) {
|
|
694
|
+
if (bndA !== bndB)
|
|
695
|
+
return false;
|
|
696
|
+
}
|
|
697
|
+
else if (pA !== pB) {
|
|
698
|
+
return false;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
return true;
|
|
702
|
+
}
|
|
703
|
+
case 'forall':
|
|
704
|
+
case 'exists': {
|
|
705
|
+
const vA = a.variable;
|
|
706
|
+
const vB = b.variable;
|
|
707
|
+
if (!vA || !vB)
|
|
708
|
+
return vA === vB;
|
|
709
|
+
const innerA = a.args?.[0];
|
|
710
|
+
const innerB = b.args?.[0];
|
|
711
|
+
if (!innerA || !innerB)
|
|
712
|
+
return false;
|
|
713
|
+
const prevA = bindA.get(vA);
|
|
714
|
+
const prevB = bindB.get(vB);
|
|
715
|
+
bindA.set(vA, depth);
|
|
716
|
+
bindB.set(vB, depth);
|
|
717
|
+
const eq = alphaEqualFormulas(innerA, innerB, bindA, bindB, depth + 1);
|
|
718
|
+
if (prevA === undefined)
|
|
719
|
+
bindA.delete(vA);
|
|
720
|
+
else
|
|
721
|
+
bindA.set(vA, prevA);
|
|
722
|
+
if (prevB === undefined)
|
|
723
|
+
bindB.delete(vB);
|
|
724
|
+
else
|
|
725
|
+
bindB.set(vB, prevB);
|
|
726
|
+
return eq;
|
|
727
|
+
}
|
|
728
|
+
case 'modal_necessity':
|
|
729
|
+
case 'modal_possibility':
|
|
730
|
+
case 'temporal_next':
|
|
731
|
+
case 'temporal_until': {
|
|
732
|
+
if (a.name !== b.name)
|
|
733
|
+
return false;
|
|
734
|
+
const argsA = a.args || [];
|
|
735
|
+
const argsB = b.args || [];
|
|
736
|
+
if (argsA.length !== argsB.length)
|
|
737
|
+
return false;
|
|
738
|
+
return argsA.every((arg, i) => alphaEqualFormulas(arg, argsB[i], bindA, bindB, depth));
|
|
739
|
+
}
|
|
740
|
+
default: {
|
|
741
|
+
const argsA = a.args || [];
|
|
742
|
+
const argsB = b.args || [];
|
|
743
|
+
if (argsA.length !== argsB.length)
|
|
744
|
+
return false;
|
|
745
|
+
if (argsA.length === 0) {
|
|
746
|
+
if (a.name !== b.name)
|
|
747
|
+
return false;
|
|
748
|
+
return a.value === b.value;
|
|
749
|
+
}
|
|
750
|
+
return argsA.every((arg, i) => alphaEqualFormulas(arg, argsB[i], bindA, bindB, depth));
|
|
751
|
+
}
|
|
650
752
|
}
|
|
651
|
-
return false;
|
|
652
753
|
}
|
|
653
754
|
// --- Motor de derivación ---
|
|
654
755
|
/** Límite duro de fórmulas derivadas para evitar explosión combinatoria */
|
|
@@ -690,7 +791,7 @@ function isRelevantToGoal(f, goal) {
|
|
|
690
791
|
};
|
|
691
792
|
return checkSub(goal);
|
|
692
793
|
}
|
|
693
|
-
function addDerivedFormula(state, formula, justification, premises) {
|
|
794
|
+
function addDerivedFormula(state, formula, justification, premises, source = 'rule') {
|
|
694
795
|
const hash = formulaHash(formula);
|
|
695
796
|
if (state.known.has(hash))
|
|
696
797
|
return false;
|
|
@@ -700,6 +801,7 @@ function addDerivedFormula(state, formula, justification, premises) {
|
|
|
700
801
|
formula,
|
|
701
802
|
justification,
|
|
702
803
|
premises,
|
|
804
|
+
source,
|
|
703
805
|
});
|
|
704
806
|
state.known.set(hash, formula);
|
|
705
807
|
return true;
|
|
@@ -809,6 +911,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
809
911
|
formula: f,
|
|
810
912
|
justification: `Premisa (${name})`,
|
|
811
913
|
premises: [],
|
|
914
|
+
source: 'premise',
|
|
812
915
|
});
|
|
813
916
|
state.known.set(formulaHash(f), f);
|
|
814
917
|
}
|
|
@@ -1423,14 +1526,14 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1423
1526
|
const subProof = tryDerive(subGoal, tempTheory, subPremises, depth + 1);
|
|
1424
1527
|
if (subProof && subProof.status === 'complete') {
|
|
1425
1528
|
// Check the sub-proof doesn't rely solely on semantic fallback
|
|
1426
|
-
const isSyntactic = subProof.steps.every((s) =>
|
|
1529
|
+
const isSyntactic = subProof.steps.every((s) => s.source !== 'semantic');
|
|
1427
1530
|
if (isSyntactic) {
|
|
1428
1531
|
// Build the main proof: premises + sub-derivation steps + conditional proof conclusion
|
|
1429
1532
|
const mainSteps = [];
|
|
1430
1533
|
let stepNum = 0;
|
|
1431
1534
|
// Copy premise steps from current state
|
|
1432
1535
|
for (const s of state.steps) {
|
|
1433
|
-
if (s.
|
|
1536
|
+
if (s.source === 'premise') {
|
|
1434
1537
|
stepNum++;
|
|
1435
1538
|
mainSteps.push({ ...s, stepNumber: stepNum, premises: [] });
|
|
1436
1539
|
}
|
|
@@ -1443,17 +1546,18 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1443
1546
|
formula: assumption,
|
|
1444
1547
|
justification: 'Supuesto (para prueba condicional)',
|
|
1445
1548
|
premises: [],
|
|
1549
|
+
source: 'assumption',
|
|
1446
1550
|
});
|
|
1447
1551
|
// Add sub-derivation steps (renumber, adjusting premise references)
|
|
1448
1552
|
const subStepMap = new Map();
|
|
1449
1553
|
for (const s of subProof.steps) {
|
|
1450
|
-
if (s.
|
|
1554
|
+
if (s.source === 'premise' && formulasEqual(s.formula, assumption)) {
|
|
1451
1555
|
subStepMap.set(s.stepNumber, assumptionStepNum);
|
|
1452
1556
|
continue;
|
|
1453
1557
|
}
|
|
1454
|
-
if (s.
|
|
1558
|
+
if (s.source === 'premise') {
|
|
1455
1559
|
// Find existing premise step in main
|
|
1456
|
-
const existing = mainSteps.find((ms) => ms.
|
|
1560
|
+
const existing = mainSteps.find((ms) => ms.source === 'premise' && formulasEqual(ms.formula, s.formula));
|
|
1457
1561
|
if (existing) {
|
|
1458
1562
|
subStepMap.set(s.stepNumber, existing.stepNumber);
|
|
1459
1563
|
continue;
|
|
@@ -1466,6 +1570,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1466
1570
|
formula: s.formula,
|
|
1467
1571
|
justification: s.justification,
|
|
1468
1572
|
premises: s.premises.map((p) => subStepMap.get(p) || p),
|
|
1573
|
+
source: s.source,
|
|
1469
1574
|
});
|
|
1470
1575
|
}
|
|
1471
1576
|
// Add final conditional proof step
|
|
@@ -1477,6 +1582,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1477
1582
|
justification: 'Prueba Condicional (Teorema de Deduccion)',
|
|
1478
1583
|
premises: [assumptionStepNum, subGoalStepNum],
|
|
1479
1584
|
subproofs: [subProof],
|
|
1585
|
+
source: 'rule',
|
|
1480
1586
|
});
|
|
1481
1587
|
return buildProof(goal, mainSteps, premiseNames, theory, 'natural_deduction', [subProof]);
|
|
1482
1588
|
}
|
|
@@ -1505,7 +1611,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1505
1611
|
const subProofL = tryDerive(goal, tempTheoryL, subPremisesL, depth + 1);
|
|
1506
1612
|
if (!subProofL || subProofL.status !== 'complete')
|
|
1507
1613
|
continue;
|
|
1508
|
-
const isSyntacticL = subProofL.steps.every((s) =>
|
|
1614
|
+
const isSyntacticL = subProofL.steps.every((s) => s.source !== 'semantic');
|
|
1509
1615
|
if (!isSyntacticL)
|
|
1510
1616
|
continue;
|
|
1511
1617
|
// Try to derive goal assuming right
|
|
@@ -1522,7 +1628,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1522
1628
|
const subProofR = tryDerive(goal, tempTheoryR, subPremisesR, depth + 1);
|
|
1523
1629
|
if (!subProofR || subProofR.status !== 'complete')
|
|
1524
1630
|
continue;
|
|
1525
|
-
const isSyntacticR = subProofR.steps.every((s) =>
|
|
1631
|
+
const isSyntacticR = subProofR.steps.every((s) => s.source !== 'semantic');
|
|
1526
1632
|
if (!isSyntacticR)
|
|
1527
1633
|
continue;
|
|
1528
1634
|
// Both cases succeed — build proof by cases
|
|
@@ -1530,7 +1636,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1530
1636
|
let stepNum = 0;
|
|
1531
1637
|
// Copy premise steps
|
|
1532
1638
|
for (const s of state.steps) {
|
|
1533
|
-
if (s.
|
|
1639
|
+
if (s.source === 'premise') {
|
|
1534
1640
|
stepNum++;
|
|
1535
1641
|
mainSteps.push({ ...s, stepNumber: stepNum, premises: [] });
|
|
1536
1642
|
}
|
|
@@ -1544,15 +1650,16 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1544
1650
|
formula: left,
|
|
1545
1651
|
justification: 'Supuesto (caso izquierdo)',
|
|
1546
1652
|
premises: [],
|
|
1653
|
+
source: 'assumption',
|
|
1547
1654
|
});
|
|
1548
1655
|
const leftStepMap = new Map();
|
|
1549
1656
|
for (const s of subProofL.steps) {
|
|
1550
|
-
if (s.
|
|
1657
|
+
if (s.source === 'premise' && formulasEqual(s.formula, left)) {
|
|
1551
1658
|
leftStepMap.set(s.stepNumber, leftAssumptionStep);
|
|
1552
1659
|
continue;
|
|
1553
1660
|
}
|
|
1554
|
-
if (s.
|
|
1555
|
-
const existing = mainSteps.find((ms) => ms.
|
|
1661
|
+
if (s.source === 'premise') {
|
|
1662
|
+
const existing = mainSteps.find((ms) => ms.source === 'premise' && formulasEqual(ms.formula, s.formula));
|
|
1556
1663
|
if (existing) {
|
|
1557
1664
|
leftStepMap.set(s.stepNumber, existing.stepNumber);
|
|
1558
1665
|
continue;
|
|
@@ -1565,6 +1672,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1565
1672
|
formula: s.formula,
|
|
1566
1673
|
justification: s.justification,
|
|
1567
1674
|
premises: s.premises.map((p) => leftStepMap.get(p) || p),
|
|
1675
|
+
source: s.source,
|
|
1568
1676
|
});
|
|
1569
1677
|
}
|
|
1570
1678
|
const leftGoalStep = leftStepMap.get(subProofL.steps[subProofL.steps.length - 1]?.stepNumber ?? 0) ?? stepNum;
|
|
@@ -1576,15 +1684,16 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1576
1684
|
formula: right,
|
|
1577
1685
|
justification: 'Supuesto (caso derecho)',
|
|
1578
1686
|
premises: [],
|
|
1687
|
+
source: 'assumption',
|
|
1579
1688
|
});
|
|
1580
1689
|
const rightStepMap = new Map();
|
|
1581
1690
|
for (const s of subProofR.steps) {
|
|
1582
|
-
if (s.
|
|
1691
|
+
if (s.source === 'premise' && formulasEqual(s.formula, right)) {
|
|
1583
1692
|
rightStepMap.set(s.stepNumber, rightAssumptionStep);
|
|
1584
1693
|
continue;
|
|
1585
1694
|
}
|
|
1586
|
-
if (s.
|
|
1587
|
-
const existing = mainSteps.find((ms) => ms.
|
|
1695
|
+
if (s.source === 'premise') {
|
|
1696
|
+
const existing = mainSteps.find((ms) => ms.source === 'premise' && formulasEqual(ms.formula, s.formula));
|
|
1588
1697
|
if (existing) {
|
|
1589
1698
|
rightStepMap.set(s.stepNumber, existing.stepNumber);
|
|
1590
1699
|
continue;
|
|
@@ -1597,6 +1706,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1597
1706
|
formula: s.formula,
|
|
1598
1707
|
justification: s.justification,
|
|
1599
1708
|
premises: s.premises.map((p) => rightStepMap.get(p) || p),
|
|
1709
|
+
source: s.source,
|
|
1600
1710
|
});
|
|
1601
1711
|
}
|
|
1602
1712
|
const rightGoalStep = rightStepMap.get(subProofR.steps[subProofR.steps.length - 1]?.stepNumber ?? 0) ?? stepNum;
|
|
@@ -1608,6 +1718,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1608
1718
|
justification: 'Eliminacion de disyuncion (prueba por casos)',
|
|
1609
1719
|
premises: [disjStepNum, leftGoalStep, rightGoalStep],
|
|
1610
1720
|
subproofs: [subProofL, subProofR],
|
|
1721
|
+
source: 'rule',
|
|
1611
1722
|
});
|
|
1612
1723
|
return buildProof(goal, mainSteps, premiseNames, theory, 'natural_deduction', [
|
|
1613
1724
|
subProofL,
|
|
@@ -1680,6 +1791,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1680
1791
|
formula: goal,
|
|
1681
1792
|
justification: 'Verificacion semantica (todas las valuaciones satisfacen la consecuencia)',
|
|
1682
1793
|
premises: premiseStepNums,
|
|
1794
|
+
source: 'semantic',
|
|
1683
1795
|
});
|
|
1684
1796
|
state.known.set(goalHash, goal);
|
|
1685
1797
|
}
|
|
@@ -1904,26 +2016,56 @@ class ClassicalPropositional {
|
|
|
1904
2016
|
};
|
|
1905
2017
|
}
|
|
1906
2018
|
}
|
|
1907
|
-
prove(goal, theory) {
|
|
2019
|
+
prove(goal, theory, premises) {
|
|
1908
2020
|
const wf = this.checkWellFormed(goal);
|
|
1909
2021
|
if (wf.length > 0) {
|
|
1910
2022
|
return { status: 'error', diagnostics: wf, formula: goal };
|
|
1911
2023
|
}
|
|
1912
|
-
const
|
|
1913
|
-
const
|
|
2024
|
+
const usingRestricted = premises !== undefined && premises.length > 0;
|
|
2025
|
+
const premiseNames = usingRestricted
|
|
2026
|
+
? premises.filter((n) => theory.axioms.has(n) || theory.theorems.has(n))
|
|
2027
|
+
: Array.from(theory.axioms.keys());
|
|
2028
|
+
const diagnostics = [];
|
|
2029
|
+
if (usingRestricted) {
|
|
2030
|
+
for (const n of premises) {
|
|
2031
|
+
if (!theory.axioms.has(n) && !theory.theorems.has(n)) {
|
|
2032
|
+
diagnostics.push({
|
|
2033
|
+
severity: 'warning',
|
|
2034
|
+
message: `Premisa '${n}' no encontrada en la teoría; será ignorada en prove`,
|
|
2035
|
+
});
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
const effectiveTheory = usingRestricted
|
|
2040
|
+
? {
|
|
2041
|
+
profile: theory.profile,
|
|
2042
|
+
axioms: new Map(premiseNames
|
|
2043
|
+
.filter((n) => theory.axioms.has(n))
|
|
2044
|
+
.map((n) => [n, theory.axioms.get(n)])),
|
|
2045
|
+
theorems: new Map(premiseNames
|
|
2046
|
+
.filter((n) => theory.theorems.has(n))
|
|
2047
|
+
.map((n) => [n, theory.theorems.get(n)])),
|
|
2048
|
+
claims: theory.claims,
|
|
2049
|
+
judgments: theory.judgments,
|
|
2050
|
+
}
|
|
2051
|
+
: theory;
|
|
2052
|
+
const proof = tryDerive(goal, effectiveTheory, premiseNames);
|
|
1914
2053
|
if (proof && proof.status === 'complete') {
|
|
2054
|
+
const isSemantic = proof.method === 'semantic';
|
|
1915
2055
|
return {
|
|
1916
2056
|
status: 'provable',
|
|
1917
|
-
output:
|
|
2057
|
+
output: isSemantic
|
|
2058
|
+
? `${formulaToString(goal)} es DEMOSTRABLE desde la teoria (verificación semántica, sin derivación sintáctica)`
|
|
2059
|
+
: `${formulaToString(goal)} es DEMOSTRABLE desde la teoria`,
|
|
1918
2060
|
proof,
|
|
1919
2061
|
educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'prove', ok: true }),
|
|
1920
|
-
diagnostics
|
|
2062
|
+
diagnostics,
|
|
1921
2063
|
formula: goal,
|
|
1922
2064
|
};
|
|
1923
2065
|
}
|
|
1924
2066
|
// Semantic fallback: verify via SAT/truth-table whether goal follows from axioms
|
|
1925
2067
|
const allAxiomFormulas = premiseNames
|
|
1926
|
-
.map((n) =>
|
|
2068
|
+
.map((n) => effectiveTheory.axioms.get(n) || effectiveTheory.theorems.get(n))
|
|
1927
2069
|
.filter((f) => f !== undefined);
|
|
1928
2070
|
let semanticResult;
|
|
1929
2071
|
const atoms = new Set();
|
|
@@ -1980,42 +2122,46 @@ class ClassicalPropositional {
|
|
|
1980
2122
|
}
|
|
1981
2123
|
}
|
|
1982
2124
|
if (semanticResult) {
|
|
2125
|
+
const premiseSteps = [];
|
|
2126
|
+
premiseNames.forEach((n, i) => {
|
|
2127
|
+
const f = effectiveTheory.axioms.get(n) || effectiveTheory.theorems.get(n);
|
|
2128
|
+
if (f) {
|
|
2129
|
+
premiseSteps.push({
|
|
2130
|
+
stepNumber: i + 1,
|
|
2131
|
+
formula: f,
|
|
2132
|
+
justification: `Premisa (${n})`,
|
|
2133
|
+
premises: [],
|
|
2134
|
+
source: 'premise',
|
|
2135
|
+
});
|
|
2136
|
+
}
|
|
2137
|
+
});
|
|
1983
2138
|
const semanticProofSteps = [
|
|
1984
|
-
...
|
|
1985
|
-
.map((n, i) => {
|
|
1986
|
-
const f = theory.axioms.get(n) || theory.theorems.get(n);
|
|
1987
|
-
return f
|
|
1988
|
-
? {
|
|
1989
|
-
stepNumber: i + 1,
|
|
1990
|
-
formula: f,
|
|
1991
|
-
justification: `Premisa (${n})`,
|
|
1992
|
-
premises: [],
|
|
1993
|
-
}
|
|
1994
|
-
: null;
|
|
1995
|
-
})
|
|
1996
|
-
.filter((s) => s !== null),
|
|
2139
|
+
...premiseSteps,
|
|
1997
2140
|
{
|
|
1998
2141
|
stepNumber: premiseNames.length + 1,
|
|
1999
2142
|
formula: goal,
|
|
2000
2143
|
justification: 'Verificacion semantica (tautologia o consecuencia logica)',
|
|
2001
2144
|
premises: premiseNames.map((_, i) => i + 1),
|
|
2145
|
+
source: 'semantic',
|
|
2002
2146
|
},
|
|
2003
2147
|
];
|
|
2004
|
-
const semanticProof = buildProof(goal, semanticProofSteps, premiseNames,
|
|
2148
|
+
const semanticProof = buildProof(goal, semanticProofSteps, premiseNames, effectiveTheory, 'semantic');
|
|
2005
2149
|
return {
|
|
2006
2150
|
status: 'provable',
|
|
2007
|
-
output: `${formulaToString(goal)} es DEMOSTRABLE desde la teoria`,
|
|
2151
|
+
output: `${formulaToString(goal)} es DEMOSTRABLE desde la teoria (verificación semántica, sin derivación sintáctica)`,
|
|
2008
2152
|
proof: semanticProof,
|
|
2009
2153
|
educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'prove', ok: true }),
|
|
2010
|
-
diagnostics
|
|
2154
|
+
diagnostics,
|
|
2011
2155
|
formula: goal,
|
|
2012
2156
|
};
|
|
2013
2157
|
}
|
|
2158
|
+
// Ni derivación sintáctica ni consecuencia semántica: existe contramodelo.
|
|
2159
|
+
// Esto sí es refutable en el sentido fuerte.
|
|
2014
2160
|
return {
|
|
2015
2161
|
status: 'refutable',
|
|
2016
|
-
output: `${formulaToString(goal)} NO
|
|
2162
|
+
output: `${formulaToString(goal)} NO se sigue de la teoría (existe contramodelo en ${formulaToString(goal)})`,
|
|
2017
2163
|
educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'prove', ok: false }),
|
|
2018
|
-
diagnostics
|
|
2164
|
+
diagnostics,
|
|
2019
2165
|
formula: goal,
|
|
2020
2166
|
};
|
|
2021
2167
|
}
|
|
@@ -2029,14 +2175,17 @@ class ClassicalPropositional {
|
|
|
2029
2175
|
// Build reasoning info
|
|
2030
2176
|
const rulesUsed = new Set();
|
|
2031
2177
|
for (const step of proof.steps) {
|
|
2032
|
-
if (
|
|
2178
|
+
if (step.source !== 'premise') {
|
|
2033
2179
|
rulesUsed.add(step.justification);
|
|
2034
2180
|
}
|
|
2035
2181
|
}
|
|
2036
2182
|
const reasoningType = rulesUsed.size > 0 ? Array.from(rulesUsed).join(', ') : 'Derivación directa';
|
|
2183
|
+
const isSemantic = proof.method === 'semantic';
|
|
2037
2184
|
return {
|
|
2038
2185
|
status: 'provable',
|
|
2039
|
-
output:
|
|
2186
|
+
output: isSemantic
|
|
2187
|
+
? `${formulaToString(goal)} derivado (verificación semántica, sin derivación sintáctica)`
|
|
2188
|
+
: `${formulaToString(goal)} derivado exitosamente`,
|
|
2040
2189
|
proof,
|
|
2041
2190
|
reasoningType,
|
|
2042
2191
|
reasoningSchema: rulesUsed.has('Modus Ponens')
|
|
@@ -2057,8 +2206,8 @@ class ClassicalPropositional {
|
|
|
2057
2206
|
};
|
|
2058
2207
|
}
|
|
2059
2208
|
return {
|
|
2060
|
-
status: '
|
|
2061
|
-
output: `No se
|
|
2209
|
+
status: 'unknown',
|
|
2210
|
+
output: `No se pudo derivar ${formulaToString(goal)} desde las premisas dadas (sin refutación)`,
|
|
2062
2211
|
educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'derive', ok: false }),
|
|
2063
2212
|
diagnostics: [],
|
|
2064
2213
|
formula: goal,
|