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>
impl<V: SensorVocabulary<N>, const N: usize> CoherenceField<V, N>
Sourcepub fn new() -> Self
pub fn new() -> Self
Construct a fresh field with no accumulated coherence.
Examples found in repository?
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}Sourcepub fn effective_coherence(&self, instant: f32, key: &ContextKey<V, N>) -> f32
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?
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}Sourcepub fn positive_interaction(
&mut self,
key: &ContextKey<V, N>,
personality: &Personality,
tick: u64,
alone: bool,
)
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?
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}Sourcepub fn negative_interaction(
&mut self,
key: &ContextKey<V, N>,
personality: &Personality,
tick: u64,
)
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?
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}Sourcepub fn context_coherence(&self, key: &ContextKey<V, N>) -> f32
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.
Sourcepub fn context_interaction_count(&self, key: &ContextKey<V, N>) -> u32
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?
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}Sourcepub fn context_count(&self) -> usize
pub fn context_count(&self) -> usize
Number of tracked contexts.
Sourcepub fn iter(
&self,
) -> impl Iterator<Item = (&ContextKey<V, N>, &CoherenceAccumulator)>
pub fn iter( &self, ) -> impl Iterator<Item = (&ContextKey<V, N>, &CoherenceAccumulator)>
Iterate over all (context key, accumulator) pairs.
Sourcepub fn set_fallback(&mut self, value: Option<f32>)
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).
Sourcepub fn get_or_create(
&mut self,
key: &ContextKey<V, N>,
) -> &mut CoherenceAccumulator
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.