Compare commits
2 Commits
mimo/code/
...
burn/20260
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77e6d67365 | ||
|
|
5295d0b0eb |
13
app.js
13
app.js
@@ -108,8 +108,8 @@ class SymbolicEngine {
|
||||
}
|
||||
}
|
||||
|
||||
addRule(condition, action, description) {
|
||||
this.rules.push({ condition, action, description });
|
||||
addRule(condition, action, description, triggerFacts = []) {
|
||||
this.rules.push({ condition, action, description, triggerFacts });
|
||||
}
|
||||
|
||||
reason() {
|
||||
@@ -404,6 +404,7 @@ class NeuroSymbolicBridge {
|
||||
}
|
||||
|
||||
perceive(rawState) {
|
||||
Object.entries(rawState).forEach(([key, value]) => this.engine.addFact(key, value));
|
||||
const concepts = [];
|
||||
if (rawState.stability < 0.4 && rawState.energy > 60) concepts.push('UNSTABLE_OSCILLATION');
|
||||
if (rawState.energy < 30 && rawState.activePortals > 2) concepts.push('CRITICAL_DRAIN_PATTERN');
|
||||
@@ -574,7 +575,6 @@ class PSELayer {
|
||||
constructor() {
|
||||
this.worker = new Worker('gofai_worker.js');
|
||||
this.worker.onmessage = (e) => this.handleWorkerMessage(e);
|
||||
this.pendingRequests = new Map();
|
||||
}
|
||||
|
||||
handleWorkerMessage(e) {
|
||||
@@ -621,6 +621,9 @@ function setupGOFAI() {
|
||||
// Setup FSM
|
||||
agentFSMs['timmy'] = new AgentFSM('timmy', 'IDLE');
|
||||
agentFSMs['timmy'].addTransition('IDLE', 'ANALYZING', (facts) => facts.get('activePortals') > 0);
|
||||
|
||||
symbolicEngine.addRule((facts) => facts.get('UNSTABLE_OSCILLATION'), () => 'STABILIZE MATRIX', 'Unstable oscillation demands stabilization', ['UNSTABLE_OSCILLATION']);
|
||||
symbolicEngine.addRule((facts) => facts.get('CRITICAL_DRAIN_PATTERN'), () => 'SHED PORTAL LOAD', 'Critical drain demands portal shedding', ['CRITICAL_DRAIN_PATTERN']);
|
||||
|
||||
// Setup Planner
|
||||
symbolicPlanner.addAction('Stabilize Matrix', { energy: 50 }, { stability: 1.0 });
|
||||
@@ -631,11 +634,13 @@ function updateGOFAI(delta, elapsed) {
|
||||
|
||||
// Simulate perception
|
||||
neuroBridge.perceive({ stability: 0.3, energy: 80, activePortals: 1 });
|
||||
agentFSMs['timmy']?.update(symbolicEngine.facts);
|
||||
|
||||
// Run reasoning
|
||||
if (Math.floor(elapsed * 2) > Math.floor((elapsed - delta) * 2)) {
|
||||
symbolicEngine.reason();
|
||||
pseLayer.offloadReasoning(Array.from(symbolicEngine.facts.entries()), symbolicEngine.rules.map(r => ({ description: r.description })));
|
||||
pseLayer.offloadReasoning(Array.from(symbolicEngine.facts.entries()), symbolicEngine.rules.map((r) => ({ description: r.description, triggerFacts: r.triggerFacts })));
|
||||
pseLayer.offloadPlanning(Object.fromEntries(symbolicEngine.facts), { stability: 1.0 }, symbolicPlanner.actions);
|
||||
document.getElementById("pse-task-count").innerText = parseInt(document.getElementById("pse-task-count").innerText) + 1;
|
||||
metaLayer.reflect();
|
||||
|
||||
|
||||
@@ -1,30 +1,35 @@
|
||||
const heuristic = (state, goal) => Object.keys(goal).reduce((h, key) => h + (state[key] === goal[key] ? 0 : Math.abs((state[key] || 0) - (goal[key] || 0))), 0), preconditionsMet = (state, preconditions = {}) => Object.entries(preconditions).every(([key, value]) => (typeof value === 'number' ? (state[key] || 0) >= value : state[key] === value));
|
||||
const findPlan = (initialState, goalState, actions = []) => {
|
||||
const openSet = [{ state: initialState, plan: [], g: 0, h: heuristic(initialState, goalState) }];
|
||||
const visited = new Map([[JSON.stringify(initialState), 0]]);
|
||||
while (openSet.length) {
|
||||
openSet.sort((a, b) => (a.g + a.h) - (b.g + b.h));
|
||||
const { state, plan, g } = openSet.shift();
|
||||
if (heuristic(state, goalState) === 0) return plan;
|
||||
actions.forEach((action) => {
|
||||
if (!preconditionsMet(state, action.preconditions)) return;
|
||||
const nextState = { ...state, ...(action.effects || {}) };
|
||||
const key = JSON.stringify(nextState);
|
||||
const nextG = g + 1;
|
||||
if (!visited.has(key) || nextG < visited.get(key)) {
|
||||
visited.set(key, nextG);
|
||||
openSet.push({ state: nextState, plan: [...plan, action.name], g: nextG, h: heuristic(nextState, goalState) });
|
||||
}
|
||||
});
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
// ═══ GOFAI PARALLEL WORKER (PSE) ═══
|
||||
self.onmessage = function(e) {
|
||||
const { type, data } = e.data;
|
||||
|
||||
switch(type) {
|
||||
case 'REASON':
|
||||
const { facts, rules } = data;
|
||||
const results = [];
|
||||
// Off-thread rule matching
|
||||
rules.forEach(rule => {
|
||||
// Simulate heavy rule matching
|
||||
if (Math.random() > 0.95) {
|
||||
results.push({ rule: rule.description, outcome: 'OFF-THREAD MATCH' });
|
||||
}
|
||||
});
|
||||
self.postMessage({ type: 'REASON_RESULT', results });
|
||||
break;
|
||||
|
||||
case 'PLAN':
|
||||
const { initialState, goalState, actions } = data;
|
||||
// Off-thread A* search
|
||||
console.log('[PSE] Starting off-thread A* search...');
|
||||
// Simulate planning delay
|
||||
const startTime = performance.now();
|
||||
while(performance.now() - startTime < 50) {} // Artificial load
|
||||
self.postMessage({ type: 'PLAN_RESULT', plan: ['Off-Thread Step 1', 'Off-Thread Step 2'] });
|
||||
break;
|
||||
if (type === 'REASON') {
|
||||
const factMap = new Map(data.facts || []);
|
||||
const results = (data.rules || []).filter((rule) => (rule.triggerFacts || []).every((fact) => factMap.get(fact))).map((rule) => ({ rule: rule.description, outcome: 'OFF-THREAD MATCH' }));
|
||||
self.postMessage({ type: 'REASON_RESULT', results });
|
||||
return;
|
||||
}
|
||||
if (type === 'PLAN') {
|
||||
const plan = findPlan(data.initialState || {}, data.goalState || {}, data.actions || []);
|
||||
self.postMessage({ type: 'PLAN_RESULT', plan });
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user