chop-logic-core
Version:
An npm package for core functions of the Chop Logic project.
1,042 lines (989 loc) • 34.8 kB
JavaScript
// 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
};