File size: 7,834 Bytes
119e586 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | %% SKC-LISP: Layered Truth Maintenance System (LTMS)
%% Knowledge layer: Prolog symbolic reasoning engine
%% Author: Ahmad Parr (ahmedparr93@gmail.com)
%% Integration: Snapkitty LISP Bridge knowledge engine
:- dynamic fact/5. % fact(Value, Source, Timestamp, Confidence, Priority)
:- dynamic rule/4. % rule(Head, Body, Module, Priority)
:- dynamic concept/2. % concept(Name, Senses)
:- dynamic sense/4. % sense(Concept, Gloss, ContextPred, Confidence)
:- dynamic belief_base/1. % belief_base(Timestamp) for history
:- dynamic module_stats/3. % module_stats(Module, RuleCount, LastUpdated)
%% ============================================================================
%% 1. CONFLICT RESOLUTION
%% ============================================================================
%% When multiple facts claim the same value, pick the winner by:
%% Priority > Confidence > Source recency
resolve_conflict(Value, Winner) :-
findall(f(Value,S,T,C,P), fact(Value,S,T,C,P), Candidates),
(Candidates = []
-> fail
; predsort(compare_facts, Candidates, Sorted),
Sorted = [Winner|_]).
%% Comparison: higher priority wins, then higher confidence
compare_facts(Order, f(_,_,_,C1,P1), f(_,_,_,C2,P2)) :-
( P1 > P2 -> Order = (<)
; P1 < P2 -> Order = (>)
; C1 > C2 -> Order = (<)
; C1 < C2 -> Order = (>)
; Order = (=) ).
%% Get the winning value
get_belief(Value, WinningFact) :-
resolve_conflict(Value, WinningFact).
%% ============================================================================
%% 2. OUTDATED DETECTION
%% ============================================================================
%% Exponential decay: confidence decays over time
%% Decay function: Conf(t) = Conf(0) * exp(-0.0001 * age_in_ms)
is_outdated(fact(_,_,Created,Conf,_), Now) :-
Decay is Conf * exp(-0.0001 * (Now - Created)),
Decay < 0.15.
prune_outdated_facts(Now) :-
findall(f(V,S,T,C,P), fact(V,S,T,C,P), AllFacts),
forall(member(F, AllFacts),
(is_outdated(F, Now) -> retract(F) ; true)).
%% Half-life: time for confidence to drop to 50%
compute_half_life(HalfLife) :-
HalfLife is log(2.0) / 0.0001. % ~6931 milliseconds = 6.9 seconds
%% ============================================================================
%% 3. AMBIGUOUS CONCEPTS
%% ============================================================================
%% Concepts have multiple senses, each with a context predicate
register_concept(Name, SenseGlosses) :-
findall(sense(Name, Gloss, _, 1.0), member(Gloss, SenseGlosses), Senses),
assertz(concept(Name, Senses)).
disambiguate(Concept, Context, Sense) :-
concept(Concept, Senses),
member(sense(Concept, Gloss, Pred, Conf), Senses),
(var(Pred) ; call(Pred, Context)),
Sense = sense(Concept, Gloss, Pred, Conf).
%% Pick best sense by confidence (or first if all equal)
best_sense(Concept, Context, BestSense) :-
findall(Sense, disambiguate(Concept, Context, Sense), Candidates),
(Candidates = []
-> fail
; sort(Candidates, [BestSense|_])).
%% ============================================================================
%% 4. MAINTAINABILITY GUARD
%% ============================================================================
%% Hard limit: no module can have > 80 rules
%% Prevents knowledge explosion and maintains readable rule sets
assert_rule(Head, Body, Module, Priority) :-
findall(_, rule(_,_,Module,_), Rules),
length(Rules, N),
(N >= 80
-> throw(error(module_overflow,
context(assert_rule/4,
"Module " + Module + " has reached rule limit")))
; assertz(rule(Head, Body, Module, Priority)),
update_module_stats(Module)).
update_module_stats(Module) :-
(retract(module_stats(Module, _, _)) ; true),
findall(_, rule(_,_,Module,_), Rules),
length(Rules, Count),
get_time(Now),
assertz(module_stats(Module, Count, Now)).
%% Get module health (rules / max_rules)
module_complexity(Module, Percentage) :-
module_stats(Module, Count, _),
Percentage is (Count / 80.0) * 100.
%% Suggest refactoring when > 70% full
suggest_refactor(Module) :-
module_complexity(Module, P),
P > 70.0.
%% ============================================================================
%% 5. HYBRID / NON-RULE KNOWLEDGE
%% ============================================================================
%% Fallback to embeddings when symbolic reasoning fails
hybrid_prove(Goal, Result, Confidence) :-
( prove_symbolic(Goal, Result)
-> Confidence = 1.0
; embedding_retrieve(Goal, Result, Confidence)
).
prove_symbolic(Goal, Result) :-
clause(Goal, Body),
call(Body),
Result = Goal.
%% Stub for embedding retrieval (connects to vector DB)
embedding_retrieve(Goal, Result, Confidence) :-
% In production: query Qdrant/WORM ledger for similar embeddings
% For now: fail gracefully
fail.
%% ============================================================================
%% ASSERTION & QUERY API
%% ============================================================================
%% Assert a new fact
assert_fact(Value, Source, Confidence, Priority) :-
get_time(Now),
Timestamp is floor(Now * 1000), % milliseconds
assertz(fact(Value, Source, Timestamp, Confidence, Priority)).
%% Query belief about a value (returns winning fact + confidence)
query(Value, Confidence) :-
resolve_conflict(Value, f(Value, _, _, Confidence, _)).
%% All known senses of a concept
all_senses(Concept, AllSenses) :-
concept(Concept, AllSenses).
%% Concept subsumption: is Specific a kind of General?
is_a(Specific, General) :-
fact(is_a(Specific, General), _, _, _, _).
%% ============================================================================
%% DEBUGGING & INSPECTION
%% ============================================================================
%% List all facts
list_facts :-
findall(f(V,S,T,C,P), fact(V,S,T,C,P), Facts),
forall(member(F, Facts), writeln(F)).
%% List all rules by module
list_rules_in_module(Module) :-
findall(rule(H,B,M,Pr), rule(H,B,Module,Pr), Rules),
forall(member(R, Rules), writeln(R)).
%% List all concepts
list_concepts :-
findall(C, concept(C, _), Concepts),
forall(member(C, Concepts), writeln(C)).
%% Module report
module_report :-
findall(m(M,Count,Updated), module_stats(M,Count,Updated), Stats),
forall(member(m(Mod,Count,_), Stats),
format('~w: ~w/80 rules~n', [Mod, Count])).
%% ============================================================================
%% TESTS
%% ============================================================================
:- initialization(run_ltms_tests).
run_ltms_tests :-
writeln('=== LTMS Tests ==='),
% Test 1: Conflict resolution
writeln('Test 1: Conflict resolution'),
assert_fact(color(car), source_a, 0.8, 10),
assert_fact(color(car), source_b, 0.9, 5),
resolve_conflict(color(car), Winner),
writeln(Winner), nl,
% Test 2: Outdated detection
writeln('Test 2: Outdated detection'),
get_time(Now),
OldTime is (Now * 1000) - 10000,
(is_outdated(fact(old_value, old_source, OldTime, 0.5, 1), Now * 1000)
-> writeln('✓ Old fact marked as outdated')
; writeln('✗ Old fact not detected')), nl,
% Test 3: Module limit
writeln('Test 3: Module complexity guard'),
(module_complexity(main, P), format('Main module: ~1f% full~n', [P])
; writeln('Main module not yet used')), nl,
writeln('=== LTMS Tests Complete ===').
|