chop-logic-core
Version:
Core classes, methods and functions for calculating logical formulas and constructing proofs within the Chop Logic project.
1,522 lines (1,468 loc) • 67.2 kB
JavaScript
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
Glyph: () => Glyph,
GlyphType: () => GlyphType,
GlyphUnicode: () => GlyphUnicode,
HilbertAxioms: () => HilbertAxioms,
HilbertCalculusRule: () => HilbertCalculusRule,
HilbertCalculusSchema: () => HilbertCalculusSchema,
HilbertProof: () => HilbertProof,
HilbertProofBuilder: () => HilbertProofBuilder,
HilbertRules: () => HilbertRules,
NaturalCalculusRule: () => NaturalCalculusRule,
NaturalProof: () => NaturalProof,
NaturalProofBuilder: () => NaturalProofBuilder,
NaturalRules: () => NaturalRules,
Operator: () => Operator,
PropFormulaCheck: () => PropFormulaCheck,
Step: () => Step,
arePropFormulasStructurallyEqual: () => arePropFormulasStructurallyEqual,
buildHilbertProof: () => buildHilbertProof,
buildNaturalProof: () => buildNaturalProof,
calculatePropFormula: () => calculatePropFormula,
composeHilbertProof: () => composeHilbertProof,
composeNaturalProof: () => composeNaturalProof,
convertPropFormulaToExpression: () => convertPropFormulaToExpression,
convertPropFormulaToString: () => convertPropFormulaToString,
createOperator: () => createOperator,
createPropExpression: () => createPropExpression,
createPropFormula: () => createPropFormula,
createPropSymbol: () => createPropSymbol,
extractPropSubFormulas: () => extractPropSubFormulas,
extractPropVariables: () => extractPropVariables,
generateHilbertProofSteps: () => generateHilbertProofSteps,
generateNaturalProofSteps: () => generateNaturalProofSteps,
generatePropTruthTable: () => generatePropTruthTable,
generateTruthAssignments: () => generateTruthAssignments,
getBinaryOperationValue: () => getBinaryOperationValue,
getGlyphUnicode: () => getGlyphUnicode,
getOperatorGlyph: () => getOperatorGlyph,
getUnaryOperationValue: () => getUnaryOperationValue,
isConjunctionEliminationApplicable: () => isConjunctionEliminationApplicable,
isConjunctionIntroductionApplicable: () => isConjunctionIntroductionApplicable,
isDisjunctionEliminationApplicable: () => isDisjunctionEliminationApplicable,
isDisjunctionIntroductionApplicable: () => isDisjunctionIntroductionApplicable,
isEquivalenceEliminationApplicable: () => isEquivalenceEliminationApplicable,
isEquivalenceIntroductionApplicable: () => isEquivalenceIntroductionApplicable,
isImplicationDistributionApplicable: () => isImplicationDistributionApplicable,
isImplicationEliminationApplicable: () => isImplicationEliminationApplicable,
isImplicationIntroductionApplicable: () => isImplicationIntroductionApplicable,
isImplicationReversalApplicable: () => isImplicationReversalApplicable,
isNegationEliminationApplicable: () => isNegationEliminationApplicable,
isNegationIntroductionApplicable: () => isNegationIntroductionApplicable,
isWellFormedFormula: () => isWellFormedFormula,
replaceAtomInFormula: () => replaceAtomInFormula,
tokenizeString: () => tokenizeString,
validatePropFormulas: () => validatePropFormulas
});
module.exports = __toCommonJS(index_exports);
// src/enums/proof.ts
var Step = /* @__PURE__ */ ((Step2) => {
Step2["Premise"] = "Premise";
Step2["Assumption"] = "Assumption";
Step2["Shortcut"] = "Shortcut";
Step2["Reiteration"] = "Reiteration";
Step2["Derivation"] = "Derivation";
Step2["Axiom"] = "Axiom";
return Step2;
})(Step || {});
var HilbertCalculusSchema = /* @__PURE__ */ ((HilbertCalculusSchema2) => {
HilbertCalculusSchema2["II"] = "II";
HilbertCalculusSchema2["ID"] = "ID";
HilbertCalculusSchema2["IR"] = "IR";
return HilbertCalculusSchema2;
})(HilbertCalculusSchema || {});
var HilbertCalculusRule = /* @__PURE__ */ ((HilbertCalculusRule2) => {
HilbertCalculusRule2["II"] = "II";
HilbertCalculusRule2["ID"] = "ID";
HilbertCalculusRule2["IR"] = "IR";
HilbertCalculusRule2["IE"] = "IE";
return HilbertCalculusRule2;
})(HilbertCalculusRule || {});
var NaturalCalculusRule = /* @__PURE__ */ ((NaturalCalculusRule2) => {
NaturalCalculusRule2["NI"] = "NI";
NaturalCalculusRule2["CI"] = "CI";
NaturalCalculusRule2["DI"] = "DI";
NaturalCalculusRule2["II"] = "II";
NaturalCalculusRule2["EI"] = "EI";
NaturalCalculusRule2["NE"] = "NE";
NaturalCalculusRule2["CE"] = "CE";
NaturalCalculusRule2["DE"] = "DE";
NaturalCalculusRule2["IE"] = "IE";
NaturalCalculusRule2["EE"] = "EE";
return NaturalCalculusRule2;
})(NaturalCalculusRule || {});
var PropFormulaCheck = /* @__PURE__ */ ((PropFormulaCheck2) => {
PropFormulaCheck2["areEqual"] = "areEqual";
PropFormulaCheck2["isIE"] = "isIE";
PropFormulaCheck2["isDE"] = "isDE";
PropFormulaCheck2["isCE"] = "isCE";
PropFormulaCheck2["isEE"] = "isEE";
PropFormulaCheck2["isNE"] = "isNE";
PropFormulaCheck2["isDI"] = "isDI";
PropFormulaCheck2["isCI"] = "isCI";
PropFormulaCheck2["isEI"] = "isEI";
PropFormulaCheck2["isNI"] = "isNI";
PropFormulaCheck2["isII"] = "isII";
PropFormulaCheck2["isID"] = "isID";
PropFormulaCheck2["isIR"] = "isIR";
return PropFormulaCheck2;
})(PropFormulaCheck || {});
// src/enums/symbols.ts
var Glyph = /* @__PURE__ */ ((Glyph2) => {
Glyph2["Implication"] = "=>";
Glyph2["ReversedImplication"] = "<=";
Glyph2["Conjunction"] = "&";
Glyph2["Disjunction"] = "|";
Glyph2["Negation"] = "~";
Glyph2["Equivalence"] = "<=>";
Glyph2["ExclusiveConjunction"] = "^";
Glyph2["ShefferStroke"] = "!&";
Glyph2["WebbOperation"] = "!|";
Glyph2["AntiImplication"] = "!=>";
Glyph2["ReversedAntiImplication"] = "!<=";
Glyph2["Contradiction"] = "#";
Glyph2["Tautology"] = "@";
Glyph2["OpenParenthesis"] = "(";
Glyph2["CloseParenthesis"] = ")";
return Glyph2;
})(Glyph || {});
var GlyphType = /* @__PURE__ */ ((GlyphType2) => {
GlyphType2["Variable"] = "variable";
GlyphType2["Operator"] = "operator";
GlyphType2["Parenthesis"] = "parenthesis";
return GlyphType2;
})(GlyphType || {});
var GlyphUnicode = /* @__PURE__ */ ((GlyphUnicode2) => {
GlyphUnicode2["Implication"] = "\u2192";
GlyphUnicode2["ReversedImplication"] = "\u2190";
GlyphUnicode2["Conjunction"] = "\u2227";
GlyphUnicode2["Disjunction"] = "\u2228";
GlyphUnicode2["Negation"] = "\xAC";
GlyphUnicode2["Equivalence"] = "\u2261";
GlyphUnicode2["ExclusiveConjunction"] = "\u2295";
GlyphUnicode2["ShefferStroke"] = "\u2191";
GlyphUnicode2["WebbOperation"] = "\u2193";
GlyphUnicode2["AntiImplication"] = "\u219B";
GlyphUnicode2["ReversedAntiImplication"] = "\u219A";
GlyphUnicode2["Contradiction"] = "\u22A5";
GlyphUnicode2["Tautology"] = "\u22A4";
GlyphUnicode2["OpenParenthesis"] = "(";
GlyphUnicode2["CloseParenthesis"] = ")";
return GlyphUnicode2;
})(GlyphUnicode || {});
var Operator = /* @__PURE__ */ ((Operator2) => {
Operator2["Var"] = "VAR";
Operator2["Not"] = "NOT";
Operator2["And"] = "AND";
Operator2["Or"] = "OR";
Operator2["Implies"] = "IMPLIES";
Operator2["ReversedImplies"] = "REVERSED_IMPLIES";
Operator2["Equiv"] = "EQUIV";
Operator2["Xor"] = "XOR";
Operator2["Nand"] = "NAND";
Operator2["Nor"] = "NOR";
Operator2["AntiImplies"] = "ANTI_IMPLIES";
Operator2["ReversedAntiImplies"] = "REVERSED_ANTI_IMPLIES";
Operator2["Contradiction"] = "CONTRADICTION";
Operator2["Tautology"] = "TAUTOLOGY";
return Operator2;
})(Operator || {});
// src/propositional/builders/create-operator.ts
function createOperator(symbol) {
switch (symbol.atom[0]) {
case "~" /* Negation */:
return "NOT" /* Not */;
case "&" /* Conjunction */:
return "AND" /* And */;
case "|" /* Disjunction */:
return "OR" /* Or */;
case "=>" /* Implication */:
return "IMPLIES" /* Implies */;
case "<=" /* ReversedImplication */:
return "REVERSED_IMPLIES" /* ReversedImplies */;
case "<=>" /* Equivalence */:
return "EQUIV" /* Equiv */;
case "^" /* ExclusiveConjunction */:
return "XOR" /* Xor */;
case "!&" /* ShefferStroke */:
return "NAND" /* Nand */;
case "!|" /* WebbOperation */:
return "NOR" /* Nor */;
case "!=>" /* AntiImplication */:
return "ANTI_IMPLIES" /* AntiImplies */;
case "!<=" /* ReversedAntiImplication */:
return "REVERSED_ANTI_IMPLIES" /* ReversedAntiImplies */;
case "#" /* Contradiction */:
return "CONTRADICTION" /* Contradiction */;
case "@" /* Tautology */:
return "TAUTOLOGY" /* Tautology */;
default:
if (symbol.type === "variable" /* Variable */) {
return "VAR" /* Var */;
}
throw new Error(
`Cannot create an operator from symbol "${symbol.atom[0]}".`
);
}
}
// src/tokenizer/get-glyph-unicode.ts
var GlyphsDictionary = {
["=>" /* Implication */]: "\u2192" /* Implication */,
["<=" /* ReversedImplication */]: "\u2190" /* ReversedImplication */,
["&" /* Conjunction */]: "\u2227" /* Conjunction */,
["|" /* Disjunction */]: "\u2228" /* Disjunction */,
["~" /* Negation */]: "\xAC" /* Negation */,
["<=>" /* Equivalence */]: "\u2261" /* Equivalence */,
["^" /* ExclusiveConjunction */]: "\u2295" /* ExclusiveConjunction */,
["!&" /* ShefferStroke */]: "\u2191" /* ShefferStroke */,
["!|" /* WebbOperation */]: "\u2193" /* WebbOperation */,
["!=>" /* AntiImplication */]: "\u219B" /* AntiImplication */,
["!<=" /* ReversedAntiImplication */]: "\u219A" /* ReversedAntiImplication */,
["#" /* Contradiction */]: "\u22A5" /* Contradiction */,
["@" /* Tautology */]: "\u22A4" /* Tautology */,
["(" /* OpenParenthesis */]: "(" /* OpenParenthesis */,
[")" /* CloseParenthesis */]: ")" /* CloseParenthesis */
};
function getGlyphUnicode(char) {
if (char in GlyphsDictionary) {
return GlyphsDictionary[char];
} else {
throw new Error(`Cannot get a GlyphUnicode for the character "${char}".`);
}
}
// src/tokenizer/get-operator-glyph.ts
function getOperatorGlyph(operator) {
switch (operator) {
case "NOT" /* Not */:
return "~" /* Negation */;
case "AND" /* And */:
return "&" /* Conjunction */;
case "OR" /* Or */:
return "|" /* Disjunction */;
case "IMPLIES" /* Implies */:
return "=>" /* Implication */;
case "REVERSED_IMPLIES" /* ReversedImplies */:
return "<=" /* ReversedImplication */;
case "EQUIV" /* Equiv */:
return "<=>" /* Equivalence */;
case "XOR" /* Xor */:
return "^" /* ExclusiveConjunction */;
case "NAND" /* Nand */:
return "!&" /* ShefferStroke */;
case "NOR" /* Nor */:
return "!|" /* WebbOperation */;
case "ANTI_IMPLIES" /* AntiImplies */:
return "!=>" /* AntiImplication */;
case "REVERSED_ANTI_IMPLIES" /* ReversedAntiImplies */:
return "!<=" /* ReversedAntiImplication */;
case "CONTRADICTION" /* Contradiction */:
return "#" /* Contradiction */;
case "TAUTOLOGY" /* Tautology */:
return "@" /* Tautology */;
default:
throw new Error(`Cannot convert operator "${operator}" to a glyph.`);
}
}
// src/tokenizer/tokenize-string.ts
function tokenizeString(input) {
if (!input.length) return [];
const glyphs = Object.values(Glyph).sort((a, b) => b.length - a.length);
const glyphPattern = glyphs.map((g) => g.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`)).join("|");
const variablePattern = "[a-zA-Z]+";
const tokenizer = new RegExp(`(${glyphPattern})|(${variablePattern})`, "g");
const tokens = [];
let match = tokenizer.exec(input);
while (match !== null) {
tokens.push(match[0]);
match = tokenizer.exec(input);
}
if (!tokens.length || tokens.join("") !== input.replaceAll(/\s+/g, "")) {
throw new Error(`Invalid character(s) found in input: "${input}".`);
}
return tokens;
}
// src/propositional/builders/create-prop-symbol.ts
function createPropSymbol(char, position) {
const knownGlyphs = Object.values(Glyph);
const onlyLatinLetters = /^[a-zA-Z]+$/;
if (char === "(" /* OpenParenthesis */ || char === ")" /* CloseParenthesis */) {
return {
position,
atom: [char],
type: "parenthesis" /* Parenthesis */,
view: getGlyphUnicode(char)
};
} else if (knownGlyphs.includes(char)) {
return {
position,
atom: [char],
type: "operator" /* Operator */,
view: getGlyphUnicode(char)
};
} else if (onlyLatinLetters.test(char)) {
const firstLetter = char[0].toLowerCase();
return {
position,
atom: [char],
type: "variable" /* Variable */,
view: firstLetter
};
} else {
throw new Error(
`Cannot create a propositional symbol from the character "${char}".`
);
}
}
// src/propositional/builders/create-prop-expression.ts
function createPropExpression(input) {
const tokens = tokenizeString(input);
return tokens.map((token, index) => createPropSymbol(token, index));
}
// src/propositional/validators/is-well-formed-formula.ts
function isWellFormedFormula(expression) {
if (expression.length === 0) return false;
let index = 0;
function parseWFF() {
if (isEndOfExpression()) return false;
if (isVariable(expression[index])) {
return parseVariable2();
}
if (isNegation(expression[index])) {
return parseNegation2();
}
if (isParenthesizedExpression(expression[index])) {
return parseParenthesizedExpression();
}
return false;
}
function parseVariable2() {
index++;
return true;
}
function parseNegation2() {
index++;
return parseWFF();
}
function parseParenthesizedExpression() {
index++;
if (!parseWFF()) return false;
if (isEndOfExpression() || !isBinaryOperator(expression[index]))
return false;
index++;
if (!parseWFF()) return false;
if (isEndOfExpression() || !isClosingParenthesis(expression[index]))
return false;
index++;
return true;
}
function isEndOfExpression() {
return index >= expression.length;
}
const result = parseWFF();
return result && index === expression.length;
}
function isVariable(symbol) {
return symbol.type === "variable" /* Variable */;
}
function isNegation(symbol) {
return symbol.atom[0] === "~" /* Negation */;
}
function isParenthesizedExpression(symbol) {
return symbol.atom[0] === "(" /* OpenParenthesis */;
}
function isBinaryOperator(symbol) {
return symbol.type === "operator" /* Operator */ && symbol.atom[0] !== "~" /* Negation */;
}
function isClosingParenthesis(symbol) {
return symbol.atom[0] === ")" /* CloseParenthesis */;
}
// src/propositional/builders/create-prop-formula.ts
function createPropFormula(expression) {
if (!isWellFormedFormula(expression)) {
throw new Error(
"Invalid propositional expression: Not a well-formed formula (WFF)."
);
}
return parseExpression({ expression, start: 0, end: expression.length - 1 });
}
function parseExpression({
expression,
start,
end
}) {
if (start > end) {
throw new Error(
`Unexpected expression boundaries: start=${start}, end=${end}`
);
}
if (isSingleVariable(expression, start, end)) {
return parseVariable(expression[start]);
}
if (isNegation2(expression, start)) {
return parseNegation(expression, start, end);
}
if (isParenthesized(expression, start, end)) {
return parseBinaryExpression(expression, start, end);
}
throw new Error("Invalid formula structure.");
}
function isSingleVariable(expression, start, end) {
return start === end && expression[start].type === "variable" /* Variable */;
}
function parseVariable(symbol) {
return { operator: "VAR" /* Var */, values: symbol.atom };
}
function isNegation2(expression, start) {
return expression[start].atom[0] === "~" /* Negation */;
}
function parseNegation(expression, start, end) {
return {
operator: "NOT" /* Not */,
values: [parseExpression({ expression, start: start + 1, end })]
};
}
function isParenthesized(expression, start, end) {
return expression[start].atom[0] === "(" /* OpenParenthesis */ && expression[end].atom[0] === ")" /* CloseParenthesis */;
}
function parseBinaryExpression(expression, start, end) {
const mainOperatorIndex = findMainOperator(expression, start, end);
if (mainOperatorIndex === -1) {
throw new Error("Could not determine the main operator.");
}
return {
operator: createOperator(expression[mainOperatorIndex]),
values: [
parseExpression({
expression,
start: start + 1,
end: mainOperatorIndex - 1
}),
parseExpression({
expression,
start: mainOperatorIndex + 1,
end: end - 1
})
]
};
}
function findMainOperator(expression, start, end) {
let balance = 0;
for (let i = start; i <= end; i++) {
const symbol = expression[i];
if (symbol.atom[0] === "(" /* OpenParenthesis */) balance++;
if (symbol.atom[0] === ")" /* CloseParenthesis */) balance--;
if (balance === 1 && symbol.type === "operator" /* Operator */ && symbol.atom[0] !== "~" /* Negation */) {
return i;
}
}
return -1;
}
// src/propositional/converters/convert-prop-formula-to-expression.ts
function convertPropFormulaToExpression(formula) {
const expression = [];
let position = 0;
function traverse(node) {
const { operator, values } = node;
if (operator === "VAR" /* Var */) {
expression.push(createPropSymbol(values[0], position++));
return;
}
expression.push(createPropSymbol("(", position++));
if (operator === "NOT" /* Not */) {
expression.push(createPropSymbol(getOperatorGlyph(operator), position++));
traverse(values[0]);
} else {
const [left, right] = values;
traverse(left);
expression.push(createPropSymbol(getOperatorGlyph(operator), position++));
traverse(right);
}
expression.push(createPropSymbol(")", position++));
}
traverse(formula);
return expression;
}
// src/propositional/converters/convert-prop-formula-to-string.ts
function convertPropFormulaToString(formula) {
if (formula.operator === "VAR" /* Var */) {
return formula.values[0];
}
const glyph = getGlyphUnicode(getOperatorGlyph(formula.operator));
const subFormulas = formula.values;
const values = subFormulas.map(convertPropFormulaToString);
if (formula.operator === "NOT" /* Not */) {
return `${glyph}${values[0]}`;
}
const glyphSpace = ` ${glyph} `;
return `(${values.join(glyphSpace)})`;
}
// src/propositional/converters/extract-prop-sub-formulas.ts
function extractPropSubFormulas(formula) {
if (formula.operator === "VAR" /* Var */) return [];
const subFormulas = /* @__PURE__ */ new Set();
const result = [];
function traverse(subFormula) {
if (subFormula.operator === "VAR" /* Var */) {
return;
}
const key = JSON.stringify(subFormula);
if (!subFormulas.has(key)) {
subFormulas.add(key);
result.push(subFormula);
}
if (Array.isArray(subFormula.values)) {
for (const value of subFormula.values) {
traverse(value);
}
}
}
if (Array.isArray(formula.values)) {
for (const value of formula.values) {
traverse(value);
}
}
return result;
}
// src/propositional/converters/extract-prop-variables.ts
function extractPropVariables(formula) {
const variablesSet = /* @__PURE__ */ new Set();
function traverse(node) {
if (node.operator === "VAR" /* Var */) {
variablesSet.add(node.values[0]);
return;
}
if (Array.isArray(node.values)) {
const subFormulas = node.values;
for (const subFormula of subFormulas) {
traverse(subFormula);
}
}
}
traverse(formula);
const sortedVariables = Array.from(variablesSet).sort(
(a, b) => a.localeCompare(b)
);
return new Map(sortedVariables.map((varName, index) => [index, [varName]]));
}
// src/propositional/converters/replace-atom-in-formula.ts
function replaceAtomInFormula({
formula,
atom,
substitute
}) {
function traverse(node) {
if (node.operator === "VAR" /* Var */) {
const nodeAtom = node.values;
if (nodeAtom[0] === atom[0]) {
if (Array.isArray(substitute) && substitute.length === 1 && typeof substitute[0] === "string") {
return {
operator: "VAR" /* Var */,
values: substitute
};
} else {
return substitute;
}
}
return node;
}
if (Array.isArray(node.values)) {
const subFormulas = node.values;
const newValues = subFormulas.map((subFormula) => traverse(subFormula));
return {
operator: node.operator,
values: newValues
};
}
return node;
}
return traverse(formula);
}
// src/propositional/evaluators/get-binary-operation-value.ts
function getBinaryOperationValue({
operator,
leftOperand,
rightOperand
}) {
switch (operator) {
case "AND" /* And */:
return leftOperand && rightOperand;
case "OR" /* Or */:
return leftOperand || rightOperand;
case "IMPLIES" /* Implies */:
return !leftOperand || rightOperand;
case "REVERSED_IMPLIES" /* ReversedImplies */:
return !rightOperand || leftOperand;
case "EQUIV" /* Equiv */:
return leftOperand === rightOperand;
case "XOR" /* Xor */:
return leftOperand !== rightOperand;
case "NAND" /* Nand */:
return !(leftOperand && rightOperand);
case "NOR" /* Nor */:
return !(leftOperand || rightOperand);
case "ANTI_IMPLIES" /* AntiImplies */:
return leftOperand && !rightOperand;
case "REVERSED_ANTI_IMPLIES" /* ReversedAntiImplies */:
return rightOperand && !leftOperand;
case "CONTRADICTION" /* Contradiction */:
return false;
case "TAUTOLOGY" /* Tautology */:
return true;
case "VAR" /* Var */:
case "NOT" /* Not */:
throw new Error(`Operator "${operator}" is not a binary operator.`);
default:
throw new Error(`Unknown operator: "${operator}".`);
}
}
// src/propositional/evaluators/get-unary-operation-value.ts
function getUnaryOperationValue({
operator,
operand
}) {
switch (operator) {
case "VAR" /* Var */:
return operand;
// A variable simply retains its boolean value.
case "NOT" /* Not */:
return !operand;
// Logical negation.
default:
throw new Error(`Operator "${operator}" is not a valid unary operator.`);
}
}
// src/propositional/evaluators/calculate-prop-formula.ts
function calculatePropFormula({
formula,
assignment,
variablesMap
}) {
const variables = variablesMap ?? extractPropVariables(formula);
if (variables.size !== assignment.length) {
throw new Error(
`Mismatch between formula variables (${variables.size}) and assignment length (${assignment.length}).`
);
}
const variableValues = /* @__PURE__ */ new Map();
variables.forEach((atom, index) => {
variableValues.set(atom[0], assignment[index]);
});
function evaluate(node) {
if (node.operator === "VAR" /* Var */) {
return !!variableValues.get(node.values[0]);
}
if (node.operator === "NOT" /* Not */) {
const operand = node.values[0];
return getUnaryOperationValue({
operator: node.operator,
operand: evaluate(operand)
});
}
const [left, right] = node.values;
return getBinaryOperationValue({
operator: node.operator,
leftOperand: evaluate(left),
rightOperand: evaluate(right)
});
}
return evaluate(formula);
}
// src/propositional/hilbert-calculus/axioms/implication-distribution.ts
function implicationDistributionSchema(formulas) {
const [A, B, C] = formulas;
return {
operator: "IMPLIES" /* Implies */,
values: [
{
operator: "IMPLIES" /* Implies */,
values: [A, { operator: "IMPLIES" /* Implies */, values: [B, C] }]
},
{
operator: "IMPLIES" /* Implies */,
values: [
{ operator: "IMPLIES" /* Implies */, values: [A, B] },
{ operator: "IMPLIES" /* Implies */, values: [A, C] }
]
}
]
};
}
// src/propositional/hilbert-calculus/axioms/implication-introduction.ts
function implicationIntroductionSchema(formulas) {
const [A, B] = formulas;
return {
operator: "IMPLIES" /* Implies */,
values: [
A,
{
operator: "IMPLIES" /* Implies */,
values: [B, A]
}
]
};
}
// src/propositional/hilbert-calculus/axioms/implication-reversal.ts
function implicationReversalSchema(formulas) {
const [A, B] = formulas;
return {
operator: "IMPLIES" /* Implies */,
values: [
{
operator: "IMPLIES" /* Implies */,
values: [
{ operator: "NOT" /* Not */, values: [A] },
{ operator: "NOT" /* Not */, values: [B] }
]
},
{
operator: "IMPLIES" /* Implies */,
values: [B, A]
}
]
};
}
// src/propositional/hilbert-calculus/axioms/index.ts
var HilbertAxioms = Object.freeze({
II: implicationIntroductionSchema,
ID: implicationDistributionSchema,
IR: implicationReversalSchema
});
// src/propositional/validators/are-prop-formulas-structurally-equal.ts
function arePropFormulasStructurallyEqual(formulas) {
if (!formulas.length) return false;
const strings = formulas.map((formula) => JSON.stringify(formula));
return strings.every((item) => item === strings[0]);
}
// src/propositional/validators/is-conjunction-elimination-applicable.ts
function isConjunctionEliminationApplicable(formulas) {
if (formulas.length === 0) {
return false;
}
return formulas.every((formula) => formula.operator === "AND" /* And */);
}
// src/propositional/validators/is-conjunction-introduction-applicable.ts
function isConjunctionIntroductionApplicable(formulas) {
return formulas.length === 2;
}
// src/propositional/validators/is-disjunction-elimination-applicable.ts
function isDisjunctionEliminationApplicable(formulas) {
if (formulas.length !== 3) return false;
const [formula1, formula2, formula3] = formulas;
let disjunction = null;
let implication1 = null;
let implication2 = null;
for (const formula of [formula1, formula2, formula3]) {
const isValidDisjunction = formula.operator === "OR" /* Or */ && Array.isArray(formula.values) && formula.values.length === 2;
const isValidImplication = formula.operator === "IMPLIES" /* Implies */ && Array.isArray(formula.values) && formula.values.length === 2;
const isImplication1Missing = !implication1;
if (isValidDisjunction) {
disjunction = formula;
} else if (isValidImplication) {
if (isImplication1Missing) {
implication1 = formula;
} else {
implication2 = formula;
}
}
}
if (!disjunction || !implication1 || !implication2) {
return false;
}
const [disjunct1, disjunct2] = disjunction.values;
const [antecedent1, consequent1] = implication1.values;
const [antecedent2, consequent2] = implication2.values;
if (!arePropFormulasStructurallyEqual([consequent1, consequent2])) {
return false;
}
return arePropFormulasStructurallyEqual([disjunct1, antecedent1]) && arePropFormulasStructurallyEqual([disjunct2, antecedent2]) || arePropFormulasStructurallyEqual([disjunct1, antecedent2]) && arePropFormulasStructurallyEqual([disjunct2, antecedent1]);
}
// src/propositional/validators/is-disjunction-introduction-applicable.ts
function isDisjunctionIntroductionApplicable(formulas) {
return formulas.length === 2;
}
// src/propositional/validators/is-equivalence-elimination-applicable.ts
function isEquivalenceEliminationApplicable(formulas) {
if (formulas.length === 0) {
return false;
}
return formulas.every((formula) => formula.operator === "EQUIV" /* Equiv */);
}
// src/propositional/validators/is-equivalence-introduction-applicable.ts
function isEquivalenceIntroductionApplicable(formulas) {
if (formulas.length !== 2) {
return false;
}
const [formula1, formula2] = formulas;
if (formula1.operator !== "IMPLIES" /* Implies */ || formula2.operator !== "IMPLIES" /* Implies */) {
return false;
}
const [antecedent1, consequent1] = formula1.values;
const [antecedent2, consequent2] = formula2.values;
return arePropFormulasStructurallyEqual([antecedent1, consequent2]) && arePropFormulasStructurallyEqual([antecedent2, consequent1]);
}
// src/propositional/validators/is-implication-distribution-applicable.ts
function isImplicationDistributionSchema(formula) {
if (formula.operator !== "IMPLIES" /* Implies */) {
return false;
}
if (!Array.isArray(formula.values) || formula.values.length !== 2) {
return false;
}
const consequent = formula.values[1];
if (!Array.isArray(consequent.values) || consequent.operator !== "IMPLIES" /* Implies */ || consequent.values.length !== 2) {
return false;
}
return true;
}
function isImplicationDistributionApplicable(formulas) {
if (formulas.length === 0) {
return false;
}
return formulas.every(isImplicationDistributionSchema);
}
// src/propositional/validators/is-implication-elimination-applicable.ts
function isImplicationEliminationApplicable(formulas) {
if (formulas.length !== 2) return false;
const [formula1, formula2] = formulas;
const checkImplication = (implication, antecedent) => implication.operator === "IMPLIES" /* Implies */ && Array.isArray(implication.values) && implication.values.length === 2 && arePropFormulasStructurallyEqual([implication.values[0], antecedent]);
return checkImplication(formula1, formula2) || checkImplication(formula2, formula1);
}
// src/propositional/validators/is-implication-introduction-applicable.ts
function isImplicationIntroductionApplicable(formulas) {
return formulas.length === 2;
}
// src/propositional/validators/is-implication-reversal-applicable.ts
function isImplicationReversalSchema(formula) {
if (formula.operator !== "IMPLIES" /* Implies */) {
return false;
}
if (!Array.isArray(formula.values) || formula.values.length !== 2) {
return false;
}
const antecedent = formula.values[0];
const consequent = formula.values[1];
if (!Array.isArray(antecedent.values) || antecedent.operator !== "NOT" /* Not */ || antecedent.values.length !== 1) {
return false;
}
if (!Array.isArray(consequent.values) || consequent.operator !== "NOT" /* Not */ || consequent.values.length !== 1) {
return false;
}
return true;
}
function isImplicationReversalApplicable(formulas) {
if (formulas.length === 0) {
return false;
}
return formulas.every(isImplicationReversalSchema);
}
// src/propositional/validators/is-negation-elimination-applicable.ts
function isNegationEliminationApplicable(formulas) {
if (formulas.length === 0) {
return false;
}
return formulas.every(
(formula) => formula.operator === "NOT" /* Not */ && Array.isArray(formula.values) && formula.values.length === 1 && formula.values[0].operator === "NOT" /* Not */
);
}
// src/propositional/validators/is-negation-introduction-applicable.ts
function isNegationIntroductionApplicable(formulas) {
if (formulas.length !== 2) {
return false;
}
const [formula1, formula2] = formulas;
if (formula1.operator !== "IMPLIES" /* Implies */ || formula2.operator !== "IMPLIES" /* Implies */) {
return false;
}
const [antecedent1, consequent1] = formula1.values;
const [antecedent2, consequent2] = formula2.values;
if (!arePropFormulasStructurallyEqual([antecedent1, antecedent2])) {
return false;
}
return consequent1.operator === "NOT" /* Not */ && arePropFormulasStructurallyEqual([
consequent1.values[0],
consequent2
]) || consequent2.operator === "NOT" /* Not */ && arePropFormulasStructurallyEqual([
consequent2.values[0],
consequent1
]);
}
// src/propositional/validators/validate-prop-formulas.ts
var PROP_FORMULA_CHECKS = {
["areEqual" /* areEqual */]: arePropFormulasStructurallyEqual,
// Elimination rules
["isIE" /* isIE */]: isImplicationEliminationApplicable,
["isDE" /* isDE */]: isDisjunctionEliminationApplicable,
["isCE" /* isCE */]: isConjunctionEliminationApplicable,
["isEE" /* isEE */]: isEquivalenceEliminationApplicable,
["isNE" /* isNE */]: isNegationEliminationApplicable,
// Introduction rules
["isDI" /* isDI */]: isDisjunctionIntroductionApplicable,
["isCI" /* isCI */]: isConjunctionIntroductionApplicable,
["isEI" /* isEI */]: isEquivalenceIntroductionApplicable,
["isNI" /* isNI */]: isNegationIntroductionApplicable,
["isII" /* isII */]: isImplicationIntroductionApplicable,
// Other rules
["isID" /* isID */]: isImplicationDistributionApplicable,
["isIR" /* isIR */]: isImplicationReversalApplicable
};
function validatePropFormulas(formulas, checks = Object.keys(
PropFormulaCheck
)) {
return checks.reduce((results, checkName) => {
const checkFunction = PROP_FORMULA_CHECKS[checkName];
results[checkName] = checkFunction ? checkFunction(formulas) : false;
return results;
}, {});
}
// src/propositional/hilbert-calculus/rules/implication-distribution.ts
function implicationDistributionRule(formulas) {
if (!isImplicationDistributionApplicable(formulas)) {
throw new Error(
"Implication distribution requires each formula to have the form F => (G => H)."
);
}
return formulas.map((formula) => {
const F = formula.values[0];
const consequent = formula.values[1];
const G = consequent.values[0];
const H = consequent.values[1];
return {
operator: "IMPLIES" /* Implies */,
values: [
{
operator: "IMPLIES" /* Implies */,
values: [F, G]
},
{
operator: "IMPLIES" /* Implies */,
values: [F, H]
}
]
};
});
}
// src/propositional/hilbert-calculus/rules/implication-elimination.ts
function implicationEliminationRule(formulas) {
if (!isImplicationEliminationApplicable(formulas)) {
throw new Error(
"Implication elimination is not applicable to the given formulas."
);
}
const [formula1, formula2] = formulas;
let implicationFormula;
if (formula1.operator === "IMPLIES" /* Implies */ && Array.isArray(formula1.values) && formula1.values.length === 2 && arePropFormulasStructurallyEqual([formula1.values[0], formula2])) {
implicationFormula = formula1;
} else if (formula2.operator === "IMPLIES" /* Implies */ && Array.isArray(formula2.values) && formula2.values.length === 2 && arePropFormulasStructurallyEqual([formula2.values[0], formula1])) {
implicationFormula = formula2;
}
return [implicationFormula?.values[1]];
}
// src/propositional/hilbert-calculus/rules/implication-introduction.ts
function implicationIntroductionRule(formulas) {
if (!isImplicationIntroductionApplicable(formulas)) {
throw new Error(
"Implication introduction requires exactly two formulas: the proven formula and the new antecedent formula."
);
}
const [provenFormula, newFormula] = formulas;
return [
{
operator: "IMPLIES" /* Implies */,
values: [newFormula, provenFormula]
}
];
}
// src/propositional/hilbert-calculus/rules/implication-reversal.ts
function implicationReversalRule(formulas) {
if (!isImplicationReversalApplicable(formulas)) {
throw new Error(
"Implication reversal requires each formula to have the form \xACF => \xACG."
);
}
return formulas.map((formula) => {
const antecedent = formula.values[0];
const consequent = formula.values[1];
const F = antecedent.values[0];
const G = consequent.values[0];
return {
operator: "IMPLIES" /* Implies */,
values: [G, F]
};
});
}
// src/propositional/hilbert-calculus/generators/generate-hilbert-proof-steps.ts
function generateHilbertProofSteps(input) {
const { index, step } = input;
if (step === "Derivation" /* Derivation */) {
return buildDerivedSteps(index, input.payload);
}
if (step === "Axiom" /* Axiom */) {
return buildAxiomStep(index, input.payload);
}
return buildBaseStep(index, step, input.payload);
}
function buildDerivedSteps(index, payload) {
const { formulas, rule, derivedFrom } = payload;
const derivedFormulas = getRuleFunction(rule)(formulas);
return derivedFormulas.map((formula, derivedIndex) => {
return {
index: index + derivedIndex,
step: "Derivation" /* Derivation */,
formula,
stringView: convertPropFormulaToString(formula),
expression: convertPropFormulaToExpression(formula),
comment: `${rule}: ${derivedFrom.join(", ")}`,
derivedFrom
};
});
}
function buildAxiomStep(index, payload) {
const { formulas, schema } = payload;
const formula = getSchemaFunction(schema)(formulas);
return [
{
index,
step: "Axiom" /* Axiom */,
formula,
stringView: convertPropFormulaToString(formula),
expression: convertPropFormulaToExpression(formula),
comment: `${schema}`
}
];
}
function buildBaseStep(index, step, payload) {
return [
{
index,
step,
formula: payload.formula,
stringView: convertPropFormulaToString(payload.formula),
expression: convertPropFormulaToExpression(payload.formula),
comment: `${step}`
}
];
}
function getSchemaFunction(schema) {
switch (schema) {
case "II" /* II */:
return implicationIntroductionSchema;
case "ID" /* ID */:
return implicationDistributionSchema;
case "IR" /* IR */:
return implicationReversalSchema;
}
}
function getRuleFunction(rule) {
switch (rule) {
case "II" /* II */:
return implicationIntroductionRule;
case "ID" /* ID */:
return implicationDistributionRule;
case "IR" /* IR */:
return implicationReversalRule;
case "IE" /* IE */:
return implicationEliminationRule;
}
}
// src/propositional/hilbert-calculus/classes/hilbert-proof.ts
var HilbertProof = class {
/**
* Creates a new Hilbert proof with a goal formula.
* @param goal - The target formula to prove
*/
constructor(goal) {
this.steps = [];
this.goal = goal;
}
/**
* Gets all proof steps in order.
* @returns Array of proof steps
*/
getSteps() {
return Object.freeze([...this.steps]);
}
/**
* Gets the goal formula of this proof.
* @returns The target formula
*/
getGoal() {
return this.goal;
}
/**
* Gets the number of steps in the proof.
* @returns The current step count
*/
getStepCount() {
return this.steps.length;
}
/**
* Gets a specific step by index (1-based).
* @param index - The step number (1-based)
* @returns The proof step, or undefined if not found
*/
getStep(index) {
return this.steps[index - 1];
}
/**
* Adds a premise (given assumption) to the proof.
* @param formula - The premise formula
* @param comment - Optional explanation for the premise
* @returns The added proof step
*/
addPremise(formula, comment) {
const steps = generateHilbertProofSteps({
index: this.steps.length + 1,
step: "Premise" /* Premise */,
payload: { formula }
});
const step = steps[0];
if (comment) {
step.comment = comment;
}
this.steps.push(step);
return step;
}
/**
* Adds an axiom step to the proof.
* @param payload - The axiom payload containing formulas and schema
* @param comment - Optional explanation for the axiom
* @returns The added proof step
*/
addAxiom(payload, comment) {
const steps = generateHilbertProofSteps({
index: this.steps.length + 1,
step: "Axiom" /* Axiom */,
payload
});
const step = steps[0];
if (comment) {
step.comment = comment;
}
this.steps.push(step);
return step;
}
/**
* Adds a derived step to the proof using a Hilbert calculus rule.
* @param payload - The derived step payload containing formulas, schema, and step references
* @param comment - Optional explanation for the derivation
* @returns The added proof step
*/
addDerivedStep(payload, comment) {
const newSteps = generateHilbertProofSteps({
index: this.steps.length + 1,
step: "Derivation" /* Derivation */,
payload
});
newSteps.forEach((step) => {
if (comment) {
step.comment = comment;
}
this.steps.push(step);
});
return newSteps;
}
/**
* Checks if the proof is complete (last step matches the goal).
* @returns True if the last step's formula matches the goal
*/
isComplete() {
if (this.steps.length === 0) {
return false;
}
if (this.steps.every((step) => step.step === "Premise" /* Premise */)) {
return false;
}
const lastStep = this.getLastStep();
return arePropFormulasStructurallyEqual([lastStep.formula, this.goal]);
}
/**
* Gets the last step in the proof (which should be the goal).
* @returns The final proof step, or undefined if no steps exist
*/
getLastStep() {
return this.steps.at(-1);
}
/**
* Reiterates (repeats) a previously proved step.
* Allows referring to a formula from an earlier step in the proof.
* @param fromIndex - The index of the step to reiterate (1-based)
* @param comment - Optional explanation for the reiteration
* @returns The added reiteration step
* @throws {Error} if the step index is invalid
*/
reiterateStep(fromIndex, comment) {
const sourceStep = this.getStep(fromIndex);
if (!sourceStep) {
throw new Error(`Cannot reiterate: step ${fromIndex} not found in proof`);
}
const steps = generateHilbertProofSteps({
index: this.steps.length + 1,
step: "Reiteration" /* Reiteration */,
payload: { formula: sourceStep.formula }
});
const step = steps[0];
if (comment) {
step.comment = comment;
} else {
step.comment = `Reiteration: ${fromIndex}`;
}
step.derivedFrom = [fromIndex];
this.steps.push(step);
return step;
}
/**
* Clears all steps from the proof.
*/
clear() {
this.steps = [];
}
/**
* Replaces all occurrences of an atom with a formula or atom in all proof steps.
* The goal formula is not modified.
*
* @param atom - The atomic proposition to replace
* @param substitute - The formula or atom to substitute
*/
replace(atom, substitute) {
this.steps.forEach((step) => {
const newFormula = replaceAtomInFormula({
formula: step.formula,
atom,
substitute
});
step.formula = newFormula;
step.expression = convertPropFormulaToExpression(newFormula);
step.stringView = convertPropFormulaToString(newFormula);
});
}
};
// src/propositional/hilbert-calculus/classes/hilbert-proof-builder.ts
var HilbertProofBuilder = class {
/**
* Creates a new proof builder with a goal formula.
* @param goal - The target formula to prove
*/
constructor(goal) {
this.proof = new HilbertProof(goal);
}
/**
* Adds a premise (given assumption) to the proof.
* @param formula - The premise formula
* @param comment - Optional explanation for the premise
* @returns This builder instance for chaining
*/
addPremise(formula, comment) {
this.proof.addPremise(formula, comment);
return this;
}
/**
* Adds an axiom step to the proof.
* @param payload - The axiom payload containing formulas and schema
* @param comment - Optional explanation for the axiom
* @returns This builder instance for chaining
*/
addAxiom(payload, comment) {
this.proof.addAxiom(payload, comment);
return this;
}
/**
* Adds a derived step to the proof using a Hilbert calculus rule.
* @param payload - The derived step payload containing formulas, schema, and step references
* @param comment - Optional explanation for the derivation
* @returns This builder instance for chaining
*/
addDerivedStep(payload, comment) {
this.proof.addDerivedStep(payload, comment);
return this;
}
/**
* Reiterates (repeats) a previously proved step.
* Allows referring to a formula from an earlier step in the proof.
* @param fromIndex - The index of the step to reiterate (1-based)
* @param comment - Optional explanation for the reiteration
* @returns This builder instance for chaining
*/
reiterateStep(fromIndex, comment) {
this.proof.reiterateStep(fromIndex, comment);
return this;
}
/**
* Replaces all occurrences of an atom with a formula or atom in all proof steps.
* The goal formula is not modified.
*
* @param atom - The atomic proposition to replace
* @param substitute - The formula or atom to substitute
* @returns This builder instance for chaining
*/
replace(atom, substitute) {
this.proof.replace(atom, substitute);
return this;
}
/**
* Constructs the proof and returns it.
* @returns The completed HilbertProof instance
*/
build() {
return this.proof;
}
/**
* Adds multiple steps in sequence using a callback function.
* Useful for building complex proofs programmatically.
*
* @param stepsFn - A callback that receives the current builder and adds steps
* @returns This builder instance for chaining
*
* @example
* ```typescript
* proof.buildSteps((builder) => {
* builder.addPremise(p);
* builder.addAxiom(axiom1);
* builder.addDerivedStep(derived1);
* });
* ```
*/
buildSteps(stepsFn) {
stepsFn(this);
return this;
}
/**
* Gets the current state of the proof without building.
* Useful for inspection during construction.
* @returns The current HilbertProof instance
*/
preview() {
return this.proof;
}
};
// src/propositional/hilbert-calculus/generators/build-hilbert-proof.ts
function buildHilbertProof(goal) {
return new HilbertProofBuilder(goal);
}
// src/propositional/hilbert-calculus/generators/compose-hilbert-proof.ts
function composeHilbertProof(goal, ...stepGenerators) {
const builder = buildHilbertProof(goal);
for (const generator of stepGenerators) {
generator(builder);
}
return builder.build();
}
// src/propositional/hilbert-calculus/rules/index.ts
var HilbertRules = Object.freeze({
II: implicationIntroductionRule,
ID: implicationDistributionRule,
IE: implicationEliminationRule,
IR: implicationReversalRule
});
// src/propositional/natural-calculus/rules/conjunction-elimination.ts
function conjunctionElimination(formulas) {
if (!isConjunctionEliminationApplicable(formulas)) {
throw new Error(
"Conjunction Elimination is not applicable for the given formulas."
);
}
return formulas.flatMap((formula) => {
const conjunct1 = formula.values[0];
const conjunct2 = formula.values[1];
return [conjunct1, conjunct2];
});
}
// src/propositional/natural-calculus/rules/conjunction-introduction.ts
function conjunctionIntroduction(formulas) {
if (!isConjunctionIntroductionApplicable(formulas)) {
throw new Error(
"Conjunction introduction is not applicable to the given formulas."
);
}
const conjunct1 = formulas[0];
const conjunct2 = formulas[1];
return [
{
operator: "AND" /* And */,
values: [conjunct1, conjunct2]
},
{
operator: "AND" /* And */,
values: [conjunct2, conjunct1]
}
];
}
// src/propositional/natural-calculus/rules/disjunction-elimination.ts
function disjunctionElimination(formulas) {
if (!isDisjunctionEliminationApplicable(formulas)) {
throw new Error(
"Disjunction elimination is not applicable to the given formulas."
);
}
const implication1 = formulas.find(
(formula) => formula.operator === "IMPLIES" /* Implies */
);
return [implication1?.values[1]];
}
// src/propositional/natural-calculus/rules/disjunction-introduction.ts
function disjunctionIntroduction(formulas) {
if (!isDisjunctionIntroductionApplicable(formulas)) {
throw new Error(
"Disjunction introduction is not applicable to the given formulas."
);
}
const disjunct1 = formulas[0];
const disjunct2 = formulas[1];
return [
{ operator: "OR" /* Or */, values: [disjunct1, disjunct2] },
{ operator: "OR" /* Or */, values: [disjunct2, disjunct1] }
];
}
// src/propositional/natural-calculus/rules/equivalence-elimination.ts
function equivalenceElimination(formulas) {
if (!isEquivalenceEliminationApplicable(formulas)) {
throw new Error(
"Equivalence elimination is not applicable. All formulas must be equivalences."
);
}
return formulas.flatMap((formula) => {
const [A, B] = formula.values;
return [
{ operator: "IMPLIES" /* Implies */, values: [A, B] },
{ operator: "IMPLIES" /* Implies */, values: [B, A] }
];
});
}
// src/propositional/natural-calculus/rules/equivalence-introduction.ts
function equivalenceIntroduction(formulas) {
if (!isEquivalenceIntroductionApplicable(formulas)) {
throw new Error(
"Equivalence introduction is not applicable to the given formulas."
);
}
const [implication1, implication2] = formulas;
const firstAntecedent = implication1.values[0];
const secondAntecedent = implication2.values[0];
return [
{
operator: "EQUIV" /* Equiv */,
values: [firstAntecedent, secondAntecedent]
}
];
}
// src/propositional/natural-calculus/rules/implication-elimination.ts
functio