Skip to main content

CoherenceField

Struct CoherenceField 

Source
pub struct CoherenceField<V: SensorVocabulary<N>, const N: usize> { /* private fields */ }
Expand description

The coherence field: a map of context → CoherenceAccumulator.

Generic over any sensor vocabulary V implementing SensorVocabulary<N>. Maintains at most [MAX_CONTEXTS] entries with LRU eviction.

Patent Claims 6–7, 13.

Implementations§

Source§

impl<V: SensorVocabulary<N>, const N: usize> CoherenceField<V, N>

Source

pub fn new() -> Self

Construct a fresh field with no accumulated coherence.

Examples found in repository?
examples/mbot2.rs (line 82)
60fn main() {
61    println!("CCF mBot2 — Emergent Behaviour Simulation");
62    println!("==========================================\n");
63
64    // ── Personality ──────────────────────────────────────────────────────────
65    //
66    // These three parameters shape how the robot accumulates and loses trust.
67    // They are analogous to temperament — the same events produce different
68    // magnitudes of response depending on personality.
69    //
70    // This configuration: eager to engage (high curiosity), not easily startled
71    // (low sensitivity), recovers quickly from disruption (high recovery).
72    let personality = Personality {
73        curiosity_drive:     0.8,
74        startle_sensitivity: 0.3,
75        recovery_speed:      0.7,
76    };
77
78    // ── Trust field ──────────────────────────────────────────────────────────
79    //
80    // The field maintains an independent trust state per sensory context.
81    // It starts empty — the robot has no experience yet.
82    let mut field: CoherenceField<MbotSensors, 6> = CoherenceField::new();
83
84    // ── Phase space ──────────────────────────────────────────────────────────
85    //
86    // Configurable thresholds for the four-quadrant classifier.
87    // The default values (enter 0.65 / exit 0.55 on coherence) are a good
88    // starting point. Adjust to tune how quickly the robot "warms up".
89    let ps = PhaseSpace::new();
90    let mut phase = SocialPhase::ShyObserver;
91
92    // ── Two sensor contexts ──────────────────────────────────────────────────
93    //
94    // The living room: bright, quiet, a familiar person nearby.
95    // The basement:    dark, moderate noise, no one present.
96    //
97    // These are entirely independent trust contexts. Experience in one
98    // does not transfer to the other.
99    let living_room = ContextKey::new(MbotSensors {
100        brightness:  BrightnessBand::Bright,
101        noise:       NoiseBand::Quiet,
102        presence:    PresenceSignature::Close,
103        motion:      MotionContext::Static,
104        orientation: Orientation::Upright,
105        time_period: TimePeriod::Day,
106    });
107
108    let basement = ContextKey::new(MbotSensors {
109        brightness:  BrightnessBand::Dark,
110        noise:       NoiseBand::Moderate,
111        presence:    PresenceSignature::Absent,
112        motion:      MotionContext::Static,
113        orientation: Orientation::Upright,
114        time_period: TimePeriod::Evening,
115    });
116
117    // ── Phase 1: Build trust in the living room ───────────────────────────────
118    //
119    // Simulate 80 ticks of positive interaction in the living room.
120    // The person is present, the environment is calm, interactions go well.
121    println!("Phase 1: 80 positive interactions in the living room");
122    println!("------------------------------------------------------");
123
124    for tick in 0u64..80 {
125        // alone=false: the person is present; the interaction is social
126        field.positive_interaction(&living_room, &personality, tick, false);
127
128        // instant: the current sensor-level signal (1.0 = fully coherent reading)
129        // In a real system this comes from your homeostasis / sensor fusion layer.
130        let instant: f32 = 0.9;
131        let coherence = field.effective_coherence(instant, &living_room);
132        let tension: f32 = 0.1; // calm environment
133        phase = SocialPhase::classify(coherence, tension, phase, &ps);
134
135        if tick % 20 == 19 {
136            let led = phase.led_tint();
137            println!(
138                "  tick {:>3} | coherence {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
139                tick + 1,
140                coherence,
141                phase,
142                led[0], led[1], led[2]
143            );
144        }
145    }
146
147    // ── Phase 2: The basement — zero trust, same robot ───────────────────────
148    //
149    // The robot is moved to the basement. It has never been here before.
150    // All the trust it built in the living room is irrelevant in this context.
151    // It starts from zero — exactly as it should.
152    println!("\nPhase 2: Robot moved to the basement (zero prior experience)");
153    println!("--------------------------------------------------------------");
154
155    let basement_coherence = field.effective_coherence(0.9, &basement);
156    let basement_tension: f32 = 0.5; // unfamiliar, slightly unnerving
157    phase = SocialPhase::classify(basement_coherence, basement_tension, phase, &ps);
158
159    let led = phase.led_tint();
160    println!(
161        "  coherence in basement: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
162        basement_coherence,
163        phase,
164        led[0], led[1], led[2]
165    );
166    println!("  (Trust does not transfer. The robot earned nothing here yet.)");
167
168    // ── Phase 3: A startle event back in the living room ─────────────────────
169    //
170    // The robot returns to the familiar living room. Someone slams a door.
171    // Because the robot has deep trust in this context (earned floor > 0),
172    // the negative event causes a drop — but cannot erase the accumulated history.
173    println!("\nPhase 3: Return to living room — startle event (door slam)");
174    println!("------------------------------------------------------------");
175
176    let before = field.effective_coherence(0.9, &living_room);
177    field.negative_interaction(&living_room, &personality, 81);
178    let after = field.effective_coherence(0.9, &living_room);
179
180    println!("  coherence before startle: {:.2}", before);
181    println!("  coherence after startle:  {:.2}", after);
182    println!(
183        "  drop: {:.2} (earned floor protects against erasure)",
184        before - after
185    );
186
187    let tension: f32 = 0.55; // brief spike from the startle
188    phase = SocialPhase::classify(after, tension, phase, &ps);
189    let led = phase.led_tint();
190    println!(
191        "  phase: {:?} | LED #{:02X}{:02X}{:02X}",
192        phase, led[0], led[1], led[2]
193    );
194
195    // ── Phase 4: Recovery ─────────────────────────────────────────────────────
196    //
197    // A few more positive interactions and the robot recovers. The familiar
198    // environment reasserts itself. This is not scripted — it emerges from the
199    // accumulated trust floor protecting the relationship.
200    println!("\nPhase 4: Recovery — 5 positive interactions");
201    println!("--------------------------------------------");
202
203    for tick in 82u64..87 {
204        field.positive_interaction(&living_room, &personality, tick, false);
205    }
206    let recovered = field.effective_coherence(0.9, &living_room);
207    let tension: f32 = 0.1;
208    phase = SocialPhase::classify(recovered, tension, phase, &ps);
209    let led = phase.led_tint();
210    println!(
211        "  coherence after recovery: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
212        recovered, phase, led[0], led[1], led[2]
213    );
214
215    // ── Summary ───────────────────────────────────────────────────────────────
216    println!("\nSummary");
217    println!("-------");
218    println!(
219        "  Living room trust:  {:.2} ({} interactions)",
220        field.effective_coherence(0.9, &living_room),
221        field.context_interaction_count(&living_room),
222    );
223    println!(
224        "  Basement trust:     {:.2} ({} interactions)",
225        field.effective_coherence(0.9, &basement),
226        field.context_interaction_count(&basement),
227    );
228    println!("\nThe robot knows where it belongs.");
229    println!("No rules. No scripts. Earned.");
230}
Source

pub fn effective_coherence(&self, instant: f32, key: &ContextKey<V, N>) -> f32

Compute effective coherence using the asymmetric gate (CCF-001).

  • Unfamiliar (ctx < 0.3): min(instant, ctx) — earn trust first.
  • Familiar (ctx ≥ 0.3): 0.3 × instant + 0.7 × ctx — history buffers noise.
Examples found in repository?
examples/mbot2.rs (line 131)
60fn main() {
61    println!("CCF mBot2 — Emergent Behaviour Simulation");
62    println!("==========================================\n");
63
64    // ── Personality ──────────────────────────────────────────────────────────
65    //
66    // These three parameters shape how the robot accumulates and loses trust.
67    // They are analogous to temperament — the same events produce different
68    // magnitudes of response depending on personality.
69    //
70    // This configuration: eager to engage (high curiosity), not easily startled
71    // (low sensitivity), recovers quickly from disruption (high recovery).
72    let personality = Personality {
73        curiosity_drive:     0.8,
74        startle_sensitivity: 0.3,
75        recovery_speed:      0.7,
76    };
77
78    // ── Trust field ──────────────────────────────────────────────────────────
79    //
80    // The field maintains an independent trust state per sensory context.
81    // It starts empty — the robot has no experience yet.
82    let mut field: CoherenceField<MbotSensors, 6> = CoherenceField::new();
83
84    // ── Phase space ──────────────────────────────────────────────────────────
85    //
86    // Configurable thresholds for the four-quadrant classifier.
87    // The default values (enter 0.65 / exit 0.55 on coherence) are a good
88    // starting point. Adjust to tune how quickly the robot "warms up".
89    let ps = PhaseSpace::new();
90    let mut phase = SocialPhase::ShyObserver;
91
92    // ── Two sensor contexts ──────────────────────────────────────────────────
93    //
94    // The living room: bright, quiet, a familiar person nearby.
95    // The basement:    dark, moderate noise, no one present.
96    //
97    // These are entirely independent trust contexts. Experience in one
98    // does not transfer to the other.
99    let living_room = ContextKey::new(MbotSensors {
100        brightness:  BrightnessBand::Bright,
101        noise:       NoiseBand::Quiet,
102        presence:    PresenceSignature::Close,
103        motion:      MotionContext::Static,
104        orientation: Orientation::Upright,
105        time_period: TimePeriod::Day,
106    });
107
108    let basement = ContextKey::new(MbotSensors {
109        brightness:  BrightnessBand::Dark,
110        noise:       NoiseBand::Moderate,
111        presence:    PresenceSignature::Absent,
112        motion:      MotionContext::Static,
113        orientation: Orientation::Upright,
114        time_period: TimePeriod::Evening,
115    });
116
117    // ── Phase 1: Build trust in the living room ───────────────────────────────
118    //
119    // Simulate 80 ticks of positive interaction in the living room.
120    // The person is present, the environment is calm, interactions go well.
121    println!("Phase 1: 80 positive interactions in the living room");
122    println!("------------------------------------------------------");
123
124    for tick in 0u64..80 {
125        // alone=false: the person is present; the interaction is social
126        field.positive_interaction(&living_room, &personality, tick, false);
127
128        // instant: the current sensor-level signal (1.0 = fully coherent reading)
129        // In a real system this comes from your homeostasis / sensor fusion layer.
130        let instant: f32 = 0.9;
131        let coherence = field.effective_coherence(instant, &living_room);
132        let tension: f32 = 0.1; // calm environment
133        phase = SocialPhase::classify(coherence, tension, phase, &ps);
134
135        if tick % 20 == 19 {
136            let led = phase.led_tint();
137            println!(
138                "  tick {:>3} | coherence {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
139                tick + 1,
140                coherence,
141                phase,
142                led[0], led[1], led[2]
143            );
144        }
145    }
146
147    // ── Phase 2: The basement — zero trust, same robot ───────────────────────
148    //
149    // The robot is moved to the basement. It has never been here before.
150    // All the trust it built in the living room is irrelevant in this context.
151    // It starts from zero — exactly as it should.
152    println!("\nPhase 2: Robot moved to the basement (zero prior experience)");
153    println!("--------------------------------------------------------------");
154
155    let basement_coherence = field.effective_coherence(0.9, &basement);
156    let basement_tension: f32 = 0.5; // unfamiliar, slightly unnerving
157    phase = SocialPhase::classify(basement_coherence, basement_tension, phase, &ps);
158
159    let led = phase.led_tint();
160    println!(
161        "  coherence in basement: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
162        basement_coherence,
163        phase,
164        led[0], led[1], led[2]
165    );
166    println!("  (Trust does not transfer. The robot earned nothing here yet.)");
167
168    // ── Phase 3: A startle event back in the living room ─────────────────────
169    //
170    // The robot returns to the familiar living room. Someone slams a door.
171    // Because the robot has deep trust in this context (earned floor > 0),
172    // the negative event causes a drop — but cannot erase the accumulated history.
173    println!("\nPhase 3: Return to living room — startle event (door slam)");
174    println!("------------------------------------------------------------");
175
176    let before = field.effective_coherence(0.9, &living_room);
177    field.negative_interaction(&living_room, &personality, 81);
178    let after = field.effective_coherence(0.9, &living_room);
179
180    println!("  coherence before startle: {:.2}", before);
181    println!("  coherence after startle:  {:.2}", after);
182    println!(
183        "  drop: {:.2} (earned floor protects against erasure)",
184        before - after
185    );
186
187    let tension: f32 = 0.55; // brief spike from the startle
188    phase = SocialPhase::classify(after, tension, phase, &ps);
189    let led = phase.led_tint();
190    println!(
191        "  phase: {:?} | LED #{:02X}{:02X}{:02X}",
192        phase, led[0], led[1], led[2]
193    );
194
195    // ── Phase 4: Recovery ─────────────────────────────────────────────────────
196    //
197    // A few more positive interactions and the robot recovers. The familiar
198    // environment reasserts itself. This is not scripted — it emerges from the
199    // accumulated trust floor protecting the relationship.
200    println!("\nPhase 4: Recovery — 5 positive interactions");
201    println!("--------------------------------------------");
202
203    for tick in 82u64..87 {
204        field.positive_interaction(&living_room, &personality, tick, false);
205    }
206    let recovered = field.effective_coherence(0.9, &living_room);
207    let tension: f32 = 0.1;
208    phase = SocialPhase::classify(recovered, tension, phase, &ps);
209    let led = phase.led_tint();
210    println!(
211        "  coherence after recovery: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
212        recovered, phase, led[0], led[1], led[2]
213    );
214
215    // ── Summary ───────────────────────────────────────────────────────────────
216    println!("\nSummary");
217    println!("-------");
218    println!(
219        "  Living room trust:  {:.2} ({} interactions)",
220        field.effective_coherence(0.9, &living_room),
221        field.context_interaction_count(&living_room),
222    );
223    println!(
224        "  Basement trust:     {:.2} ({} interactions)",
225        field.effective_coherence(0.9, &basement),
226        field.context_interaction_count(&basement),
227    );
228    println!("\nThe robot knows where it belongs.");
229    println!("No rules. No scripts. Earned.");
230}
Source

pub fn positive_interaction( &mut self, key: &ContextKey<V, N>, personality: &Personality, tick: u64, alone: bool, )

Record a positive interaction for a context, modulated by personality.

Creates the accumulator at the personality baseline if the context is unseen.

Examples found in repository?
examples/mbot2.rs (line 126)
60fn main() {
61    println!("CCF mBot2 — Emergent Behaviour Simulation");
62    println!("==========================================\n");
63
64    // ── Personality ──────────────────────────────────────────────────────────
65    //
66    // These three parameters shape how the robot accumulates and loses trust.
67    // They are analogous to temperament — the same events produce different
68    // magnitudes of response depending on personality.
69    //
70    // This configuration: eager to engage (high curiosity), not easily startled
71    // (low sensitivity), recovers quickly from disruption (high recovery).
72    let personality = Personality {
73        curiosity_drive:     0.8,
74        startle_sensitivity: 0.3,
75        recovery_speed:      0.7,
76    };
77
78    // ── Trust field ──────────────────────────────────────────────────────────
79    //
80    // The field maintains an independent trust state per sensory context.
81    // It starts empty — the robot has no experience yet.
82    let mut field: CoherenceField<MbotSensors, 6> = CoherenceField::new();
83
84    // ── Phase space ──────────────────────────────────────────────────────────
85    //
86    // Configurable thresholds for the four-quadrant classifier.
87    // The default values (enter 0.65 / exit 0.55 on coherence) are a good
88    // starting point. Adjust to tune how quickly the robot "warms up".
89    let ps = PhaseSpace::new();
90    let mut phase = SocialPhase::ShyObserver;
91
92    // ── Two sensor contexts ──────────────────────────────────────────────────
93    //
94    // The living room: bright, quiet, a familiar person nearby.
95    // The basement:    dark, moderate noise, no one present.
96    //
97    // These are entirely independent trust contexts. Experience in one
98    // does not transfer to the other.
99    let living_room = ContextKey::new(MbotSensors {
100        brightness:  BrightnessBand::Bright,
101        noise:       NoiseBand::Quiet,
102        presence:    PresenceSignature::Close,
103        motion:      MotionContext::Static,
104        orientation: Orientation::Upright,
105        time_period: TimePeriod::Day,
106    });
107
108    let basement = ContextKey::new(MbotSensors {
109        brightness:  BrightnessBand::Dark,
110        noise:       NoiseBand::Moderate,
111        presence:    PresenceSignature::Absent,
112        motion:      MotionContext::Static,
113        orientation: Orientation::Upright,
114        time_period: TimePeriod::Evening,
115    });
116
117    // ── Phase 1: Build trust in the living room ───────────────────────────────
118    //
119    // Simulate 80 ticks of positive interaction in the living room.
120    // The person is present, the environment is calm, interactions go well.
121    println!("Phase 1: 80 positive interactions in the living room");
122    println!("------------------------------------------------------");
123
124    for tick in 0u64..80 {
125        // alone=false: the person is present; the interaction is social
126        field.positive_interaction(&living_room, &personality, tick, false);
127
128        // instant: the current sensor-level signal (1.0 = fully coherent reading)
129        // In a real system this comes from your homeostasis / sensor fusion layer.
130        let instant: f32 = 0.9;
131        let coherence = field.effective_coherence(instant, &living_room);
132        let tension: f32 = 0.1; // calm environment
133        phase = SocialPhase::classify(coherence, tension, phase, &ps);
134
135        if tick % 20 == 19 {
136            let led = phase.led_tint();
137            println!(
138                "  tick {:>3} | coherence {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
139                tick + 1,
140                coherence,
141                phase,
142                led[0], led[1], led[2]
143            );
144        }
145    }
146
147    // ── Phase 2: The basement — zero trust, same robot ───────────────────────
148    //
149    // The robot is moved to the basement. It has never been here before.
150    // All the trust it built in the living room is irrelevant in this context.
151    // It starts from zero — exactly as it should.
152    println!("\nPhase 2: Robot moved to the basement (zero prior experience)");
153    println!("--------------------------------------------------------------");
154
155    let basement_coherence = field.effective_coherence(0.9, &basement);
156    let basement_tension: f32 = 0.5; // unfamiliar, slightly unnerving
157    phase = SocialPhase::classify(basement_coherence, basement_tension, phase, &ps);
158
159    let led = phase.led_tint();
160    println!(
161        "  coherence in basement: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
162        basement_coherence,
163        phase,
164        led[0], led[1], led[2]
165    );
166    println!("  (Trust does not transfer. The robot earned nothing here yet.)");
167
168    // ── Phase 3: A startle event back in the living room ─────────────────────
169    //
170    // The robot returns to the familiar living room. Someone slams a door.
171    // Because the robot has deep trust in this context (earned floor > 0),
172    // the negative event causes a drop — but cannot erase the accumulated history.
173    println!("\nPhase 3: Return to living room — startle event (door slam)");
174    println!("------------------------------------------------------------");
175
176    let before = field.effective_coherence(0.9, &living_room);
177    field.negative_interaction(&living_room, &personality, 81);
178    let after = field.effective_coherence(0.9, &living_room);
179
180    println!("  coherence before startle: {:.2}", before);
181    println!("  coherence after startle:  {:.2}", after);
182    println!(
183        "  drop: {:.2} (earned floor protects against erasure)",
184        before - after
185    );
186
187    let tension: f32 = 0.55; // brief spike from the startle
188    phase = SocialPhase::classify(after, tension, phase, &ps);
189    let led = phase.led_tint();
190    println!(
191        "  phase: {:?} | LED #{:02X}{:02X}{:02X}",
192        phase, led[0], led[1], led[2]
193    );
194
195    // ── Phase 4: Recovery ─────────────────────────────────────────────────────
196    //
197    // A few more positive interactions and the robot recovers. The familiar
198    // environment reasserts itself. This is not scripted — it emerges from the
199    // accumulated trust floor protecting the relationship.
200    println!("\nPhase 4: Recovery — 5 positive interactions");
201    println!("--------------------------------------------");
202
203    for tick in 82u64..87 {
204        field.positive_interaction(&living_room, &personality, tick, false);
205    }
206    let recovered = field.effective_coherence(0.9, &living_room);
207    let tension: f32 = 0.1;
208    phase = SocialPhase::classify(recovered, tension, phase, &ps);
209    let led = phase.led_tint();
210    println!(
211        "  coherence after recovery: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
212        recovered, phase, led[0], led[1], led[2]
213    );
214
215    // ── Summary ───────────────────────────────────────────────────────────────
216    println!("\nSummary");
217    println!("-------");
218    println!(
219        "  Living room trust:  {:.2} ({} interactions)",
220        field.effective_coherence(0.9, &living_room),
221        field.context_interaction_count(&living_room),
222    );
223    println!(
224        "  Basement trust:     {:.2} ({} interactions)",
225        field.effective_coherence(0.9, &basement),
226        field.context_interaction_count(&basement),
227    );
228    println!("\nThe robot knows where it belongs.");
229    println!("No rules. No scripts. Earned.");
230}
Source

pub fn negative_interaction( &mut self, key: &ContextKey<V, N>, personality: &Personality, tick: u64, )

Record a negative interaction for a context, modulated by personality.

Creates the accumulator at the personality baseline if the context is unseen.

Examples found in repository?
examples/mbot2.rs (line 177)
60fn main() {
61    println!("CCF mBot2 — Emergent Behaviour Simulation");
62    println!("==========================================\n");
63
64    // ── Personality ──────────────────────────────────────────────────────────
65    //
66    // These three parameters shape how the robot accumulates and loses trust.
67    // They are analogous to temperament — the same events produce different
68    // magnitudes of response depending on personality.
69    //
70    // This configuration: eager to engage (high curiosity), not easily startled
71    // (low sensitivity), recovers quickly from disruption (high recovery).
72    let personality = Personality {
73        curiosity_drive:     0.8,
74        startle_sensitivity: 0.3,
75        recovery_speed:      0.7,
76    };
77
78    // ── Trust field ──────────────────────────────────────────────────────────
79    //
80    // The field maintains an independent trust state per sensory context.
81    // It starts empty — the robot has no experience yet.
82    let mut field: CoherenceField<MbotSensors, 6> = CoherenceField::new();
83
84    // ── Phase space ──────────────────────────────────────────────────────────
85    //
86    // Configurable thresholds for the four-quadrant classifier.
87    // The default values (enter 0.65 / exit 0.55 on coherence) are a good
88    // starting point. Adjust to tune how quickly the robot "warms up".
89    let ps = PhaseSpace::new();
90    let mut phase = SocialPhase::ShyObserver;
91
92    // ── Two sensor contexts ──────────────────────────────────────────────────
93    //
94    // The living room: bright, quiet, a familiar person nearby.
95    // The basement:    dark, moderate noise, no one present.
96    //
97    // These are entirely independent trust contexts. Experience in one
98    // does not transfer to the other.
99    let living_room = ContextKey::new(MbotSensors {
100        brightness:  BrightnessBand::Bright,
101        noise:       NoiseBand::Quiet,
102        presence:    PresenceSignature::Close,
103        motion:      MotionContext::Static,
104        orientation: Orientation::Upright,
105        time_period: TimePeriod::Day,
106    });
107
108    let basement = ContextKey::new(MbotSensors {
109        brightness:  BrightnessBand::Dark,
110        noise:       NoiseBand::Moderate,
111        presence:    PresenceSignature::Absent,
112        motion:      MotionContext::Static,
113        orientation: Orientation::Upright,
114        time_period: TimePeriod::Evening,
115    });
116
117    // ── Phase 1: Build trust in the living room ───────────────────────────────
118    //
119    // Simulate 80 ticks of positive interaction in the living room.
120    // The person is present, the environment is calm, interactions go well.
121    println!("Phase 1: 80 positive interactions in the living room");
122    println!("------------------------------------------------------");
123
124    for tick in 0u64..80 {
125        // alone=false: the person is present; the interaction is social
126        field.positive_interaction(&living_room, &personality, tick, false);
127
128        // instant: the current sensor-level signal (1.0 = fully coherent reading)
129        // In a real system this comes from your homeostasis / sensor fusion layer.
130        let instant: f32 = 0.9;
131        let coherence = field.effective_coherence(instant, &living_room);
132        let tension: f32 = 0.1; // calm environment
133        phase = SocialPhase::classify(coherence, tension, phase, &ps);
134
135        if tick % 20 == 19 {
136            let led = phase.led_tint();
137            println!(
138                "  tick {:>3} | coherence {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
139                tick + 1,
140                coherence,
141                phase,
142                led[0], led[1], led[2]
143            );
144        }
145    }
146
147    // ── Phase 2: The basement — zero trust, same robot ───────────────────────
148    //
149    // The robot is moved to the basement. It has never been here before.
150    // All the trust it built in the living room is irrelevant in this context.
151    // It starts from zero — exactly as it should.
152    println!("\nPhase 2: Robot moved to the basement (zero prior experience)");
153    println!("--------------------------------------------------------------");
154
155    let basement_coherence = field.effective_coherence(0.9, &basement);
156    let basement_tension: f32 = 0.5; // unfamiliar, slightly unnerving
157    phase = SocialPhase::classify(basement_coherence, basement_tension, phase, &ps);
158
159    let led = phase.led_tint();
160    println!(
161        "  coherence in basement: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
162        basement_coherence,
163        phase,
164        led[0], led[1], led[2]
165    );
166    println!("  (Trust does not transfer. The robot earned nothing here yet.)");
167
168    // ── Phase 3: A startle event back in the living room ─────────────────────
169    //
170    // The robot returns to the familiar living room. Someone slams a door.
171    // Because the robot has deep trust in this context (earned floor > 0),
172    // the negative event causes a drop — but cannot erase the accumulated history.
173    println!("\nPhase 3: Return to living room — startle event (door slam)");
174    println!("------------------------------------------------------------");
175
176    let before = field.effective_coherence(0.9, &living_room);
177    field.negative_interaction(&living_room, &personality, 81);
178    let after = field.effective_coherence(0.9, &living_room);
179
180    println!("  coherence before startle: {:.2}", before);
181    println!("  coherence after startle:  {:.2}", after);
182    println!(
183        "  drop: {:.2} (earned floor protects against erasure)",
184        before - after
185    );
186
187    let tension: f32 = 0.55; // brief spike from the startle
188    phase = SocialPhase::classify(after, tension, phase, &ps);
189    let led = phase.led_tint();
190    println!(
191        "  phase: {:?} | LED #{:02X}{:02X}{:02X}",
192        phase, led[0], led[1], led[2]
193    );
194
195    // ── Phase 4: Recovery ─────────────────────────────────────────────────────
196    //
197    // A few more positive interactions and the robot recovers. The familiar
198    // environment reasserts itself. This is not scripted — it emerges from the
199    // accumulated trust floor protecting the relationship.
200    println!("\nPhase 4: Recovery — 5 positive interactions");
201    println!("--------------------------------------------");
202
203    for tick in 82u64..87 {
204        field.positive_interaction(&living_room, &personality, tick, false);
205    }
206    let recovered = field.effective_coherence(0.9, &living_room);
207    let tension: f32 = 0.1;
208    phase = SocialPhase::classify(recovered, tension, phase, &ps);
209    let led = phase.led_tint();
210    println!(
211        "  coherence after recovery: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
212        recovered, phase, led[0], led[1], led[2]
213    );
214
215    // ── Summary ───────────────────────────────────────────────────────────────
216    println!("\nSummary");
217    println!("-------");
218    println!(
219        "  Living room trust:  {:.2} ({} interactions)",
220        field.effective_coherence(0.9, &living_room),
221        field.context_interaction_count(&living_room),
222    );
223    println!(
224        "  Basement trust:     {:.2} ({} interactions)",
225        field.effective_coherence(0.9, &basement),
226        field.context_interaction_count(&basement),
227    );
228    println!("\nThe robot knows where it belongs.");
229    println!("No rules. No scripts. Earned.");
230}
Source

pub fn context_coherence(&self, key: &ContextKey<V, N>) -> f32

Get the accumulated coherence for a context.

Returns the accumulator value if seen, or the fallback / 0.0 for unseen contexts.

Source

pub fn context_interaction_count(&self, key: &ContextKey<V, N>) -> u32

Number of positive interactions recorded for a context (0 if unseen).

Examples found in repository?
examples/mbot2.rs (line 221)
60fn main() {
61    println!("CCF mBot2 — Emergent Behaviour Simulation");
62    println!("==========================================\n");
63
64    // ── Personality ──────────────────────────────────────────────────────────
65    //
66    // These three parameters shape how the robot accumulates and loses trust.
67    // They are analogous to temperament — the same events produce different
68    // magnitudes of response depending on personality.
69    //
70    // This configuration: eager to engage (high curiosity), not easily startled
71    // (low sensitivity), recovers quickly from disruption (high recovery).
72    let personality = Personality {
73        curiosity_drive:     0.8,
74        startle_sensitivity: 0.3,
75        recovery_speed:      0.7,
76    };
77
78    // ── Trust field ──────────────────────────────────────────────────────────
79    //
80    // The field maintains an independent trust state per sensory context.
81    // It starts empty — the robot has no experience yet.
82    let mut field: CoherenceField<MbotSensors, 6> = CoherenceField::new();
83
84    // ── Phase space ──────────────────────────────────────────────────────────
85    //
86    // Configurable thresholds for the four-quadrant classifier.
87    // The default values (enter 0.65 / exit 0.55 on coherence) are a good
88    // starting point. Adjust to tune how quickly the robot "warms up".
89    let ps = PhaseSpace::new();
90    let mut phase = SocialPhase::ShyObserver;
91
92    // ── Two sensor contexts ──────────────────────────────────────────────────
93    //
94    // The living room: bright, quiet, a familiar person nearby.
95    // The basement:    dark, moderate noise, no one present.
96    //
97    // These are entirely independent trust contexts. Experience in one
98    // does not transfer to the other.
99    let living_room = ContextKey::new(MbotSensors {
100        brightness:  BrightnessBand::Bright,
101        noise:       NoiseBand::Quiet,
102        presence:    PresenceSignature::Close,
103        motion:      MotionContext::Static,
104        orientation: Orientation::Upright,
105        time_period: TimePeriod::Day,
106    });
107
108    let basement = ContextKey::new(MbotSensors {
109        brightness:  BrightnessBand::Dark,
110        noise:       NoiseBand::Moderate,
111        presence:    PresenceSignature::Absent,
112        motion:      MotionContext::Static,
113        orientation: Orientation::Upright,
114        time_period: TimePeriod::Evening,
115    });
116
117    // ── Phase 1: Build trust in the living room ───────────────────────────────
118    //
119    // Simulate 80 ticks of positive interaction in the living room.
120    // The person is present, the environment is calm, interactions go well.
121    println!("Phase 1: 80 positive interactions in the living room");
122    println!("------------------------------------------------------");
123
124    for tick in 0u64..80 {
125        // alone=false: the person is present; the interaction is social
126        field.positive_interaction(&living_room, &personality, tick, false);
127
128        // instant: the current sensor-level signal (1.0 = fully coherent reading)
129        // In a real system this comes from your homeostasis / sensor fusion layer.
130        let instant: f32 = 0.9;
131        let coherence = field.effective_coherence(instant, &living_room);
132        let tension: f32 = 0.1; // calm environment
133        phase = SocialPhase::classify(coherence, tension, phase, &ps);
134
135        if tick % 20 == 19 {
136            let led = phase.led_tint();
137            println!(
138                "  tick {:>3} | coherence {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
139                tick + 1,
140                coherence,
141                phase,
142                led[0], led[1], led[2]
143            );
144        }
145    }
146
147    // ── Phase 2: The basement — zero trust, same robot ───────────────────────
148    //
149    // The robot is moved to the basement. It has never been here before.
150    // All the trust it built in the living room is irrelevant in this context.
151    // It starts from zero — exactly as it should.
152    println!("\nPhase 2: Robot moved to the basement (zero prior experience)");
153    println!("--------------------------------------------------------------");
154
155    let basement_coherence = field.effective_coherence(0.9, &basement);
156    let basement_tension: f32 = 0.5; // unfamiliar, slightly unnerving
157    phase = SocialPhase::classify(basement_coherence, basement_tension, phase, &ps);
158
159    let led = phase.led_tint();
160    println!(
161        "  coherence in basement: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
162        basement_coherence,
163        phase,
164        led[0], led[1], led[2]
165    );
166    println!("  (Trust does not transfer. The robot earned nothing here yet.)");
167
168    // ── Phase 3: A startle event back in the living room ─────────────────────
169    //
170    // The robot returns to the familiar living room. Someone slams a door.
171    // Because the robot has deep trust in this context (earned floor > 0),
172    // the negative event causes a drop — but cannot erase the accumulated history.
173    println!("\nPhase 3: Return to living room — startle event (door slam)");
174    println!("------------------------------------------------------------");
175
176    let before = field.effective_coherence(0.9, &living_room);
177    field.negative_interaction(&living_room, &personality, 81);
178    let after = field.effective_coherence(0.9, &living_room);
179
180    println!("  coherence before startle: {:.2}", before);
181    println!("  coherence after startle:  {:.2}", after);
182    println!(
183        "  drop: {:.2} (earned floor protects against erasure)",
184        before - after
185    );
186
187    let tension: f32 = 0.55; // brief spike from the startle
188    phase = SocialPhase::classify(after, tension, phase, &ps);
189    let led = phase.led_tint();
190    println!(
191        "  phase: {:?} | LED #{:02X}{:02X}{:02X}",
192        phase, led[0], led[1], led[2]
193    );
194
195    // ── Phase 4: Recovery ─────────────────────────────────────────────────────
196    //
197    // A few more positive interactions and the robot recovers. The familiar
198    // environment reasserts itself. This is not scripted — it emerges from the
199    // accumulated trust floor protecting the relationship.
200    println!("\nPhase 4: Recovery — 5 positive interactions");
201    println!("--------------------------------------------");
202
203    for tick in 82u64..87 {
204        field.positive_interaction(&living_room, &personality, tick, false);
205    }
206    let recovered = field.effective_coherence(0.9, &living_room);
207    let tension: f32 = 0.1;
208    phase = SocialPhase::classify(recovered, tension, phase, &ps);
209    let led = phase.led_tint();
210    println!(
211        "  coherence after recovery: {:.2} | phase {:?} | LED #{:02X}{:02X}{:02X}",
212        recovered, phase, led[0], led[1], led[2]
213    );
214
215    // ── Summary ───────────────────────────────────────────────────────────────
216    println!("\nSummary");
217    println!("-------");
218    println!(
219        "  Living room trust:  {:.2} ({} interactions)",
220        field.effective_coherence(0.9, &living_room),
221        field.context_interaction_count(&living_room),
222    );
223    println!(
224        "  Basement trust:     {:.2} ({} interactions)",
225        field.effective_coherence(0.9, &basement),
226        field.context_interaction_count(&basement),
227    );
228    println!("\nThe robot knows where it belongs.");
229    println!("No rules. No scripts. Earned.");
230}
Source

pub fn decay_all(&mut self, elapsed_ticks: u64)

Apply time-based decay to all accumulators.

Source

pub fn context_count(&self) -> usize

Number of tracked contexts.

Source

pub fn iter( &self, ) -> impl Iterator<Item = (&ContextKey<V, N>, &CoherenceAccumulator)>

Iterate over all (context key, accumulator) pairs.

Source

pub fn set_fallback(&mut self, value: Option<f32>)

Set the fallback coherence returned for unseen contexts in degraded mode.

Pass None to clear the fallback (unseen contexts revert to 0.0).

Source

pub fn get_or_create( &mut self, key: &ContextKey<V, N>, ) -> &mut CoherenceAccumulator

Get or create the accumulator for key, initialising at the personality baseline.

Evicts the oldest entry when the field is at [MAX_CONTEXTS] capacity.

Trait Implementations§

Source§

impl<V: SensorVocabulary<N>, const N: usize> Debug for CoherenceField<V, N>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<V: SensorVocabulary<N>, const N: usize> Default for CoherenceField<V, N>

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

§

impl<V, const N: usize> Freeze for CoherenceField<V, N>

§

impl<V, const N: usize> RefUnwindSafe for CoherenceField<V, N>
where V: RefUnwindSafe,

§

impl<V, const N: usize> Send for CoherenceField<V, N>
where V: Send,

§

impl<V, const N: usize> Sync for CoherenceField<V, N>
where V: Sync,

§

impl<V, const N: usize> Unpin for CoherenceField<V, N>
where V: Unpin,

§

impl<V, const N: usize> UnsafeUnpin for CoherenceField<V, N>

§

impl<V, const N: usize> UnwindSafe for CoherenceField<V, N>
where V: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.