Files
el/lang/runtime/engram_reason.h
T
bigmerge 01826421c4 seam: implement decorated-fn boundary auto-emit; prove on clone
Will waived diff review -> build it for real. Add engram_boundary_beat() to the
runtime (afferent counter++ + engram_chrono_tick + engram_strengthen(self-anchor)
+ dharma_emit) and two act-stats counters (aff_boundary_ops, dharma_emits).
codegen cg_fn injects ONE engram_boundary_beat(op) at the entry of every
@manager/@accessor fn (fn_has_decorator, so it fires under @route @manager too) —
a decorated op self-reports with ZERO hand-written instrumentation. Rebuilt elc
self-host + the cognition engram in the worktree; ran it as the clone daemon on
:8900. Proof (/api/boundary-proof, @manager, empty body, 5x): aff_boundary_ops
0->5, dharma_emits 0->5, self activation_count 1510->1513, chrono stamp advanced.
Brought in feat/cognitive-architecture engram runtime+server for the build.
strengthen = activation bump (not content/edge write) -> identity protection
intact. Live :8742 untouched; no push, no cutover.
2026-08-14 21:20:18 -05:00

162 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* engram_reason.h — the REASONING layer: compositions over the §5 geometry
* OPERATORS (engram_geometry.h). Where the operators are a relational ALGEBRA over
* neighborhood descriptors, these are reasoning MODES built by CHAINING that algebra:
*
* ANALOGY A:B :: C:? — learn the A→B transform (Procrustes), apply to C.
* INDUCTION {E_i} → rule — pool example geometries; a generalizing structure
* + a membership test.
* ABDUCTION x → best H — the structure whose geometry best PLACES an
* observation in-distribution (inverse of prediction).
* CAUSAL x ? y | Z, t — separate mere overlap (correlation) from directed
* influence (temporal precedence + association that
* SURVIVES controlling for confounders via subtract).
* PLANNING start → goal — a trajectory (sequence of neighborhoods) through the
* manifold: shortest path over geo-distance edges.
*
* PURE + READ-ONLY (stdlib + libm only): every function consumes GeoDescriptor(s)
* (+ a few scalars / timestamps) and NEVER touches the store, index, or activation.
* All geometry is delegated to the engram_geo_* primitives; this file only composes.
*
* FRAME CONTRACT (inherited): descriptors passed together MUST share emb `dim` and
* `global_mean` frame — exactly the §5 operator contract. A function returns <0 on
* a dim/frame mismatch or bad argument.
*/
#ifndef ENGRAM_REASON_H
#define ENGRAM_REASON_H
#include <stdint.h>
#include "engram_geometry.h"
/* ═══════════════════════════════════════════════════════════════════════════
* SHARED PRIMITIVE — point-to-manifold FIT. How well does a single point x sit
* inside a neighborhood's ellipsoid? Splits the residual (x centroid) into:
* - the IN-SUBSPACE part, scaled by each axis extent → a Mahalanobis distance
* (how many "radii" out along the modeled directions), and
* - the ORTHOGONAL part outside the retained axes → energy the model does not
* explain at all (charged at the extent floor).
* This is the common engine under INDUCTION's membership test and ABDUCTION's
* explanation ranking. ext_floor (>0) guards zero-extent axes / the null model.
* ═══════════════════════════════════════════════════════════════════════════ */
typedef struct {
double mahalanobis; /* sqrt( Σ_k ((a_k·(xc)) / max(ext_k,floor))² ) */
double ortho_residual; /* ‖(xc) projected off the retained axes‖ (raw L2) */
double distance; /* sqrt( maha² + (ortho_residual/floor)² ) — full fit */
double score; /* 1 / (1 + distance²) ∈ (0,1] (1 = dead-center) */
} GeoFit;
int engram_reason_point_fit(const GeoDescriptor* g, const float* x,
double ext_floor, GeoFit* out);
/* ═══════════════════════════════════════════════════════════════════════════
* ANALOGY — "A:B :: C:?". Learn the transform that carries A to B (orthogonal
* Procrustes rotation R between their principal frames + the residual translation),
* apply it to C, and return the mapped point + the nearest candidate neighborhood.
* Composes: engram_geo_analogy (R) + engram_geo_analogy_apply + engram_geo_distance.
* ═══════════════════════════════════════════════════════════════════════════ */
typedef struct {
int dim;
float* mapped_point; /* predicted D location = R·c_C + (c_B R·c_A) (owned)*/
double analogy_residual;/* Procrustes ‖AB R‖_F — frame-alignment quality */
int best; /* index of nearest candidate to mapped_point, or 1 */
double best_distance; /* centroid L2 from mapped_point to the winner */
int n_candidates;
double* distances; /* centroid L2 mapped_point→candidate[i] (owned)*/
} GeoAnalogyResult;
/* candidates may be NULL/0 (then best=1 and only mapped_point is filled). */
int engram_reason_analogy(const GeoDescriptor* A, const GeoDescriptor* B,
const GeoDescriptor* C,
const GeoDescriptor* const* candidates, int n_candidates,
GeoAnalogyResult* out);
void engram_reason_analogy_free(GeoAnalogyResult* r);
/* ═══════════════════════════════════════════════════════════════════════════
* INDUCTION — from a SET of example neighborhoods to the generalizing structure.
* Pools the examples (law-of-total-variance via engram_geo_combine, folded left to
* right) into a single "rule" descriptor whose top principal axes are the directions
* CONSISTENTLY present across the examples (the shared subspace surfaces as the
* dominant pooled axes; idiosyncratic per-example directions fall to the tail).
* The rule carries a membership test (point-to-manifold fit against the pool).
* ═══════════════════════════════════════════════════════════════════════════ */
typedef struct {
GeoDescriptor* rule; /* induced generalizing geometry (owned; geo_free) */
double ext_floor; /* extent floor used by the membership test */
int n_examples;/* how many examples were pooled */
} GeoInduction;
/* top_axes<=0 → 8. ext_floor<=0 → derived from the pooled radius. */
int engram_reason_induce(const GeoDescriptor* const* examples, int n_examples,
int top_axes, double ext_floor, GeoInduction* out);
/* Membership of a point in the induced rule ∈ (0,1] (the fit score). <0 on error. */
double engram_reason_membership(const GeoInduction* ind, const float* x);
void engram_reason_induction_free(GeoInduction* out);
/* ═══════════════════════════════════════════════════════════════════════════
* ABDUCTION — inference to the best explanation. Given an observation POINT, rank a
* set of candidate structures by how well each PLACES the observation in-distribution
* (min point-to-manifold distance = the structure that, if assumed, best accounts for
* the observation). The inverse of prediction.
* ═══════════════════════════════════════════════════════════════════════════ */
typedef struct {
int best; /* index of best-explaining hypothesis, or 1 */
double best_score;
int n;
double* scores; /* fit score per hypothesis (higher = better) (owned)*/
double* distances; /* explanation distance per hypothesis (owned)*/
int* rank; /* hypothesis indices sorted best→worst (owned)*/
} GeoAbduction;
int engram_reason_abduce(const float* obs, int dim,
const GeoDescriptor* const* hypotheses, int n,
double ext_floor, GeoAbduction* out);
void engram_reason_abduction_free(GeoAbduction* out);
/* ═══════════════════════════════════════════════════════════════════════════
* CAUSAL — correlation vs causation. Over two variables' geometries (+ candidate
* confounders + temporal order), distinguish:
* - mere co-occurrence / overlap (correlation), from
* - directed influence: association that (a) SURVIVES controlling for confounders
* (subtract each Z's subspace from both centroids, re-measure) and (b) is oriented
* by temporal PRECEDENCE.
* Composes: centroid cosine (correlation) + engram_geo_subtract (control) + timestamps.
* ═══════════════════════════════════════════════════════════════════════════ */
typedef enum {
GEO_CAUSAL_NONE = 0, /* no meaningful association */
GEO_CAUSAL_DIRECTED = 1, /* survives control + temporally ordered → cause→eff */
GEO_CAUSAL_CONFOUNDED = 2 /* correlated but association dies under control */
} GeoCausalVerdict;
typedef struct {
double assoc_raw; /* |cos(c_x,c_y)| — the raw correlation */
double assoc_controlled; /* |cos| of residual centroids after control */
int temporal_dir; /* +1 x→y, 1 y→x, 0 tie/unknown */
GeoCausalVerdict verdict;
int confounded; /* 1 iff verdict==CONFOUNDED (the flag) */
double strength; /* directed influence estimate ∈[0,1] (0 else)*/
} GeoCausal;
/* confounders may be NULL/0. t_x,t_y are comparable timestamps (any monotone unit);
* pass equal values for "unknown order". drop_frac∈(0,1): a controlled association
* below (1drop_frac)·assoc_raw AND below an absolute floor ⇒ CONFOUNDED. */
int engram_reason_causal(const GeoDescriptor* x, const GeoDescriptor* y,
const GeoDescriptor* const* confounders, int n_conf,
int64_t t_x, int64_t t_y,
double drop_frac, GeoCausal* out);
/* ═══════════════════════════════════════════════════════════════════════════
* PLANNING — trajectory construction. Given a set of neighborhoods (manifold nodes),
* a start and a goal, build a PATH (sequence of intermediate neighborhoods) by
* shortest path over the graph whose edges connect neighborhoods within
* neighbor_radius, weighted by geo-distance. Long straight jumps are not edges, so
* the path follows the manifold's curvature through intermediates (a discrete geodesic).
* Composes: engram_geo_distance (edge weights) + Dijkstra.
* ═══════════════════════════════════════════════════════════════════════════ */
typedef struct {
int* path; /* node indices start..goal (owned) */
int path_len;
double total_cost; /* summed centroid-distance edge weights along path */
int reached; /* 1 if goal reachable within neighbor_radius graph */
} GeoPlan;
/* neighbor_radius>0: max centroid distance for two neighborhoods to be adjacent.
* Use "wasserstein"!=0 to weight edges by Wasserstein-2 instead of centroid L2. */
int engram_reason_plan(const GeoDescriptor* const* nodes, int n,
int start, int goal, double neighbor_radius,
int use_wasserstein, GeoPlan* out);
void engram_reason_plan_free(GeoPlan* out);
#endif /* ENGRAM_REASON_H */