/** * Test Bilattice Integration with Existing Possibilistic Infrastructure * * This test demonstrates how bilattice orderings are integrated into our existing * rule system while maintaining compatibility with possibilistic reasoning. */ import { test, describe } from 'node:test'; import assert from 'node:assert'; import { QualitativeScale, QualitativeCapacity, BilatticeOrderings, getSetKey } from '../../src/qualitative/index.js'; describe('Bilattice Integration with Possibilistic Infrastructure', () => { test('should demonstrate BaseRule bilattice-enhanced evidence combination', () => { const scale = QualitativeScale.fivePoint(); const stateSpace = ['evidence1', 'evidence2', 'evidence3']; // Create a capacity for bilattice analysis const qmt = new Map(); qmt.set(getSetKey(new Set(['evidence1'])), 0.75); // High belief evidence qmt.set(getSetKey(new Set(['evidence2'])), 0.5); // Medium belief evidence qmt.set(getSetKey(new Set(['evidence3'])), 0.25); // Low belief evidence qmt.set(getSetKey(new Set(['evidence1', 'evidence2'])), 1); // Combined evidence const capacity = new QualitativeCapacity(stateSpace, scale, qmt); // Simulate collected values from rule evaluation - using valid fivePoint scale values const collectedValues = [ { value: 0.75, // Valid fivePoint scale value possibility: 0.75, // Valid fivePoint scale value path: ['user', 'relation1'], source: { entityKey: 'user1', relation: 'score', step: 0 }, metadata: { timestamp: Date.now(), reliability: 0.9 } }, { value: 0.5, // Valid fivePoint scale value possibility: 0.5, // Valid fivePoint scale value path: ['user', 'relation2'], source: { entityKey: 'user2', relation: 'rating', step: 1 }, metadata: { timestamp: Date.now(), reliability: 0.8 } }, { value: 0.25, // Valid fivePoint scale value possibility: 0.25, // Valid fivePoint scale value path: ['user', 'relation3'], source: { entityKey: 'user3', relation: 'feedback', step: 2 }, metadata: { timestamp: Date.now(), reliability: 0.7 } } ]; // Test information-based evidence selection const epistemicPairs = collectedValues.map(cv => ({ belief: cv.possibility, disbelief: 1 - cv.possibility })); // Create propositions for bilattice analysis const propositions = collectedValues.map((cv, index) => [`evidence${index + 1}`]); const mostInformative = BilatticeOrderings.findMostInformative(propositions, capacity); // The most informative evidence should be the one with highest belief AND disbelief // Evidence 1: belief=0.75, disbelief=0.25 // Evidence 2: belief=0.5, disbelief=0.5 // Evidence 3: belief=0.25, disbelief=0.75 // Evidence 1 and 2 are incomparable in information ordering (neither dominates) // The algorithm picks the first one (evidence 1) as default assert.strictEqual(mostInformative.epistemic.belief, 0.75); // Disbelief = capacity of the complement: max focal subset of // {evidence2, evidence3} is {evidence2}=0.5. assert.strictEqual(mostInformative.epistemic.disbelief, 0.5); assert.strictEqual(mostInformative.rank, 1); }); test('should demonstrate qualitative relational comparator with bilattice reasoning', () => { const scale = QualitativeScale.fivePoint(); // Simulate blurred values from qualitative decay const blurredValues = [ { interval: { lower: 0.5, upper: 0.75 }, possibility: 0.75, originalValue: 0.75, originalPossibility: 1.0, timestamp: Date.now(), relation: 'score', meta: { periodsElapsed: 1, blurSteps: 1 } }, { interval: { lower: 0.25, upper: 0.5 }, possibility: 0.5, originalValue: 0.5, originalPossibility: 0.8, timestamp: Date.now(), relation: 'rating', meta: { periodsElapsed: 2, blurSteps: 2 } } ]; // Test epistemic comparison of blurred values const epistemicPairs = blurredValues.map(bv => ({ belief: bv.possibility, disbelief: 1 - bv.possibility })); // Create a simple capacity for comparison const stateSpace = ['blurred1', 'blurred2']; const qmt = new Map(); qmt.set(getSetKey(new Set(['blurred1'])), 0.75); qmt.set(getSetKey(new Set(['blurred2'])), 0.5); const capacity = new QualitativeCapacity(stateSpace, scale, qmt); const comparison = BilatticeOrderings.compareEpistemicStatus( ['blurred1'], ['blurred2'], capacity ); // blurred1 should be more true than blurred2 (higher capacity value) assert.ok(comparison.truthOrdering); assert.strictEqual(comparison.relationship, 'A more true than B'); }); test('should demonstrate defeasible logic with bilattice reasoning', () => { const scale = QualitativeScale.tenPoint(); // Simulate evidence from different rule types in defeasible logic const strictEvidence = { value: 1.0, possibility: 1.0, path: ['strict_rule'], source: { entityKey: 'system', relation: 'strict_check', step: 0 }, metadata: { timestamp: Date.now(), reliability: 1.0, ruleType: 'strict' } }; const defeasibleEvidence = { value: 0.8, possibility: 0.8, path: ['defeasible_rule'], source: { entityKey: 'user', relation: 'user_check', step: 1 }, metadata: { timestamp: Date.now(), reliability: 0.9, ruleType: 'defeasible' } }; const defeaterEvidence = { value: 0.6, possibility: 0.6, path: ['defeater_rule'], source: { entityKey: 'security', relation: 'security_check', step: 2 }, metadata: { timestamp: Date.now(), reliability: 0.8, ruleType: 'defeater' } }; const allEvidence = [strictEvidence, defeasibleEvidence, defeaterEvidence]; // Create capacity representing the defeasible logic structure const stateSpace = ['strict', 'defeasible', 'defeater']; const qmt = new Map(); qmt.set(getSetKey(new Set(['strict'])), 1.0); // Strict rules have highest priority qmt.set(getSetKey(new Set(['defeasible'])), 0.8); // Defeasible rules have medium priority qmt.set(getSetKey(new Set(['defeater'])), 0.6); // Defeaters have lower priority qmt.set(getSetKey(new Set(['strict', 'defeasible'])), 1.0); // Strict + defeasible = strict wins qmt.set(getSetKey(new Set(['strict', 'defeater'])), 1.0); // Strict + defeater = strict wins qmt.set(getSetKey(new Set(['defeasible', 'defeater'])), 0.8); // Defeasible + defeater = defeasible wins const capacity = new QualitativeCapacity(stateSpace, scale, qmt); // Test information ordering for defeasible logic const epistemicPairs = allEvidence.map(ev => ({ belief: ev.possibility, disbelief: 1 - ev.possibility })); // Create propositions for bilattice analysis (must match the capacity state space) const propositions = [['strict'], ['defeasible'], ['defeater']]; const informationRanking = BilatticeOrderings.rankByInformation(propositions, capacity); // Strict evidence should rank highest in information ordering const strictRank = informationRanking.find(r => r.epistemic.belief === 1.0)?.rank; const defeasibleRank = informationRanking.find(r => r.epistemic.belief === 0.8)?.rank; const defeaterRank = informationRanking.find(r => r.epistemic.belief === 0.6)?.rank; assert.ok(strictRank <= defeasibleRank); assert.ok(defeasibleRank <= defeaterRank); }); test('should demonstrate chain rule with epistemic path analysis', () => { const scale = QualitativeScale.tenPoint(); // Simulate collected values from a chain traversal const chainValues = [ { value: 0.9, possibility: 0.9, path: ['user', 'account', 'balance'], source: { entityKey: 'account1', relation: 'balance', step: 2 }, metadata: { timestamp: Date.now(), reliability: 0.95, pathPossibility: 0.9 } }, { value: 0.7, possibility: 0.7, path: ['user', 'account', 'credit'], source: { entityKey: 'account2', relation: 'credit', step: 2 }, metadata: { timestamp: Date.now(), reliability: 0.85, pathPossibility: 0.7 } }, { value: 0.5, possibility: 0.5, path: ['user', 'account', 'debt'], source: { entityKey: 'account3', relation: 'debt', step: 2 }, metadata: { timestamp: Date.now(), reliability: 0.75, pathPossibility: 0.5 } } ]; // Create capacity for path-based epistemic analysis const stateSpace = ['path1', 'path2', 'path3']; const qmt = new Map(); qmt.set(getSetKey(new Set(['path1'])), 0.9); // High confidence path qmt.set(getSetKey(new Set(['path2'])), 0.7); // Medium confidence path qmt.set(getSetKey(new Set(['path3'])), 0.5); // Low confidence path qmt.set(getSetKey(new Set(['path1', 'path2'])), 1.0); // Combined high-confidence paths const capacity = new QualitativeCapacity(stateSpace, scale, qmt); // Test truth ordering for path selection const pathPropositions = [ ['path1'], ['path2'], ['path3'] ]; const truthRanking = BilatticeOrderings.rankByTruth(pathPropositions, capacity); // Path1 should rank highest in truth ordering (highest capacity value) const path1Rank = truthRanking.find(r => r.capacity === 0.9)?.rank; const path2Rank = truthRanking.find(r => r.capacity === 0.7)?.rank; const path3Rank = truthRanking.find(r => r.capacity === 0.5)?.rank; assert.strictEqual(path1Rank, 1); assert.ok(path2Rank > path1Rank); assert.ok(path3Rank > path2Rank); }); test('should demonstrate hybrid epistemic reasoning', () => { const scale = QualitativeScale.tenPoint(); // Simulate mixed evidence from different sources const mixedEvidence = [ { value: 0.8, possibility: 0.8, path: ['direct_evidence'], source: { entityKey: 'direct', relation: 'observation', step: 0 }, metadata: { timestamp: Date.now(), reliability: 0.9, sourceType: 'direct' } }, { value: 0.6, possibility: 0.6, path: ['inferred_evidence'], source: { entityKey: 'inference', relation: 'deduction', step: 1 }, metadata: { timestamp: Date.now(), reliability: 0.7, sourceType: 'inferred' } }, { value: 0.4, possibility: 0.4, path: ['similarity_evidence'], source: { entityKey: 'similarity', relation: 'analogy', step: 2 }, metadata: { timestamp: Date.now(), reliability: 0.6, sourceType: 'similarity' } } ]; // Create capacity for hybrid analysis const stateSpace = ['direct', 'inferred', 'similarity']; const qmt = new Map(); qmt.set(getSetKey(new Set(['direct'])), 0.8); // Direct evidence has highest reliability qmt.set(getSetKey(new Set(['inferred'])), 0.6); // Inferred evidence has medium reliability qmt.set(getSetKey(new Set(['similarity'])), 0.4); // Similarity evidence has lowest reliability qmt.set(getSetKey(new Set(['direct', 'inferred'])), 0.9); // Direct + inferred = high confidence qmt.set(getSetKey(new Set(['direct', 'similarity'])), 0.8); // Direct + similarity = direct dominates qmt.set(getSetKey(new Set(['inferred', 'similarity'])), 0.6); // Inferred + similarity = inferred dominates const capacity = new QualitativeCapacity(stateSpace, scale, qmt); // Test comprehensive epistemic comparison const epistemicPairs = mixedEvidence.map(ev => ({ belief: ev.possibility, disbelief: 1 - ev.possibility })); // Create propositions for bilattice analysis (must match the capacity state space) const propositions = [['direct'], ['inferred'], ['similarity']]; const informationRanking = BilatticeOrderings.rankByInformation(propositions, capacity); const truthRanking = BilatticeOrderings.rankByTruth(propositions, capacity); // Direct evidence should rank highest in both orderings const directInfoRank = informationRanking.find(r => r.epistemic.belief === 0.8)?.rank; const directTruthRank = truthRanking.find(r => r.capacity === 0.8)?.rank; assert.strictEqual(directInfoRank, 1); assert.strictEqual(directTruthRank, 1); // Test comprehensive comparison const comparison = BilatticeOrderings.compareEpistemicStatus( ['direct'], ['inferred'], capacity ); assert.ok(comparison.truthOrdering); assert.strictEqual(comparison.relationship, 'A more true than B'); }); test('should maintain backward compatibility with existing possibilistic infrastructure', () => { const scale = QualitativeScale.tenPoint(); // Test that bilattice reasoning can be disabled and standard OWA fusion still works const standardEvidence = [ { value: 0.8, possibility: 0.8, path: ['evidence1'], source: {}, metadata: {} }, { value: 0.6, possibility: 0.6, path: ['evidence2'], source: {}, metadata: {} }, { value: 0.4, possibility: 0.4, path: ['evidence3'], source: {}, metadata: {} } ]; // Test standard OWA fusion (bilattice disabled) const epistemicPairs = standardEvidence.map(ev => ({ belief: ev.possibility, disbelief: 1 - ev.possibility })); // Standard max operation should select the highest value const maxValue = Math.max(...standardEvidence.map(ev => ev.possibility)); assert.strictEqual(maxValue, 0.8); // Test that bilattice reasoning can be enabled when needed const stateSpace = ['ev1', 'ev2', 'ev3']; const qmt = new Map(); qmt.set(getSetKey(new Set(['ev1'])), 0.8); qmt.set(getSetKey(new Set(['ev2'])), 0.6); qmt.set(getSetKey(new Set(['ev3'])), 0.4); const capacity = new QualitativeCapacity(stateSpace, scale, qmt); // Create propositions for bilattice analysis const propositions = standardEvidence.map((ev, index) => [`ev${index + 1}`]); const mostInformative = BilatticeOrderings.findMostInformative(propositions, capacity); // Epistemic pairs from the capacity: // ev1 ({ev1}): belief=0.8, disbelief=gamma({ev2,ev3})=0.6 // ev2 ({ev2}): belief=0.6, disbelief=gamma({ev1,ev3})=0.8 // ev3 ({ev3}): belief=0.4, disbelief=gamma({ev1,ev2})=0.8 // ev1 dominates in belief; the algorithm keeps the first best (ev1). assert.strictEqual(mostInformative.epistemic.belief, 0.8); assert.strictEqual(mostInformative.epistemic.disbelief, 0.6); }); });