Files
core/tests/rules/qualitative-capacity-simple.test.js
T

251 lines
9.6 KiB
JavaScript
Raw Normal View History

/**
* Simple Test Suite for Qualitative Capacity System
*
* Tests core functionality using Node.js built-in test framework
*/
import { test, describe } from 'node:test';
import assert from 'node:assert/strict';
import {
QualitativeScale,
QualitativeCapacity,
QualitativeFusion,
OWAQualitativeFusion,
getOWAQualitativeWeights,
DEFAULT_QUALITATIVE_SCALE
} from '../../src/qualitative/index.js';
describe('QualitativeScale', () => {
test('should create scale with correct properties', () => {
const scale = new QualitativeScale([0, 0.25, 0.5, 0.75, 1], 'test');
assert.deepStrictEqual(scale.values, [0, 0.25, 0.5, 0.75, 1]);
assert.strictEqual(scale.bottom, 0);
assert.strictEqual(scale.top, 1);
assert.strictEqual(scale.size, 5);
});
test('should create correct negation map', () => {
const scale = new QualitativeScale([0, 0.25, 0.5, 0.75, 1], 'test');
assert.strictEqual(scale.negate(0), 1);
assert.strictEqual(scale.negate(1), 0);
assert.strictEqual(scale.negate(0.25), 0.75);
assert.strictEqual(scale.negate(0.5), 0.5);
assert.strictEqual(scale.negate(0.75), 0.25);
});
test('should perform min/max operations correctly', () => {
const scale = new QualitativeScale([0, 0.25, 0.5, 0.75, 1], 'test');
assert.strictEqual(scale.min(0.25, 0.75), 0.25);
assert.strictEqual(scale.max(0.25, 0.75), 0.75);
assert.strictEqual(scale.minAll([0.25, 0.5, 0.75]), 0.25);
assert.strictEqual(scale.maxAll([0.25, 0.5, 0.75]), 0.75);
});
test('should compare values correctly', () => {
const scale = new QualitativeScale([0, 0.25, 0.5, 0.75, 1], 'test');
assert.strictEqual(scale.compare(0.25, 0.75), -1);
assert.strictEqual(scale.compare(0.75, 0.25), 1);
assert.strictEqual(scale.compare(0.5, 0.5), 0);
});
test('should validate values are in scale', () => {
const scale = new QualitativeScale([0, 0.25, 0.5, 0.75, 1], 'test');
assert.strictEqual(scale.contains(0.5), true);
assert.strictEqual(scale.contains(0.3), false);
});
test('should create common scales correctly', () => {
const binary = QualitativeScale.binary();
assert.deepStrictEqual(binary.values, [0, 1]);
const ternary = QualitativeScale.ternary();
assert.deepStrictEqual(ternary.values, [0, 0.5, 1]);
const fivePoint = QualitativeScale.fivePoint();
assert.deepStrictEqual(fivePoint.values, [0, 0.25, 0.5, 0.75, 1]);
});
});
describe('QualitativeCapacity', () => {
test('should create capacity with correct properties', () => {
const stateSpace = ['s1', 's2', 's3'];
const scale = new QualitativeScale([0, 0.5, 1], 'test');
// Create a QMT with some focal sets
const qmt = new Map();
qmt.set(new Set(['s1']), 0.5);
qmt.set(new Set(['s1', 's2']), 1);
qmt.set(new Set(['s1', 's2', 's3']), 1);
const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
assert.deepStrictEqual(capacity.stateSpace, ['s1', 's2', 's3']);
assert.strictEqual(capacity.scale, scale);
assert.strictEqual(capacity.getFocalSets().length, 3);
});
test('should compute capacity values correctly', () => {
const stateSpace = ['s1', 's2', 's3'];
const scale = new QualitativeScale([0, 0.5, 1], 'test');
const qmt = new Map();
qmt.set(new Set(['s1']), 0.5);
qmt.set(new Set(['s1', 's2']), 1);
qmt.set(new Set(['s1', 's2', 's3']), 1);
const capacity = new QualitativeCapacity(stateSpace, scale, qmt);
assert.strictEqual(capacity.getCapacity(['s1']), 0.5);
assert.strictEqual(capacity.getCapacity(['s1', 's2']), 1);
assert.strictEqual(capacity.getCapacity(['s2']), 0); // Not a focal set
assert.strictEqual(capacity.getCapacity(['s1', 's2', 's3']), 1);
});
test('should identify special capacity types', () => {
const stateSpace = ['s1', 's2'];
const scale = QualitativeScale.binary();
// Test possibility measure (all focal sets are singletons)
const possibilityQMT = new Map();
possibilityQMT.set(new Set(['s1']), 1);
possibilityQMT.set(new Set(['s2']), 0.5);
const possibilityCapacity = new QualitativeCapacity(stateSpace, scale, possibilityQMT);
assert.strictEqual(possibilityCapacity.isPossibilityMeasure(), true);
assert.strictEqual(possibilityCapacity.isNecessityMeasure(), false);
// Test necessity measure (focal sets form a nested chain)
const necessityQMT = new Map();
necessityQMT.set(new Set(['s1']), 0.5);
necessityQMT.set(new Set(['s1', 's2']), 1);
const necessityCapacity = new QualitativeCapacity(stateSpace, scale, necessityQMT);
assert.strictEqual(necessityCapacity.isPossibilityMeasure(), false);
assert.strictEqual(necessityCapacity.isNecessityMeasure(), true);
});
test('should create simple support capacities', () => {
const stateSpace = ['s1', 's2', 's3'];
const scale = QualitativeScale.binary();
const ssc = QualitativeCapacity.createSimpleSupport(stateSpace, ['s1'], 1, scale);
assert.strictEqual(ssc.getCapacity(['s1']), 1);
assert.strictEqual(ssc.getCapacity(['s1', 's2']), 1);
assert.strictEqual(ssc.getCapacity(['s2']), 0);
assert.strictEqual(ssc.isNecessityMeasure(), true);
});
});
describe('QualitativeFusion', () => {
test('should perform normalized conjunctive fusion', () => {
const stateSpace = ['s1', 's2'];
const scale = QualitativeScale.binary();
const capacity1 = QualitativeCapacity.createSimpleSupport(stateSpace, ['s1'], 1, scale);
const capacity2 = QualitativeCapacity.createSimpleSupport(stateSpace, ['s2'], 1, scale);
const fused = QualitativeFusion.normalizedConjunctive([capacity1, capacity2]);
assert.deepStrictEqual(fused.stateSpace, stateSpace);
assert.strictEqual(fused.scale, scale);
assert.strictEqual(fused.getCapacity(['s1', 's2']), 1); // Full set should have top value
});
test('should perform disjunctive fusion', () => {
const stateSpace = ['s1', 's2'];
const scale = QualitativeScale.binary();
const capacity1 = QualitativeCapacity.createSimpleSupport(stateSpace, ['s1'], 1, scale);
const capacity2 = QualitativeCapacity.createSimpleSupport(stateSpace, ['s2'], 1, scale);
const result = QualitativeFusion.disjunctive(capacity1, capacity2);
assert.deepStrictEqual(result.stateSpace, stateSpace);
assert.strictEqual(result.scale, scale);
assert.strictEqual(result.getCapacity(['s1', 's2']), 1); // min(1, 1)
});
test('should compute Sugeno integral', () => {
const stateSpace = ['s1', 's2'];
const scale = QualitativeScale.ternary();
const capacity = QualitativeCapacity.createSimpleSupport(stateSpace, ['s1'], 1, scale);
const decisionFunction = { 's1': 0.5, 's2': 1 };
const sugenoValue = QualitativeFusion.sugenoIntegral(capacity, decisionFunction);
// Should be a value in the scale
assert.strictEqual(scale.contains(sugenoValue), true);
assert.ok(sugenoValue >= 0);
assert.ok(sugenoValue <= 1);
});
});
describe('OWAQualitativeFusion', () => {
test('should perform qualitative OWA fusion', () => {
const values = [0, 0.5, 1]; // Use values that are in the ternary scale
const weights = [0, 0.5, 1]; // Use weights that are in the ternary scale
const scale = QualitativeScale.ternary();
const result = OWAQualitativeFusion.fuseWithMeta(values, weights, weights, 'max', scale);
// The result should be a valid value in the scale
assert.ok(scale.contains(result.value));
assert.ok(result.meta);
});
test('should generate OWA weights correctly', () => {
const scale = QualitativeScale.ternary();
const maxWeights = getOWAQualitativeWeights('max', 3, null, scale);
const minWeights = getOWAQualitativeWeights('min', 3, null, scale);
assert.strictEqual(maxWeights[0], 1); // Top weight on first position
assert.strictEqual(maxWeights[1], 0); // Bottom weight on others
assert.strictEqual(maxWeights[2], 0);
assert.strictEqual(minWeights[0], 0); // Bottom weight on first positions
assert.strictEqual(minWeights[1], 0);
assert.strictEqual(minWeights[2], 1); // Top weight on last position
});
});
describe('Integration Tests', () => {
test('should work with default qualitative scale', () => {
const stateSpace = ['s1', 's2'];
const capacity = QualitativeCapacity.createSimpleSupport(stateSpace, ['s1'], 1, DEFAULT_QUALITATIVE_SCALE);
assert.strictEqual(capacity.scale, DEFAULT_QUALITATIVE_SCALE);
assert.strictEqual(capacity.getCapacity(['s1']), 1);
});
test('should perform end-to-end fusion workflow', () => {
const stateSpace = ['s1', 's2'];
const scale = QualitativeScale.binary();
// Create two simple support capacities
const capacity1 = QualitativeCapacity.createSimpleSupport(stateSpace, ['s1'], 1, scale);
const capacity2 = QualitativeCapacity.createSimpleSupport(stateSpace, ['s2'], 1, scale);
// Fuse them using normalized conjunctive rule
const fused = QualitativeFusion.normalizedConjunctive([capacity1, capacity2]);
// Verify the result
assert.deepStrictEqual(fused.stateSpace, stateSpace);
assert.strictEqual(fused.scale, scale);
assert.strictEqual(fused.getCapacity(['s1', 's2']), 1); // Full set should have top value
});
test('should handle edge cases gracefully', () => {
const stateSpace = ['s1'];
const scale = QualitativeScale.binary();
// Test with single state
const capacity = QualitativeCapacity.createSimpleSupport(stateSpace, ['s1'], 1, scale);
assert.strictEqual(capacity.getCapacity(['s1']), 1);
// Test with empty subset
assert.strictEqual(capacity.getCapacity([]), 0);
});
});