File size: 12,015 Bytes
9425aed | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 | -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- AgentGoals.hs β Goal System & Adaptation
-- bridges/haskell/AgentGoals.hs
--
-- PHASE 7 AGENT GOALS. ADAPTIVE. FRAME-AWARE.
--
-- Goals are the "why" behind agent actions.
-- Agents adjust goals based on observations and detected frame.
--
-- Frame β Goal mapping:
-- Gravity β Map (record gravitational structure)
-- Relativity β Detect (measure time effects)
-- Quantum β Detect (sample superposition)
-- Wormhole β Explore (find connections)
-- Horizon β Detect (anomalies near boundaries)
-- Unknown β Explore (gather data)
--
-- Goals are observable: agents commit to them, but can adapt.
--
-- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
{-# LANGUAGE DeriveGeneric #-}
module AgentGoals where
import Data.List (intercalate)
import GHC.Generics (Generic)
import qualified Data.Map.Strict as Map
import SpacetimeAgent
( Agent(..), Observation(..), Frame(..), Goal(..), Subgoal(..)
, AgentId, RegionOfInterest(..), AnomalyType(..)
)
-- ββ Goal Satisfaction Metric βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Tracks progress toward goal
data GoalProgress = GoalProgress
{ progressGoalId :: Int -- Which goal instance
, progressType :: GoalType -- What kind of goal
, progressStatus :: ProgressStatus
, progressMetric :: Double -- 0-1 completion estimate
, progressObservations :: Int -- How many obs contributed
, progressUpdatedAt :: Int -- Timestamp
} deriving (Show, Eq, Generic)
data GoalType
= GoalExplore
| GoalMap
| GoalDetect
| GoalCollaborate
deriving (Show, Eq, Generic)
data ProgressStatus
= Active
| Paused
| Completed
| Failed
deriving (Show, Eq, Generic)
-- ββ Frame-based goal selection βββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- Given current frame, what should agent prioritize?
selectGoalForFrame :: Frame -> Observation -> Goal
selectGoalForFrame frame obs =
case frame of
Gravity ->
Map (LocalRegion 2.0) -- Map gravitational region
Relativity ->
Detect TemporalAnomaly -- Detect time-based anomalies
Quantum ->
Detect SuperpositionCollapse -- Sample quantum collapse
Wormhole ->
Explore FindConnections -- Find topology shortcuts
Horizon ->
Detect CurvatureSpike -- Monitor event horizon
Unknown ->
Explore SampleRegion -- Gather initial data
-- ββ Goal inheritance (agents learn from peers) βββββββββββββββββββββββββββββββββββββ
-- If another agent succeeded at a goal, inherit it
inheritGoal :: Agent -> AgentId -> Goal -> Agent
inheritGoal agent sourceAgent newGoal =
let oldDecision = decision agent
newDecision = oldDecision { agentGoal = newGoal }
in agent { decision = newDecision }
-- ββ Goal termination (agent completed or gave up) βββββββββββββββββββββββββββββββββββ
data GoalTermination
= SuccessfulCompletion
| BudgetExhausted
| NoProgressAfterN Int
| DetectedImpossible
deriving (Show, Eq, Generic)
-- Check if goal should be abandoned
shouldAbandonGoal :: Agent -> GoalProgress -> Bool
shouldAbandonGoal agent progress =
let budget = resourceBudget (decision agent)
usage = currentUsage budget
-- Abandon if: no resources left, or no progress in 10 steps
noBudget = movementUsed usage >= movementBudget budget
&& observationUsed usage >= observationBudget budget
noProgress = progressObservations progress == 0
in noBudget || noProgress
-- ββ Goal transition (when to switch goals) ββββββββββββββββββββββββββββββββββββββββ
data GoalTransition = GoalTransition
{ fromGoal :: Goal
, toGoal :: Goal
, reason :: TransitionReason
, decidedAt :: Int -- Step number
} deriving (Show, Eq, Generic)
data TransitionReason
= FrameChange -- Detected new frame
| GoalCompleted -- Goal satisfied
| ResourceLimited -- Budget pressure
| PeerSuggestion AgentId -- Another agent recommended
| OptimalitySwitch -- Found better goal
deriving (Show, Eq, Generic)
-- Decide if goal transition is warranted
shouldTransitionGoal :: Agent -> Observation -> GoalProgress -> Maybe TransitionReason
shouldTransitionGoal agent obs progress =
let currentFrame = observerFrame (position agent)
selectedFrame = detectFrame obs
-- Transition if frame changed significantly
frameChanged = currentFrame /= selectedFrame
-- Transition if goal is stuck
isStuck = progressMetric progress < 0.1 && progressObservations progress > 20
-- Transition if budget low
budgetLow = remainingMovement (resourceBudget (decision agent)) < 5
in case () of
_ | frameChanged -> Just FrameChange
_ | isStuck -> Just OptimalitySwitch
_ | budgetLow -> Just ResourceLimited
_ -> Nothing
-- Helper: detectFrame for AgentGoals module
detectFrame :: Observation -> Frame
detectFrame obs
| curvatureDetected obs = Gravity
| timeScalingDetected obs = Relativity
| probabilisticState obs = Quantum
| alternatePathsDetected obs = Wormhole
| eventHorizonNear obs = Horizon
| otherwise = Unknown
-- Helper predicates
curvatureDetected :: Observation -> Bool
curvatureDetected obs =
case Map.lookup "curvature" (obsMeasurements obs) of
Just v -> v > 0.1
Nothing -> False
timeScalingDetected :: Observation -> Bool
timeScalingDetected obs =
case Map.lookup "time_scale" (obsMeasurements obs) of
Just v -> v /= 1.0
Nothing -> False
probabilisticState :: Observation -> Bool
probabilisticState obs =
case Map.lookup "entropy" (obsMeasurements obs) of
Just v -> v > 0.3
Nothing -> False
alternatePathsDetected :: Observation -> Bool
alternatePathsDetected obs =
case Map.lookup "paths" (obsMeasurements obs) of
Just v -> v > 1.0
Nothing -> False
eventHorizonNear :: Observation -> Bool
eventHorizonNear obs =
case Map.lookup "horizon_distance" (obsMeasurements obs) of
Just v -> v < 1.0
Nothing -> False
-- Helper: remainingMovement from ResourceBudget
remainingMovement :: ResourceBudget -> Int
remainingMovement b = max 0 (movementBudget b - movementUsed (currentUsage b))
-- ββ Goal coalignment (multi-agent goal networks) ββββββββββββββββββββββββββββββββββββ
-- Track which agents are pursuing complementary goals
data GoalCoalignment = GoalCoalignment
{ agentsAligned :: [AgentId]
, alignedGoal :: Goal
, synergyValue :: Double -- Benefit of cooperation (0-1)
, communicationBudget :: Int -- Messages to coordinate
} deriving (Show, Eq, Generic)
-- Compute synergy when agents share a goal
computeSynergy :: [Agent] -> Goal -> Double
computeSynergy agents sharedGoal =
let matchCount = length $ filter (\a -> agentGoal (decision a) == sharedGoal) agents
coordCost = if matchCount > 1 then 0.1 else 0.0
in max 0.0 (0.5 + fromIntegral matchCount * 0.2 - coordCost)
-- ββ Goal history (for learning/debugging) ββββββββββββββββββββββββββββββββββββββββββ
data GoalHistory = GoalHistory
{ historyAgentId :: AgentId
, historyGoals :: [(Int, Goal)] -- (timestamp, goal)
, historyTransitions :: [GoalTransition]
, historySuccess :: Int -- Goals completed
, historyAbandoned :: Int -- Goals abandoned
} deriving (Show, Eq, Generic)
-- Log goal adoption
recordGoalAdoption :: GoalHistory -> Int -> Goal -> GoalHistory
recordGoalAdoption hist timestamp goal =
hist { historyGoals = historyGoals hist ++ [(timestamp, goal)] }
-- Log goal completion
recordGoalCompletion :: GoalHistory -> GoalHistory
recordGoalCompletion hist = hist { historySuccess = historySuccess hist + 1 }
-- Log goal abandonment
recordGoalAbandonment :: GoalHistory -> GoalHistory
recordGoalAbandonment hist = hist { historyAbandoned = historyAbandoned hist + 1 }
-- ββ Goal announcement to swarm βββββββββββββββββββββββββββββββββββββββββββββββββββββ
-- When an agent adopts a goal, it broadcasts to peers
goalAnnouncement :: Agent -> String
goalAnnouncement agent =
let aid = agentIdentity agent
goal = agentGoal (decision agent)
conf = confidenceLevel (decision agent)
pos = coordinates (position agent)
in intercalate " | "
[ "GOAL_ANNOUNCE:" ++ aid
, "goal=" ++ show goal
, "confidence=" ++ show conf
, "position=" ++ show pos
]
-- ββ Goal satisfaction predicates βββββββββββββββββββββββββββββββββββββββββββββββββββ
isGoalSatisfied :: Agent -> GoalProgress -> Bool
isGoalSatisfied agent progress =
progressMetric progress >= 0.9 -- 90% completion threshold
&& progressObservations progress > 5
isGoalFailing :: Agent -> GoalProgress -> Bool
isGoalFailing agent progress =
progressObservations progress > 30 -- Many observations
&& progressMetric progress < 0.3 -- But little progress
-- ββ Goal diversity (swarm should have varied goals) ββββββββββββββββββββββββββββββ
goalDiversity :: [Agent] -> Double
goalDiversity agents =
if null agents
then 0.0
else
let goals = map (agentGoal . decision) agents
uniqueGoals = length $ filter (\g -> length (filter (== g) goals) == 1) goals
in fromIntegral uniqueGoals / fromIntegral (length agents)
-- Export: goals summary
goalsReport :: [Agent] -> String
goalsReport agents =
let header = "βββ Swarm Goal Report βββ\n"
byGoal = countGoalsByType agents
diversity = goalDiversity agents
stats = "Total Agents: " ++ show (length agents)
++ " | Goal Diversity: " ++ show (roundTo 2 diversity) ++ "\n"
breakdown = intercalate "\n"
[ " " ++ show gt ++ ": " ++ show count
| (gt, count) <- byGoal
]
in header ++ stats ++ "\nBreakdown:\n" ++ breakdown
countGoalsByType :: [Agent] -> [(GoalType, Int)]
countGoalsByType agents =
let goals = map (agentGoal . decision) agents
explore = length $ filter isExploreGoal goals
mapGoal = length $ filter isMapGoal goals
detect = length $ filter isDetectGoal goals
collab = length $ filter isCollabGoal goals
in [ (GoalExplore, explore)
, (GoalMap, mapGoal)
, (GoalDetect, detect)
, (GoalCollaborate, collab)
]
isExploreGoal :: Goal -> Bool
isExploreGoal (Explore _) = True
isExploreGoal _ = False
isMapGoal :: Goal -> Bool
isMapGoal (Map _) = True
isMapGoal _ = False
isDetectGoal :: Goal -> Bool
isDetectGoal (Detect _) = True
isDetectGoal _ = False
isCollabGoal :: Goal -> Bool
isCollabGoal (Collaborate _) = True
isCollabGoal _ = False
-- Rounding helper
roundTo :: Int -> Double -> Double
roundTo n x = fromIntegral (round (x * 10^n) :: Integer) / 10^n
|