UNPKG

chop-logic-core

Version:

An npm package for core functions of the Chop Logic project.

1,042 lines (989 loc) 34.8 kB
// src/enums/glyph.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 || {}); // src/enums/prop-formula-check.ts 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"; return PropFormulaCheck2; })(PropFormulaCheck || {}); // 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.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"); const variablePattern = "[a-zA-Z]+"; const tokenizer = new RegExp(`(${glyphPattern})|(${variablePattern})`, "g"); const tokens = input.match(tokenizer); if (!tokens || tokens.join("") !== input.replace(/\s+/g, "")) { throw new Error(`Invalid character(s) found in input: "${input}".`); } return tokens; } // src/tokenizer/index.ts var Tokenizer = Object.freeze({ getGlyphUnicode, getOperatorGlyph, tokenizeString }); // src/propositional/factory/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/factory/create-prop-expression.ts function createPropExpression(input) { const tokens = tokenizeString(input); return tokens.map((token, index) => createPropSymbol(token, index)); } // src/propositional/factory/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/propositional/utils/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 (isNegation2(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; } function isVariable(symbol) { return symbol.type === "variable" /* Variable */; } function isNegation2(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 */; } const result = parseWFF(); return result && index === expression.length; } // src/propositional/factory/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 (isNegation(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 isNegation(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/factory/index.ts var PropositionalFactory = Object.freeze({ createExpression: createPropExpression, createFormula: createPropFormula, createSymbol: createPropSymbol, createOperator }); // src/propositional/hilbert-calculus/implication-introduction.ts function implicationIntroduction(formulas) { const [A, B] = formulas; return { operator: "IMPLIES" /* Implies */, values: [ A, { operator: "IMPLIES" /* Implies */, values: [B, A] } ] }; } // src/propositional/hilbert-calculus/implication-distribution.ts function implicationDistribution(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/implication-reversal.ts function implicationReversal(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/checks/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/checks/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/hilbert-calculus/implication-elimination.ts function implicationElimination(formulas) { if (!isImplicationEliminationApplicable(formulas)) { throw new Error("Implication elimination is not applicable to the given formulas."); } const implicationFormula = formulas.find((f) => f.operator === "IMPLIES" /* Implies */); return implicationFormula.values[1]; } // src/propositional/utils/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]}`; } return `(${values.join(` ${glyph} `)})`; } // src/propositional/utils/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/hilbert-calculus/generate-hilbert-proof-step.ts function generateHilbertProofStep(input) { const { index, step } = input; if (step === "Derivation" /* Derivation */) { return buildDerivedStep(index, input.payload); } if (step === "Axiom" /* Axiom */) { return buildAxiomStep(index, input.payload); } return buildBaseStep(index, step, input.payload); } function buildDerivedStep(index, payload) { const { formulas, schema, derivedFrom } = payload; const formula = getRuleFunction(schema)(formulas); return { index, step: "Derivation" /* Derivation */, formula, stringView: convertPropFormulaToString(formula), expression: convertPropFormulaToExpression(formula), comment: `${schema}: ${derivedFrom.join(", ")}`, derivedFrom }; } function buildAxiomStep(index, payload) { const { formulas, schema } = payload; const formula = getRuleFunction(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: createPropExpression(convertPropFormulaToString(payload.formula)), comment: `${step}` }; } function getRuleFunction(schema) { switch (schema) { case "II" /* II */: return implicationIntroduction; case "ID" /* ID */: return implicationDistribution; case "IR" /* IR */: return implicationReversal; case "IE" /* IE */: return implicationElimination; } } // src/propositional/hilbert-calculus/index.ts var HilbertCalculus = Object.freeze({ generateStep: generateHilbertProofStep, // Axiom Schemas II: implicationIntroduction, ID: implicationDistribution, IR: implicationReversal, IE: implicationElimination }); // src/propositional/checks/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/natural-calculus/negation-introduction.ts function negationIntroduction(formulas) { if (!isNegationIntroductionApplicable(formulas)) { throw new Error("Negation introduction is not applicable to the given formulas."); } const antecedent = formulas[0].values[0]; return [ { operator: "NOT" /* Not */, values: [antecedent] } ]; } // src/propositional/checks/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/natural-calculus/negation-elimination.ts function negationElimination(formulas) { if (!isNegationEliminationApplicable(formulas)) { throw new Error("Negation elimination is not applicable to the given formulas."); } const firstNegationFormula = formulas[0]; const secondNegationFormula = firstNegationFormula.values[0]; return [secondNegationFormula.values[0]]; } // src/propositional/checks/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/natural-calculus/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/checks/is-equivalence-elimination-applicable.ts function isEquivalenceEliminationApplicable(formulas) { if (formulas.length === 0) { return false; } return formulas.every((formula) => formula.operator === "EQUIV" /* Equiv */); } // src/propositional/natural-calculus/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/implication-elimination.ts function implicationElimination2(formulas) { if (!isImplicationEliminationApplicable(formulas)) { throw new Error("Implication elimination is not applicable to the given formulas."); } const implicationFormula = formulas.find((f) => f.operator === "IMPLIES" /* Implies */); return [implicationFormula.values[1]]; } // src/propositional/checks/is-dusjunction-introduction-applicable.ts function isDisjunctionIntroductionApplicable(formulas) { return formulas.length === 2; } // src/propositional/natural-calculus/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/checks/is-implication-introduction-applicable.ts function isImplicationIntroductionApplicable(formulas) { return formulas.length === 2; } // src/propositional/natural-calculus/implication-introduction.ts function implicationIntroduction2(formulas) { if (!isImplicationIntroductionApplicable(formulas)) { throw new Error("Implication introduction is not applicable to the given formulas."); } const [premise, conclusion] = formulas; return [{ operator: "IMPLIES" /* Implies */, values: [premise, conclusion] }]; } // src/propositional/checks/is-conjunction-introduction-applicable.ts function isConjunctionIntroductionApplicable(formulas) { return formulas.length === 2; } // src/propositional/natural-calculus/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/checks/is-conjunction-elimination-applicable.ts function isConjunctionEliminationApplicable(formulas) { if (formulas.length === 0) { return false; } return formulas.every((formula) => formula.operator === "AND" /* And */); } // src/propositional/natural-calculus/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/checks/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]) { if (formula.operator === "OR" /* Or */ && Array.isArray(formula.values) && formula.values.length === 2) { disjunction = formula; } else if (formula.operator === "IMPLIES" /* Implies */ && Array.isArray(formula.values) && formula.values.length === 2) { if (!implication1) { 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/natural-calculus/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/generate-natural-proof-steps.ts function generateNaturalProofSteps(input) { const { index, level, step, assumptionIndex } = input; if (step === "Derivation" /* Derivation */) { return buildDerivedSteps({ index, level, assumptionIndex, payload: input.payload }); } return [buildBaseStep2({ index, level, step, assumptionIndex, payload: input.payload })]; } function buildDerivedSteps({ index, level, payload, assumptionIndex }) { const { formulas, rule, derivedFrom } = payload; const derivedFormulas = getRuleFunction2(rule)(formulas); return derivedFormulas.map((formula, idx) => ({ index: index + idx + 1, level, step: "Derivation" /* Derivation */, formula, assumptionIndex, stringView: convertPropFormulaToString(formula), expression: convertPropFormulaToExpression(formula), comment: `${rule}: ${derivedFrom.join(", ")}`, derivedFrom })); } function buildBaseStep2({ index, level, step, payload, assumptionIndex }) { return { index, level, step, assumptionIndex, formula: payload.formula, stringView: convertPropFormulaToString(payload.formula), expression: createPropExpression(convertPropFormulaToString(payload.formula)), comment: `${step}` }; } function getRuleFunction2(rule) { switch (rule) { // Introduction rules case "CI" /* CI */: return conjunctionIntroduction; case "DI" /* DI */: return disjunctionIntroduction; case "II" /* II */: return implicationIntroduction2; case "EI" /* EI */: return equivalenceIntroduction; case "NI" /* NI */: return negationIntroduction; // Elimination rules case "CE" /* CE */: return conjunctionElimination; case "DE" /* DE */: return disjunctionElimination; case "IE" /* IE */: return implicationElimination2; case "EE" /* EE */: return equivalenceElimination; case "NE" /* NE */: return negationElimination; } } // src/propositional/natural-calculus/index.ts var NaturalCalculus = Object.freeze({ generateSteps: generateNaturalProofSteps, // Introduction rules NI: negationIntroduction, CI: conjunctionIntroduction, DI: disjunctionIntroduction, II: implicationIntroduction2, EI: equivalenceIntroduction, // Elimination rules NE: negationElimination, CE: conjunctionElimination, DE: disjunctionElimination, IE: implicationElimination2, EE: equivalenceElimination }); // src/propositional/utils/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/utils/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/utils/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; subFormulas.forEach(traverse); } } traverse(formula); const sortedVariables = Array.from(variablesSet).sort(); return new Map(sortedVariables.map((varName, index) => [index, [varName]])); } // src/propositional/utils/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/utils/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/utils/generate-truth-assignments.ts function generateTruthAssignments(varCount, limit = 100) { if (varCount > limit) { throw new Error(`Exceeded maximum variable limit (${limit}) for truth assignments.`); } const numAssignments = 2 ** varCount; const assignments = /* @__PURE__ */ new Map(); for (let i = 0; i < numAssignments; i++) { const binaryValues = Array.from({ length: varCount }, (_, bit) => Boolean(i & 1 << varCount - bit - 1)); assignments.set(i, binaryValues); } return assignments; } // src/propositional/utils/generate-prop-truth-table.ts function generatePropTruthTable(formula, limit = 100) { const variablesMap = extractPropVariables(formula); const variableCount = variablesMap.size; const truthAssignments = generateTruthAssignments(variableCount, limit); const truthTable = /* @__PURE__ */ new Map(); truthAssignments.forEach((assignment, index) => { const formulaValue = calculatePropFormula({ formula, assignment, variablesMap }); truthTable.set(index, [...assignment, formulaValue]); }); return truthTable; } // src/propositional/checks/index.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 }; function applyPropFormulaChecks(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/utils/index.ts var PropositionalUtils = Object.freeze({ calculateFormula: calculatePropFormula, convertToString: convertPropFormulaToString, convertToExpression: convertPropFormulaToExpression, getVariables: extractPropVariables, getSubFormulas: extractPropSubFormulas, isWFF: isWellFormedFormula, getUnaryValue: getUnaryOperationValue, getBinaryValue: getBinaryOperationValue, generateTT: generatePropTruthTable, generateAssignments: generateTruthAssignments, applyChecks: applyPropFormulaChecks }); // src/index.ts var ChopLogicCore = Object.freeze({ Tokenizer, PropositionalFactory, PropositionalUtils, HilbertCalculus, NaturalCalculus }); export { ChopLogicCore };