717ae1031e
Zanzibar-style authorization graph engine (direct/chain/TTU/defeasible/ binary modes, condensed snapshots, value relations) with 39 rigor test campaigns. Includes fixes for snapshot binary writer/reader format mismatch (snapshot-of-snapshot corruption), possibility write-boundary validation, empty-graph snapshot serialization, relation lookup cache direction collision, config-redefinition cache invalidation, binary threshold semantics, defeasible compiled routing, and comparator reason whitelisting.
257 lines
9.4 KiB
JavaScript
257 lines
9.4 KiB
JavaScript
/**
|
||
* Test Bilattice Orderings for Evidential Reasoning
|
||
*
|
||
* This test demonstrates the bilattice orderings (≥ᵢ, ≥ₜ) for comparing
|
||
* epistemic status of propositions in qualitative capacity systems.
|
||
*/
|
||
|
||
import { test, describe } from 'node:test';
|
||
import assert from 'node:assert';
|
||
import {
|
||
QualitativeScale,
|
||
QualitativeCapacity,
|
||
BilatticeOrderings
|
||
} from '../../src/qualitative/index.js';
|
||
|
||
describe('Bilattice Orderings', () => {
|
||
test('should implement information ordering correctly', () => {
|
||
const scale = QualitativeScale.fivePoint();
|
||
|
||
// Test information ordering: (c₁, c₁') ≥ᵢ (c₂, c₂') ⟺ c₁ ≥ c₂ and c₁' ≥ c₂'
|
||
const epistemic1 = { belief: 0.75, disbelief: 0.5 };
|
||
const epistemic2 = { belief: 0.5, disbelief: 0.25 };
|
||
const epistemic3 = { belief: 0.75, disbelief: 0.25 };
|
||
|
||
// epistemic1 should be more informative than epistemic2
|
||
assert.ok(BilatticeOrderings.informationOrdering(epistemic1, epistemic2, scale));
|
||
|
||
// epistemic1 should be more informative than epistemic3 (higher disbelief)
|
||
assert.ok(BilatticeOrderings.informationOrdering(epistemic1, epistemic3, scale));
|
||
|
||
// epistemic3 should NOT be more informative than epistemic1 (lower disbelief)
|
||
assert.ok(!BilatticeOrderings.informationOrdering(epistemic3, epistemic1, scale));
|
||
});
|
||
|
||
test('should implement truth ordering correctly', () => {
|
||
const scale = QualitativeScale.fivePoint();
|
||
const stateSpace = ['s1', 's2', 's3'];
|
||
|
||
// Create a capacity where s1 has high belief, s2 has medium belief
|
||
const qmt = new Map();
|
||
qmt.set(new Set(['s1']), 0.75); // High belief in s1
|
||
qmt.set(new Set(['s2']), 0.5); // Medium belief in s2
|
||
qmt.set(new Set(['s1', 's2']), 1); // Full belief in s1 OR s2
|
||
|
||
const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
|
||
|
||
const propositionA = ['s1']; // High belief
|
||
const propositionB = ['s2']; // Medium belief
|
||
|
||
// A should be more true than B: γ(A) ≥ γ(B) and γ(Bᶜ) ≥ γ(Aᶜ)
|
||
assert.ok(BilatticeOrderings.truthOrdering(propositionA, propositionB, capacity));
|
||
|
||
// B should NOT be more true than A
|
||
assert.ok(!BilatticeOrderings.truthOrdering(propositionB, propositionA, capacity));
|
||
});
|
||
|
||
test('should compare epistemic status comprehensively', () => {
|
||
const scale = QualitativeScale.fivePoint();
|
||
const stateSpace = ['s1', 's2', 's3'];
|
||
|
||
// Create a capacity with different belief levels
|
||
const qmt = new Map();
|
||
qmt.set(new Set(['s1']), 0.75);
|
||
qmt.set(new Set(['s2']), 0.5);
|
||
qmt.set(new Set(['s3']), 0.25);
|
||
qmt.set(new Set(['s1', 's2']), 1);
|
||
qmt.set(new Set(['s1', 's2', 's3']), 1);
|
||
|
||
const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
|
||
|
||
const propositionA = ['s1'];
|
||
const propositionB = ['s2'];
|
||
|
||
const comparison = BilatticeOrderings.compareEpistemicStatus(propositionA, propositionB, capacity);
|
||
|
||
// Check that we get a comprehensive comparison
|
||
assert.ok(comparison.propositionA);
|
||
assert.ok(comparison.propositionB);
|
||
assert.ok(typeof comparison.informationOrdering === 'boolean');
|
||
assert.ok(typeof comparison.truthOrdering === 'boolean');
|
||
assert.ok(typeof comparison.relationship === 'string');
|
||
assert.ok(typeof comparison.analysis === 'string');
|
||
|
||
// A should be more true than B, but not more informative
|
||
assert.ok(!comparison.informationOrdering);
|
||
assert.ok(comparison.truthOrdering);
|
||
assert.strictEqual(comparison.relationship, 'A more true than B');
|
||
});
|
||
|
||
test('should find most informative proposition', () => {
|
||
const scale = QualitativeScale.fivePoint();
|
||
const stateSpace = ['s1', 's2', 's3'];
|
||
|
||
// Create a capacity with varying belief levels
|
||
const qmt = new Map();
|
||
qmt.set(new Set(['s1']), 0.75);
|
||
qmt.set(new Set(['s2']), 0.5);
|
||
qmt.set(new Set(['s3']), 0.25);
|
||
qmt.set(new Set(['s1', 's2']), 1);
|
||
qmt.set(new Set(['s1', 's2', 's3']), 1);
|
||
|
||
const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
|
||
|
||
const propositions = [['s1'], ['s2'], ['s3']];
|
||
|
||
const mostInformative = BilatticeOrderings.findMostInformative(propositions, capacity);
|
||
|
||
// s1 should be most informative (highest belief and disbelief)
|
||
assert.deepStrictEqual(mostInformative.proposition, ['s1']);
|
||
assert.strictEqual(mostInformative.rank, 1);
|
||
assert.strictEqual(mostInformative.total, 3);
|
||
assert.ok(mostInformative.analysis.includes('Most informative'));
|
||
});
|
||
|
||
test('should find most true proposition', () => {
|
||
const scale = QualitativeScale.fivePoint();
|
||
const stateSpace = ['s1', 's2', 's3'];
|
||
|
||
// Create a capacity with varying belief levels
|
||
const qmt = new Map();
|
||
qmt.set(new Set(['s1']), 0.75);
|
||
qmt.set(new Set(['s2']), 0.5);
|
||
qmt.set(new Set(['s3']), 0.25);
|
||
qmt.set(new Set(['s1', 's2']), 1);
|
||
qmt.set(new Set(['s1', 's2', 's3']), 1);
|
||
|
||
const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
|
||
|
||
const propositions = [['s1'], ['s2'], ['s3']];
|
||
|
||
const mostTrue = BilatticeOrderings.findMostTrue(propositions, capacity);
|
||
|
||
// s1 should be most true (highest capacity value)
|
||
assert.deepStrictEqual(mostTrue.proposition, ['s1']);
|
||
assert.strictEqual(mostTrue.capacity, 0.75);
|
||
assert.strictEqual(mostTrue.rank, 1);
|
||
assert.strictEqual(mostTrue.total, 3);
|
||
assert.ok(mostTrue.analysis.includes('Most true'));
|
||
});
|
||
|
||
test('should rank propositions by information content', () => {
|
||
const scale = QualitativeScale.fivePoint();
|
||
const stateSpace = ['s1', 's2', 's3'];
|
||
|
||
// Create a capacity with varying belief levels
|
||
const qmt = new Map();
|
||
qmt.set(new Set(['s1']), 0.75);
|
||
qmt.set(new Set(['s2']), 0.5);
|
||
qmt.set(new Set(['s3']), 0.25);
|
||
qmt.set(new Set(['s1', 's2']), 1);
|
||
qmt.set(new Set(['s1', 's2', 's3']), 1);
|
||
|
||
const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
|
||
|
||
const propositions = [['s1'], ['s2'], ['s3']];
|
||
|
||
const ranking = BilatticeOrderings.rankByInformation(propositions, capacity);
|
||
|
||
// Should have 3 ranked propositions
|
||
assert.strictEqual(ranking.length, 3);
|
||
|
||
// Check ranking structure
|
||
for (let i = 0; i < ranking.length; i++) {
|
||
assert.strictEqual(ranking[i].rank, i + 1);
|
||
assert.ok(ranking[i].proposition);
|
||
assert.ok(ranking[i].epistemic);
|
||
assert.ok(ranking[i].analysis);
|
||
}
|
||
|
||
// s1 should be ranked first (most informative)
|
||
assert.deepStrictEqual(ranking[0].proposition, ['s1']);
|
||
});
|
||
|
||
test('should rank propositions by truth content', () => {
|
||
const scale = QualitativeScale.fivePoint();
|
||
const stateSpace = ['s1', 's2', 's3'];
|
||
|
||
// Create a capacity with varying belief levels
|
||
const qmt = new Map();
|
||
qmt.set(new Set(['s1']), 0.75);
|
||
qmt.set(new Set(['s2']), 0.5);
|
||
qmt.set(new Set(['s3']), 0.25);
|
||
qmt.set(new Set(['s1', 's2']), 1);
|
||
qmt.set(new Set(['s1', 's2', 's3']), 1);
|
||
|
||
const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
|
||
|
||
const propositions = [['s1'], ['s2'], ['s3']];
|
||
|
||
const ranking = BilatticeOrderings.rankByTruth(propositions, capacity);
|
||
|
||
// Should have 3 ranked propositions
|
||
assert.strictEqual(ranking.length, 3);
|
||
|
||
// Check ranking structure
|
||
for (let i = 0; i < ranking.length; i++) {
|
||
assert.strictEqual(ranking[i].rank, i + 1);
|
||
assert.ok(ranking[i].proposition);
|
||
assert.ok(typeof ranking[i].capacity === 'number');
|
||
assert.ok(ranking[i].analysis);
|
||
}
|
||
|
||
// s1 should be ranked first (most true)
|
||
assert.deepStrictEqual(ranking[0].proposition, ['s1']);
|
||
assert.strictEqual(ranking[0].capacity, 0.75);
|
||
});
|
||
|
||
test('should handle edge cases correctly', () => {
|
||
const scale = QualitativeScale.fivePoint();
|
||
const stateSpace = ['s1', 's2'];
|
||
|
||
// Create a simple capacity
|
||
const qmt = new Map();
|
||
qmt.set(new Set(['s1']), 0.5);
|
||
qmt.set(new Set(['s1', 's2']), 1);
|
||
|
||
const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
|
||
|
||
// Test with single proposition
|
||
const singleProposition = [['s1']];
|
||
|
||
const mostInformative = BilatticeOrderings.findMostInformative(singleProposition, capacity);
|
||
const mostTrue = BilatticeOrderings.findMostTrue(singleProposition, capacity);
|
||
|
||
assert.deepStrictEqual(mostInformative.proposition, ['s1']);
|
||
assert.strictEqual(mostInformative.rank, 1);
|
||
assert.strictEqual(mostInformative.total, 1);
|
||
|
||
assert.deepStrictEqual(mostTrue.proposition, ['s1']);
|
||
assert.strictEqual(mostTrue.rank, 1);
|
||
assert.strictEqual(mostTrue.total, 1);
|
||
});
|
||
|
||
test('should handle incomparable propositions', () => {
|
||
const scale = QualitativeScale.fivePoint();
|
||
const stateSpace = ['s1', 's2', 's3'];
|
||
|
||
// Create a capacity where propositions are incomparable
|
||
const qmt = new Map();
|
||
qmt.set(new Set(['s1']), 0.75); // High belief, low disbelief
|
||
qmt.set(new Set(['s2']), 0.5); // Medium belief, medium disbelief
|
||
qmt.set(new Set(['s1', 's2']), 1);
|
||
qmt.set(new Set(['s1', 's2', 's3']), 1);
|
||
|
||
const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
|
||
|
||
const propositionA = ['s1'];
|
||
const propositionB = ['s2'];
|
||
|
||
const comparison = BilatticeOrderings.compareEpistemicStatus(propositionA, propositionB, capacity);
|
||
|
||
// Should identify the relationship correctly
|
||
assert.ok(typeof comparison.relationship === 'string');
|
||
assert.ok(comparison.relationship !== '');
|
||
});
|
||
});
|