@stevenvo780/st-lang 3.1.1 → 3.1.3
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/cli/index.js +6 -11
- package/dist/cli/index.js.map +1 -1
- 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 +40 -6
- 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 +21 -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 +205 -53
- 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 +54 -7
- 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 +26 -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 +30 -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 +21 -3
- package/dist/profiles/shared/base-profile.js.map +1 -1
- package/dist/profiles/shared/tableau-engine.d.ts +6 -0
- package/dist/profiles/shared/tableau-engine.d.ts.map +1 -1
- package/dist/profiles/shared/tableau-engine.js +39 -6
- package/dist/profiles/shared/tableau-engine.js.map +1 -1
- package/dist/profiles/temporal/ltl.d.ts +2 -1
- package/dist/profiles/temporal/ltl.d.ts.map +1 -1
- package/dist/profiles/temporal/ltl.js +5 -1
- package/dist/profiles/temporal/ltl.js.map +1 -1
- package/dist/protocol/handler.d.ts +0 -2
- package/dist/protocol/handler.d.ts.map +1 -1
- package/dist/protocol/handler.js +2 -6
- package/dist/protocol/handler.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 +8 -0
- package/dist/runtime/interpreter.d.ts.map +1 -1
- package/dist/runtime/interpreter.js +194 -52
- package/dist/runtime/interpreter.js.map +1 -1
- package/dist/runtime/known-theorems.d.ts.map +1 -1
- package/dist/runtime/known-theorems.js +17 -5
- package/dist/runtime/known-theorems.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/parser.test.js +10 -0
- package/dist/tests/parser.test.js.map +1 -1
- package/dist/tests/profiles.test.js +16 -0
- package/dist/tests/profiles.test.js.map +1 -1
- package/dist/tests/protocol-text-layer.test.js +18 -0
- package/dist/tests/protocol-text-layer.test.js.map +1 -1
- package/dist/tests/regressions.test.d.ts +2 -0
- package/dist/tests/regressions.test.d.ts.map +1 -0
- package/dist/tests/regressions.test.js +167 -0
- package/dist/tests/regressions.test.js.map +1 -0
- 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':
|
|
@@ -106,11 +110,14 @@ function* generateValuationsLazy(atoms) {
|
|
|
106
110
|
yield {};
|
|
107
111
|
return;
|
|
108
112
|
}
|
|
109
|
-
|
|
113
|
+
if (n > 23)
|
|
114
|
+
throw new Error('Demasiadas variables para tabla de verdad (>23)');
|
|
115
|
+
const total = 2 ** n;
|
|
110
116
|
for (let i = 0; i < total; i++) {
|
|
111
117
|
const v = {};
|
|
112
118
|
for (let j = 0; j < n; j++) {
|
|
113
|
-
|
|
119
|
+
const divisor = 2 ** (n - 1 - j);
|
|
120
|
+
v[atoms[j]] = Math.floor(i / divisor) % 2 === 1;
|
|
114
121
|
}
|
|
115
122
|
yield v;
|
|
116
123
|
}
|
|
@@ -311,6 +318,10 @@ function formulaToString(f) {
|
|
|
311
318
|
}
|
|
312
319
|
function computeFormulaToString(f) {
|
|
313
320
|
switch (f.kind) {
|
|
321
|
+
case 'true':
|
|
322
|
+
return '⊤';
|
|
323
|
+
case 'false':
|
|
324
|
+
return '⊥';
|
|
314
325
|
case 'atom':
|
|
315
326
|
return f.name || '?';
|
|
316
327
|
case 'not': {
|
|
@@ -425,6 +436,8 @@ function computeNNF(f) {
|
|
|
425
436
|
const args = node.args || [];
|
|
426
437
|
if (!negated) {
|
|
427
438
|
switch (k) {
|
|
439
|
+
case 'true':
|
|
440
|
+
case 'false':
|
|
428
441
|
case 'atom':
|
|
429
442
|
case 'predicate':
|
|
430
443
|
return node;
|
|
@@ -468,6 +481,10 @@ function computeNNF(f) {
|
|
|
468
481
|
}
|
|
469
482
|
else {
|
|
470
483
|
switch (k) {
|
|
484
|
+
case 'true':
|
|
485
|
+
return { kind: 'false' };
|
|
486
|
+
case 'false':
|
|
487
|
+
return { kind: 'true' };
|
|
471
488
|
case 'atom':
|
|
472
489
|
case 'predicate':
|
|
473
490
|
return { kind: 'not', args: [node] };
|
|
@@ -637,18 +654,105 @@ function getSubFormulas(f) {
|
|
|
637
654
|
// Remove atoms and the full formula itself
|
|
638
655
|
return result.filter((n) => n.kind !== 'atom' && formulaToString(n) !== formulaToString(f));
|
|
639
656
|
}
|
|
657
|
+
/**
|
|
658
|
+
* Igualdad estructural con alpha-equivalencia sobre variables cuantificadas.
|
|
659
|
+
* Cubre átomos, predicados, cuantificadores (∀/∃), modales y constantes.
|
|
660
|
+
*/
|
|
640
661
|
function formulasEqual(a, b) {
|
|
662
|
+
return alphaEqualFormulas(a, b, new Map(), new Map());
|
|
663
|
+
}
|
|
664
|
+
function alphaEqualFormulas(a, b, bindA, bindB, depth = 0) {
|
|
641
665
|
if (a.kind !== b.kind)
|
|
642
666
|
return false;
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
667
|
+
switch (a.kind) {
|
|
668
|
+
case 'true':
|
|
669
|
+
case 'false':
|
|
670
|
+
return true;
|
|
671
|
+
case 'atom': {
|
|
672
|
+
const nameA = a.name;
|
|
673
|
+
const nameB = b.name;
|
|
674
|
+
if (nameA === undefined || nameB === undefined)
|
|
675
|
+
return nameA === nameB;
|
|
676
|
+
const bA = bindA.get(nameA);
|
|
677
|
+
const bB = bindB.get(nameB);
|
|
678
|
+
if (bA !== undefined || bB !== undefined)
|
|
679
|
+
return bA === bB;
|
|
680
|
+
return nameA === nameB;
|
|
681
|
+
}
|
|
682
|
+
case 'number':
|
|
683
|
+
return a.value === b.value;
|
|
684
|
+
case 'predicate': {
|
|
685
|
+
if (a.name !== b.name)
|
|
686
|
+
return false;
|
|
687
|
+
const paramsA = a.params || a.terms || [];
|
|
688
|
+
const paramsB = b.params || b.terms || [];
|
|
689
|
+
if (paramsA.length !== paramsB.length)
|
|
690
|
+
return false;
|
|
691
|
+
for (let i = 0; i < paramsA.length; i++) {
|
|
692
|
+
const pA = paramsA[i];
|
|
693
|
+
const pB = paramsB[i];
|
|
694
|
+
const bndA = bindA.get(pA);
|
|
695
|
+
const bndB = bindB.get(pB);
|
|
696
|
+
if (bndA !== undefined || bndB !== undefined) {
|
|
697
|
+
if (bndA !== bndB)
|
|
698
|
+
return false;
|
|
699
|
+
}
|
|
700
|
+
else if (pA !== pB) {
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
return true;
|
|
705
|
+
}
|
|
706
|
+
case 'forall':
|
|
707
|
+
case 'exists': {
|
|
708
|
+
const vA = a.variable;
|
|
709
|
+
const vB = b.variable;
|
|
710
|
+
if (!vA || !vB)
|
|
711
|
+
return vA === vB;
|
|
712
|
+
const innerA = a.args?.[0];
|
|
713
|
+
const innerB = b.args?.[0];
|
|
714
|
+
if (!innerA || !innerB)
|
|
715
|
+
return false;
|
|
716
|
+
const prevA = bindA.get(vA);
|
|
717
|
+
const prevB = bindB.get(vB);
|
|
718
|
+
bindA.set(vA, depth);
|
|
719
|
+
bindB.set(vB, depth);
|
|
720
|
+
const eq = alphaEqualFormulas(innerA, innerB, bindA, bindB, depth + 1);
|
|
721
|
+
if (prevA === undefined)
|
|
722
|
+
bindA.delete(vA);
|
|
723
|
+
else
|
|
724
|
+
bindA.set(vA, prevA);
|
|
725
|
+
if (prevB === undefined)
|
|
726
|
+
bindB.delete(vB);
|
|
727
|
+
else
|
|
728
|
+
bindB.set(vB, prevB);
|
|
729
|
+
return eq;
|
|
730
|
+
}
|
|
731
|
+
case 'modal_necessity':
|
|
732
|
+
case 'modal_possibility':
|
|
733
|
+
case 'temporal_next':
|
|
734
|
+
case 'temporal_until': {
|
|
735
|
+
if (a.name !== b.name)
|
|
736
|
+
return false;
|
|
737
|
+
const argsA = a.args || [];
|
|
738
|
+
const argsB = b.args || [];
|
|
739
|
+
if (argsA.length !== argsB.length)
|
|
740
|
+
return false;
|
|
741
|
+
return argsA.every((arg, i) => alphaEqualFormulas(arg, argsB[i], bindA, bindB, depth));
|
|
742
|
+
}
|
|
743
|
+
default: {
|
|
744
|
+
const argsA = a.args || [];
|
|
745
|
+
const argsB = b.args || [];
|
|
746
|
+
if (argsA.length !== argsB.length)
|
|
747
|
+
return false;
|
|
748
|
+
if (argsA.length === 0) {
|
|
749
|
+
if (a.name !== b.name)
|
|
750
|
+
return false;
|
|
751
|
+
return a.value === b.value;
|
|
752
|
+
}
|
|
753
|
+
return argsA.every((arg, i) => alphaEqualFormulas(arg, argsB[i], bindA, bindB, depth));
|
|
754
|
+
}
|
|
650
755
|
}
|
|
651
|
-
return false;
|
|
652
756
|
}
|
|
653
757
|
// --- Motor de derivación ---
|
|
654
758
|
/** Límite duro de fórmulas derivadas para evitar explosión combinatoria */
|
|
@@ -690,7 +794,7 @@ function isRelevantToGoal(f, goal) {
|
|
|
690
794
|
};
|
|
691
795
|
return checkSub(goal);
|
|
692
796
|
}
|
|
693
|
-
function addDerivedFormula(state, formula, justification, premises) {
|
|
797
|
+
function addDerivedFormula(state, formula, justification, premises, source = 'rule') {
|
|
694
798
|
const hash = formulaHash(formula);
|
|
695
799
|
if (state.known.has(hash))
|
|
696
800
|
return false;
|
|
@@ -700,6 +804,7 @@ function addDerivedFormula(state, formula, justification, premises) {
|
|
|
700
804
|
formula,
|
|
701
805
|
justification,
|
|
702
806
|
premises,
|
|
807
|
+
source,
|
|
703
808
|
});
|
|
704
809
|
state.known.set(hash, formula);
|
|
705
810
|
return true;
|
|
@@ -809,6 +914,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
809
914
|
formula: f,
|
|
810
915
|
justification: `Premisa (${name})`,
|
|
811
916
|
premises: [],
|
|
917
|
+
source: 'premise',
|
|
812
918
|
});
|
|
813
919
|
state.known.set(formulaHash(f), f);
|
|
814
920
|
}
|
|
@@ -1423,14 +1529,14 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1423
1529
|
const subProof = tryDerive(subGoal, tempTheory, subPremises, depth + 1);
|
|
1424
1530
|
if (subProof && subProof.status === 'complete') {
|
|
1425
1531
|
// Check the sub-proof doesn't rely solely on semantic fallback
|
|
1426
|
-
const isSyntactic = subProof.steps.every((s) =>
|
|
1532
|
+
const isSyntactic = subProof.steps.every((s) => s.source !== 'semantic');
|
|
1427
1533
|
if (isSyntactic) {
|
|
1428
1534
|
// Build the main proof: premises + sub-derivation steps + conditional proof conclusion
|
|
1429
1535
|
const mainSteps = [];
|
|
1430
1536
|
let stepNum = 0;
|
|
1431
1537
|
// Copy premise steps from current state
|
|
1432
1538
|
for (const s of state.steps) {
|
|
1433
|
-
if (s.
|
|
1539
|
+
if (s.source === 'premise') {
|
|
1434
1540
|
stepNum++;
|
|
1435
1541
|
mainSteps.push({ ...s, stepNumber: stepNum, premises: [] });
|
|
1436
1542
|
}
|
|
@@ -1443,17 +1549,18 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1443
1549
|
formula: assumption,
|
|
1444
1550
|
justification: 'Supuesto (para prueba condicional)',
|
|
1445
1551
|
premises: [],
|
|
1552
|
+
source: 'assumption',
|
|
1446
1553
|
});
|
|
1447
1554
|
// Add sub-derivation steps (renumber, adjusting premise references)
|
|
1448
1555
|
const subStepMap = new Map();
|
|
1449
1556
|
for (const s of subProof.steps) {
|
|
1450
|
-
if (s.
|
|
1557
|
+
if (s.source === 'premise' && formulasEqual(s.formula, assumption)) {
|
|
1451
1558
|
subStepMap.set(s.stepNumber, assumptionStepNum);
|
|
1452
1559
|
continue;
|
|
1453
1560
|
}
|
|
1454
|
-
if (s.
|
|
1561
|
+
if (s.source === 'premise') {
|
|
1455
1562
|
// Find existing premise step in main
|
|
1456
|
-
const existing = mainSteps.find((ms) => ms.
|
|
1563
|
+
const existing = mainSteps.find((ms) => ms.source === 'premise' && formulasEqual(ms.formula, s.formula));
|
|
1457
1564
|
if (existing) {
|
|
1458
1565
|
subStepMap.set(s.stepNumber, existing.stepNumber);
|
|
1459
1566
|
continue;
|
|
@@ -1466,6 +1573,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1466
1573
|
formula: s.formula,
|
|
1467
1574
|
justification: s.justification,
|
|
1468
1575
|
premises: s.premises.map((p) => subStepMap.get(p) || p),
|
|
1576
|
+
source: s.source,
|
|
1469
1577
|
});
|
|
1470
1578
|
}
|
|
1471
1579
|
// Add final conditional proof step
|
|
@@ -1477,6 +1585,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1477
1585
|
justification: 'Prueba Condicional (Teorema de Deduccion)',
|
|
1478
1586
|
premises: [assumptionStepNum, subGoalStepNum],
|
|
1479
1587
|
subproofs: [subProof],
|
|
1588
|
+
source: 'rule',
|
|
1480
1589
|
});
|
|
1481
1590
|
return buildProof(goal, mainSteps, premiseNames, theory, 'natural_deduction', [subProof]);
|
|
1482
1591
|
}
|
|
@@ -1505,7 +1614,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1505
1614
|
const subProofL = tryDerive(goal, tempTheoryL, subPremisesL, depth + 1);
|
|
1506
1615
|
if (!subProofL || subProofL.status !== 'complete')
|
|
1507
1616
|
continue;
|
|
1508
|
-
const isSyntacticL = subProofL.steps.every((s) =>
|
|
1617
|
+
const isSyntacticL = subProofL.steps.every((s) => s.source !== 'semantic');
|
|
1509
1618
|
if (!isSyntacticL)
|
|
1510
1619
|
continue;
|
|
1511
1620
|
// Try to derive goal assuming right
|
|
@@ -1522,7 +1631,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1522
1631
|
const subProofR = tryDerive(goal, tempTheoryR, subPremisesR, depth + 1);
|
|
1523
1632
|
if (!subProofR || subProofR.status !== 'complete')
|
|
1524
1633
|
continue;
|
|
1525
|
-
const isSyntacticR = subProofR.steps.every((s) =>
|
|
1634
|
+
const isSyntacticR = subProofR.steps.every((s) => s.source !== 'semantic');
|
|
1526
1635
|
if (!isSyntacticR)
|
|
1527
1636
|
continue;
|
|
1528
1637
|
// Both cases succeed — build proof by cases
|
|
@@ -1530,7 +1639,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1530
1639
|
let stepNum = 0;
|
|
1531
1640
|
// Copy premise steps
|
|
1532
1641
|
for (const s of state.steps) {
|
|
1533
|
-
if (s.
|
|
1642
|
+
if (s.source === 'premise') {
|
|
1534
1643
|
stepNum++;
|
|
1535
1644
|
mainSteps.push({ ...s, stepNumber: stepNum, premises: [] });
|
|
1536
1645
|
}
|
|
@@ -1544,15 +1653,16 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1544
1653
|
formula: left,
|
|
1545
1654
|
justification: 'Supuesto (caso izquierdo)',
|
|
1546
1655
|
premises: [],
|
|
1656
|
+
source: 'assumption',
|
|
1547
1657
|
});
|
|
1548
1658
|
const leftStepMap = new Map();
|
|
1549
1659
|
for (const s of subProofL.steps) {
|
|
1550
|
-
if (s.
|
|
1660
|
+
if (s.source === 'premise' && formulasEqual(s.formula, left)) {
|
|
1551
1661
|
leftStepMap.set(s.stepNumber, leftAssumptionStep);
|
|
1552
1662
|
continue;
|
|
1553
1663
|
}
|
|
1554
|
-
if (s.
|
|
1555
|
-
const existing = mainSteps.find((ms) => ms.
|
|
1664
|
+
if (s.source === 'premise') {
|
|
1665
|
+
const existing = mainSteps.find((ms) => ms.source === 'premise' && formulasEqual(ms.formula, s.formula));
|
|
1556
1666
|
if (existing) {
|
|
1557
1667
|
leftStepMap.set(s.stepNumber, existing.stepNumber);
|
|
1558
1668
|
continue;
|
|
@@ -1565,6 +1675,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1565
1675
|
formula: s.formula,
|
|
1566
1676
|
justification: s.justification,
|
|
1567
1677
|
premises: s.premises.map((p) => leftStepMap.get(p) || p),
|
|
1678
|
+
source: s.source,
|
|
1568
1679
|
});
|
|
1569
1680
|
}
|
|
1570
1681
|
const leftGoalStep = leftStepMap.get(subProofL.steps[subProofL.steps.length - 1]?.stepNumber ?? 0) ?? stepNum;
|
|
@@ -1576,15 +1687,16 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1576
1687
|
formula: right,
|
|
1577
1688
|
justification: 'Supuesto (caso derecho)',
|
|
1578
1689
|
premises: [],
|
|
1690
|
+
source: 'assumption',
|
|
1579
1691
|
});
|
|
1580
1692
|
const rightStepMap = new Map();
|
|
1581
1693
|
for (const s of subProofR.steps) {
|
|
1582
|
-
if (s.
|
|
1694
|
+
if (s.source === 'premise' && formulasEqual(s.formula, right)) {
|
|
1583
1695
|
rightStepMap.set(s.stepNumber, rightAssumptionStep);
|
|
1584
1696
|
continue;
|
|
1585
1697
|
}
|
|
1586
|
-
if (s.
|
|
1587
|
-
const existing = mainSteps.find((ms) => ms.
|
|
1698
|
+
if (s.source === 'premise') {
|
|
1699
|
+
const existing = mainSteps.find((ms) => ms.source === 'premise' && formulasEqual(ms.formula, s.formula));
|
|
1588
1700
|
if (existing) {
|
|
1589
1701
|
rightStepMap.set(s.stepNumber, existing.stepNumber);
|
|
1590
1702
|
continue;
|
|
@@ -1597,6 +1709,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1597
1709
|
formula: s.formula,
|
|
1598
1710
|
justification: s.justification,
|
|
1599
1711
|
premises: s.premises.map((p) => rightStepMap.get(p) || p),
|
|
1712
|
+
source: s.source,
|
|
1600
1713
|
});
|
|
1601
1714
|
}
|
|
1602
1715
|
const rightGoalStep = rightStepMap.get(subProofR.steps[subProofR.steps.length - 1]?.stepNumber ?? 0) ?? stepNum;
|
|
@@ -1608,6 +1721,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1608
1721
|
justification: 'Eliminacion de disyuncion (prueba por casos)',
|
|
1609
1722
|
premises: [disjStepNum, leftGoalStep, rightGoalStep],
|
|
1610
1723
|
subproofs: [subProofL, subProofR],
|
|
1724
|
+
source: 'rule',
|
|
1611
1725
|
});
|
|
1612
1726
|
return buildProof(goal, mainSteps, premiseNames, theory, 'natural_deduction', [
|
|
1613
1727
|
subProofL,
|
|
@@ -1680,6 +1794,7 @@ function tryDerive(goal, theory, premiseNames, depth = 0) {
|
|
|
1680
1794
|
formula: goal,
|
|
1681
1795
|
justification: 'Verificacion semantica (todas las valuaciones satisfacen la consecuencia)',
|
|
1682
1796
|
premises: premiseStepNums,
|
|
1797
|
+
source: 'semantic',
|
|
1683
1798
|
});
|
|
1684
1799
|
state.known.set(goalHash, goal);
|
|
1685
1800
|
}
|
|
@@ -1904,26 +2019,56 @@ class ClassicalPropositional {
|
|
|
1904
2019
|
};
|
|
1905
2020
|
}
|
|
1906
2021
|
}
|
|
1907
|
-
prove(goal, theory) {
|
|
2022
|
+
prove(goal, theory, premises) {
|
|
1908
2023
|
const wf = this.checkWellFormed(goal);
|
|
1909
2024
|
if (wf.length > 0) {
|
|
1910
2025
|
return { status: 'error', diagnostics: wf, formula: goal };
|
|
1911
2026
|
}
|
|
1912
|
-
const
|
|
1913
|
-
const
|
|
2027
|
+
const usingRestricted = premises !== undefined && premises.length > 0;
|
|
2028
|
+
const premiseNames = usingRestricted
|
|
2029
|
+
? premises.filter((n) => theory.axioms.has(n) || theory.theorems.has(n))
|
|
2030
|
+
: Array.from(theory.axioms.keys());
|
|
2031
|
+
const diagnostics = [];
|
|
2032
|
+
if (usingRestricted) {
|
|
2033
|
+
for (const n of premises) {
|
|
2034
|
+
if (!theory.axioms.has(n) && !theory.theorems.has(n)) {
|
|
2035
|
+
diagnostics.push({
|
|
2036
|
+
severity: 'warning',
|
|
2037
|
+
message: `Premisa '${n}' no encontrada en la teoría; será ignorada en prove`,
|
|
2038
|
+
});
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
const effectiveTheory = usingRestricted
|
|
2043
|
+
? {
|
|
2044
|
+
profile: theory.profile,
|
|
2045
|
+
axioms: new Map(premiseNames
|
|
2046
|
+
.filter((n) => theory.axioms.has(n))
|
|
2047
|
+
.map((n) => [n, theory.axioms.get(n)])),
|
|
2048
|
+
theorems: new Map(premiseNames
|
|
2049
|
+
.filter((n) => theory.theorems.has(n))
|
|
2050
|
+
.map((n) => [n, theory.theorems.get(n)])),
|
|
2051
|
+
claims: theory.claims,
|
|
2052
|
+
judgments: theory.judgments,
|
|
2053
|
+
}
|
|
2054
|
+
: theory;
|
|
2055
|
+
const proof = tryDerive(goal, effectiveTheory, premiseNames);
|
|
1914
2056
|
if (proof && proof.status === 'complete') {
|
|
2057
|
+
const isSemantic = proof.method === 'semantic';
|
|
1915
2058
|
return {
|
|
1916
2059
|
status: 'provable',
|
|
1917
|
-
output:
|
|
2060
|
+
output: isSemantic
|
|
2061
|
+
? `${formulaToString(goal)} es DEMOSTRABLE desde la teoria (verificación semántica, sin derivación sintáctica)`
|
|
2062
|
+
: `${formulaToString(goal)} es DEMOSTRABLE desde la teoria`,
|
|
1918
2063
|
proof,
|
|
1919
2064
|
educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'prove', ok: true }),
|
|
1920
|
-
diagnostics
|
|
2065
|
+
diagnostics,
|
|
1921
2066
|
formula: goal,
|
|
1922
2067
|
};
|
|
1923
2068
|
}
|
|
1924
2069
|
// Semantic fallback: verify via SAT/truth-table whether goal follows from axioms
|
|
1925
2070
|
const allAxiomFormulas = premiseNames
|
|
1926
|
-
.map((n) =>
|
|
2071
|
+
.map((n) => effectiveTheory.axioms.get(n) || effectiveTheory.theorems.get(n))
|
|
1927
2072
|
.filter((f) => f !== undefined);
|
|
1928
2073
|
let semanticResult;
|
|
1929
2074
|
const atoms = new Set();
|
|
@@ -1980,42 +2125,46 @@ class ClassicalPropositional {
|
|
|
1980
2125
|
}
|
|
1981
2126
|
}
|
|
1982
2127
|
if (semanticResult) {
|
|
2128
|
+
const premiseSteps = [];
|
|
2129
|
+
premiseNames.forEach((n, i) => {
|
|
2130
|
+
const f = effectiveTheory.axioms.get(n) || effectiveTheory.theorems.get(n);
|
|
2131
|
+
if (f) {
|
|
2132
|
+
premiseSteps.push({
|
|
2133
|
+
stepNumber: i + 1,
|
|
2134
|
+
formula: f,
|
|
2135
|
+
justification: `Premisa (${n})`,
|
|
2136
|
+
premises: [],
|
|
2137
|
+
source: 'premise',
|
|
2138
|
+
});
|
|
2139
|
+
}
|
|
2140
|
+
});
|
|
1983
2141
|
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),
|
|
2142
|
+
...premiseSteps,
|
|
1997
2143
|
{
|
|
1998
2144
|
stepNumber: premiseNames.length + 1,
|
|
1999
2145
|
formula: goal,
|
|
2000
2146
|
justification: 'Verificacion semantica (tautologia o consecuencia logica)',
|
|
2001
2147
|
premises: premiseNames.map((_, i) => i + 1),
|
|
2148
|
+
source: 'semantic',
|
|
2002
2149
|
},
|
|
2003
2150
|
];
|
|
2004
|
-
const semanticProof = buildProof(goal, semanticProofSteps, premiseNames,
|
|
2151
|
+
const semanticProof = buildProof(goal, semanticProofSteps, premiseNames, effectiveTheory, 'semantic');
|
|
2005
2152
|
return {
|
|
2006
2153
|
status: 'provable',
|
|
2007
|
-
output: `${formulaToString(goal)} es DEMOSTRABLE desde la teoria`,
|
|
2154
|
+
output: `${formulaToString(goal)} es DEMOSTRABLE desde la teoria (verificación semántica, sin derivación sintáctica)`,
|
|
2008
2155
|
proof: semanticProof,
|
|
2009
2156
|
educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'prove', ok: true }),
|
|
2010
|
-
diagnostics
|
|
2157
|
+
diagnostics,
|
|
2011
2158
|
formula: goal,
|
|
2012
2159
|
};
|
|
2013
2160
|
}
|
|
2161
|
+
// Ni derivación sintáctica ni consecuencia semántica: existe contramodelo.
|
|
2162
|
+
// Esto sí es refutable en el sentido fuerte.
|
|
2014
2163
|
return {
|
|
2015
2164
|
status: 'refutable',
|
|
2016
|
-
output: `${formulaToString(goal)} NO
|
|
2165
|
+
output: `${formulaToString(goal)} NO se sigue de la teoría (existe contramodelo en ${formulaToString(goal)})`,
|
|
2017
2166
|
educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'prove', ok: false }),
|
|
2018
|
-
diagnostics
|
|
2167
|
+
diagnostics,
|
|
2019
2168
|
formula: goal,
|
|
2020
2169
|
};
|
|
2021
2170
|
}
|
|
@@ -2029,14 +2178,17 @@ class ClassicalPropositional {
|
|
|
2029
2178
|
// Build reasoning info
|
|
2030
2179
|
const rulesUsed = new Set();
|
|
2031
2180
|
for (const step of proof.steps) {
|
|
2032
|
-
if (
|
|
2181
|
+
if (step.source !== 'premise') {
|
|
2033
2182
|
rulesUsed.add(step.justification);
|
|
2034
2183
|
}
|
|
2035
2184
|
}
|
|
2036
2185
|
const reasoningType = rulesUsed.size > 0 ? Array.from(rulesUsed).join(', ') : 'Derivación directa';
|
|
2186
|
+
const isSemantic = proof.method === 'semantic';
|
|
2037
2187
|
return {
|
|
2038
2188
|
status: 'provable',
|
|
2039
|
-
output:
|
|
2189
|
+
output: isSemantic
|
|
2190
|
+
? `${formulaToString(goal)} derivado (verificación semántica, sin derivación sintáctica)`
|
|
2191
|
+
: `${formulaToString(goal)} derivado exitosamente`,
|
|
2040
2192
|
proof,
|
|
2041
2193
|
reasoningType,
|
|
2042
2194
|
reasoningSchema: rulesUsed.has('Modus Ponens')
|
|
@@ -2057,8 +2209,8 @@ class ClassicalPropositional {
|
|
|
2057
2209
|
};
|
|
2058
2210
|
}
|
|
2059
2211
|
return {
|
|
2060
|
-
status: '
|
|
2061
|
-
output: `No se
|
|
2212
|
+
status: 'unknown',
|
|
2213
|
+
output: `No se pudo derivar ${formulaToString(goal)} desde las premisas dadas (sin refutación)`,
|
|
2062
2214
|
educationalNote: (0, educational_notes_1.pickEducationalNote)({ op: 'derive', ok: false }),
|
|
2063
2215
|
diagnostics: [],
|
|
2064
2216
|
formula: goal,
|