/ src / ternary.js
ternary.js
  1  // SPDX-License-Identifier: AGPL-3.0-or-later
  2  // SPDX-FileCopyrightText: 2025 hyperpolymath
  3  //
  4  // BetLang - Ternary Logic Implementation
  5  // Three-valued logic: True (T), False (F), Unknown (U)
  6  
  7  /**
  8   * Ternary Logic in BetLang
  9   *
 10   * Three-valued logic extends boolean logic with an "unknown" value.
 11   * This is useful for:
 12   * - Handling incomplete information
 13   * - Representing sensor uncertainty
 14   * - Database NULL semantics
 15   * - Formal verification with partial knowledge
 16   */
 17  
 18  // Ternary AND (Kleene logic)
 19  // T AND T = T, T AND U = U, T AND F = F
 20  // U AND U = U, U AND F = F
 21  // F AND F = F
 22  export function ternaryAnd(operandA, operandB) {
 23    if (operandA === "F" || operandB === "F") return "F";
 24    if (operandA === "U" || operandB === "U") return "U";
 25    return "T";
 26  }
 27  
 28  // Ternary OR (Kleene logic)
 29  // T OR T = T, T OR U = T, T OR F = T
 30  // U OR U = U, U OR F = U
 31  // F OR F = F
 32  export function ternaryOr(operandA, operandB) {
 33    if (operandA === "T" || operandB === "T") return "T";
 34    if (operandA === "U" || operandB === "U") return "U";
 35    return "F";
 36  }
 37  
 38  // Ternary NOT (Kleene logic)
 39  // NOT T = F, NOT F = T, NOT U = U
 40  export function ternaryNot(operand) {
 41    if (operand === "T") return "F";
 42    if (operand === "F") return "T";
 43    return "U";
 44  }
 45  
 46  // Ternary implication (material implication)
 47  // A => B is equivalent to (NOT A) OR B
 48  export function ternaryImplies(operandA, operandB) {
 49    return ternaryOr(ternaryNot(operandA), operandB);
 50  }
 51  
 52  // Ternary equivalence
 53  // A <=> B is equivalent to (A => B) AND (B => A)
 54  export function ternaryEquivalent(operandA, operandB) {
 55    return ternaryAnd(ternaryImplies(operandA, operandB), ternaryImplies(operandB, operandA));
 56  }
 57  
 58  // Check if a ternary value is definite (not unknown)
 59  export function isDefinite(value) {
 60    return value !== "U";
 61  }
 62  
 63  // Check if a ternary value is true
 64  export function isTrue(value) {
 65    return value === "T";
 66  }
 67  
 68  // Check if a ternary value is false
 69  export function isFalse(value) {
 70    return value === "F";
 71  }
 72  
 73  // Check if a ternary value is unknown
 74  export function isUnknown(value) {
 75    return value === "U";
 76  }
 77  
 78  // Convert boolean to ternary
 79  export function booleanToTernary(value) {
 80    return value ? "T" : "F";
 81  }
 82  
 83  // Convert ternary to boolean (throws if unknown)
 84  export function ternaryToBoolean(value) {
 85    if (value === "U") {
 86      throw new Error("Cannot convert Unknown to boolean");
 87    }
 88    return value === "T";
 89  }
 90  
 91  // Try to convert ternary to boolean (returns null if unknown)
 92  export function tryTernaryToBoolean(value) {
 93    if (value === "U") return null;
 94    return value === "T";
 95  }
 96  
 97  // Print truth table for a binary operation
 98  export function printTruthTable(operationName, operation) {
 99    const values = ["T", "U", "F"];
100  
101    console.log(`${operationName} Truth Table:`);
102    console.log("  | T | U | F |");
103    console.log("--+---+---+---+");
104  
105    for (const operandA of values) {
106      const row = values.map((operandB) => operation(operandA, operandB)).join(" | ");
107      console.log(`${operandA} | ${row} |`);
108    }
109  }
110  
111  // Demonstration
112  function demonstrateTernary() {
113    console.log("=== Ternary Logic Module ===\n");
114  
115    printTruthTable("AND", ternaryAnd);
116    console.log("");
117    printTruthTable("OR", ternaryOr);
118    console.log("");
119    printTruthTable("IMPLIES", ternaryImplies);
120    console.log("");
121    printTruthTable("EQUIV", ternaryEquivalent);
122  }
123  
124  // Run if executed directly
125  if (import.meta.main) {
126    demonstrateTernary();
127  }