| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| {-# LANGUAGE DeriveGeneric #-} |
|
|
| module SpacetimeAgent where |
|
|
| import Data.ByteString (ByteString) |
| import qualified Data.ByteString as BS |
| import qualified Data.ByteString.Char8 as BSC |
| import Data.List (intercalate) |
| import Data.Maybe (fromMaybe, catMaybes) |
| import qualified Data.Map.Strict as Map |
| import GHC.Generics (Generic) |
| import Data.Hashable (hash) |
|
|
| |
| |
|
|
| data Frame |
| = Unknown |
| | Gravity |
| | Relativity |
| | Quantum |
| | Wormhole |
| | Horizon |
| deriving (Show, Eq, Ord, Generic) |
|
|
| |
|
|
| data Goal |
| = Explore Subgoal |
| | Map RegionOfInterest |
| | Detect AnomalyType |
| | Collaborate AgentId |
| deriving (Show, Eq, Generic) |
|
|
| data Subgoal |
| = ExpandBoundary |
| | SampleRegion |
| | TraceTopology |
| | FindConnections |
| deriving (Show, Eq, Generic) |
|
|
| data RegionOfInterest |
| = LocalRegion Double |
| | SpecificCoordinates [Double] |
| deriving (Show, Eq, Generic) |
|
|
| data AnomalyType |
| = CurvatureSpike |
| | TemporalAnomaly |
| | SuperpositionCollapse |
| | TopologyChange |
| deriving (Show, Eq, Generic) |
|
|
| type AgentId = String |
|
|
| |
|
|
| data ResourceBudget = ResourceBudget |
| { movementBudget :: Int |
| , observationBudget :: Int |
| , messageBudget :: Int |
| , currentUsage :: ResourceUsage |
| } deriving (Show, Eq, Generic) |
|
|
| data ResourceUsage = ResourceUsage |
| { movementUsed :: Int |
| , observationUsed :: Int |
| , messageUsed :: Int |
| } deriving (Show, Eq, Generic) |
|
|
| |
| canMove :: ResourceBudget -> Bool |
| canMove b = movementUsed (currentUsage b) < movementBudget b |
|
|
| canObserve :: ResourceBudget -> Bool |
| canObserve b = observationUsed (currentUsage b) < observationBudget b |
|
|
| canMessage :: ResourceBudget -> Bool |
| canMessage b = messageUsed (currentUsage b) < messageBudget b |
|
|
| |
| remainingMovement :: ResourceBudget -> Int |
| remainingMovement b = max 0 (movementBudget b - movementUsed (currentUsage b)) |
|
|
| remainingObservation :: ResourceBudget -> Int |
| remainingObservation b = max 0 (observationBudget b - observationUsed (currentUsage b)) |
|
|
| remainingMessage :: ResourceBudget -> Int |
| remainingMessage b = max 0 (messageBudget b - messageUsed (currentUsage b)) |
|
|
| |
|
|
| data Observation = Observation |
| { obsTimestamp :: Int |
| , obsPosition :: [Double] |
| , obsMeasurements :: Map.Map String Double |
| , obsFrameDetected :: Frame |
| , obsHash :: ByteString |
| } deriving (Show, Eq, Generic) |
|
|
| |
| encodeObservation :: Observation -> ByteString |
| encodeObservation obs = |
| let coordStr = intercalate "," (map show (obsPosition obs)) |
| measStr = intercalate ";" (map (\(k,v) -> k ++ "=" ++ show v) (Map.toList (obsMeasurements obs))) |
| frameStr = show (obsFrameDetected obs) |
| parts = [show (obsTimestamp obs), coordStr, measStr, frameStr] |
| in BSC.pack (intercalate "|" parts) |
|
|
| |
| simpleHash :: ByteString -> ByteString |
| simpleHash bs = BSC.pack $ "h" ++ show (hash bs) |
|
|
| |
|
|
| data AgentPosition = AgentPosition |
| { coordinates :: [Double] |
| , observerFrame :: Frame |
| , lastObservation :: Maybe Observation |
| , memoryLog :: [Observation] |
| } deriving (Show, Eq, Generic) |
|
|
| |
|
|
| data AgentDecision = AgentDecision |
| { agentId :: AgentId |
| , agentGoal :: Goal |
| , resourceBudget :: ResourceBudget |
| , confidenceLevel :: Double |
| , explorationPath :: [AgentPosition] |
| , decisionCount :: Int |
| } deriving (Show, Eq, Generic) |
|
|
| |
|
|
| data Action |
| = MoveRandom Int |
| | MoveAlongGradient [Double] |
| | RecordObservation [Double] |
| | SampleSuperposition |
| | SendMessageToSwarm AgentId String |
| | Wait |
| deriving (Show, Eq, Generic) |
|
|
| |
| |
|
|
| detectFrame :: Observation -> Frame |
| detectFrame obs |
| | curvatureDetected obs = Gravity |
| | timeScalingDetected obs = Relativity |
| | probabilisticState obs = Quantum |
| | alternatePathsDetected obs = Wormhole |
| | eventHorizonNear obs = Horizon |
| | otherwise = Unknown |
|
|
| |
|
|
| 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 |
|
|
| |
| |
|
|
| decideNextAction :: AgentDecision -> Observation -> Maybe Action |
| decideNextAction decision obs |
| | not (canMove (resourceBudget decision)) && not (canObserve (resourceBudget decision)) = Just Wait |
| | otherwise = case (agentGoal decision, detectFrame obs) of |
| |
| (Explore ExpandBoundary, Unknown) | canMove (resourceBudget decision) -> |
| Just (MoveRandom (remainingMovement (resourceBudget decision))) |
| (Explore ExpandBoundary, Gravity) | canMove (resourceBudget decision) -> |
| Just (MoveAlongGradient (computeGradient obs)) |
| (Explore TraceTopology, Wormhole) | canObserve (resourceBudget decision) -> |
| Just (RecordObservation (obsPosition obs)) |
|
|
| |
| (Map _, _) | canObserve (resourceBudget decision) -> |
| Just (RecordObservation (obsPosition obs)) |
|
|
| |
| (Detect _, Quantum) | canObserve (resourceBudget decision) -> |
| Just SampleSuperposition |
| (Detect _, Horizon) | canObserve (resourceBudget decision) -> |
| Just (RecordObservation (obsPosition obs)) |
|
|
| |
| (Collaborate peerId, _) | canMessage (resourceBudget decision) -> |
| Just (SendMessageToSwarm peerId ("position:" ++ show (obsPosition obs))) |
|
|
| |
| _ -> Just Wait |
|
|
| |
| computeGradient :: Observation -> [Double] |
| computeGradient obs = |
| let curvature = fromMaybe 0.0 (Map.lookup "curvature" (obsMeasurements obs)) |
| in replicate (length (obsPosition obs)) (curvature * 0.01) |
|
|
| |
|
|
| updateConfidence :: AgentPosition -> Observation -> Double |
| updateConfidence pos obs = |
| let detectedFrame = detectFrame obs |
| lastFrame = observerFrame pos |
| matches = detectedFrame == lastFrame |
| increment = if matches then 0.1 else -0.05 |
| in min 1.0 (max 0.0 (0.5 + increment)) |
|
|
| |
|
|
| updateGoal :: Agent -> Observation -> Goal |
| updateGoal agent obs = |
| let frame = detectFrame obs |
| oldGoal = agentGoal (decision agent) |
| in case frame of |
| Horizon -> Detect AnomalyType.Anomaly |
| Wormhole -> Explore Connections |
| Quantum -> Detect AnomalyType.Superposition |
| _ -> Map (LocalRegion 1.0) |
|
|
| |
| |
| |
|
|
| |
|
|
| data Agent = Agent |
| { agentIdentity :: AgentId |
| , position :: AgentPosition |
| , decision :: AgentDecision |
| , createdAt :: Int |
| , observationCount :: Int |
| } deriving (Show, Eq, Generic) |
|
|
| |
|
|
| createAgent :: AgentId -> [Double] -> Int -> Agent |
| createAgent aid coords timestamp = |
| Agent |
| { agentIdentity = aid |
| , position = AgentPosition |
| { coordinates = coords |
| , observerFrame = Unknown |
| , lastObservation = Nothing |
| , memoryLog = [] |
| } |
| , decision = AgentDecision |
| { agentId = aid |
| , agentGoal = Explore SampleRegion |
| , resourceBudget = ResourceBudget |
| { movementBudget = 100 |
| , observationBudget = 50 |
| , messageBudget = 20 |
| , currentUsage = ResourceUsage 0 0 0 |
| } |
| , confidenceLevel = 0.0 |
| , explorationPath = [] |
| , decisionCount = 0 |
| } |
| , createdAt = timestamp |
| , observationCount = 0 |
| } |
|
|
| |
|
|
| recordObservation :: Agent -> Observation -> Agent |
| recordObservation agent obs = |
| let priorHash = case lastObservation (position agent) of |
| Just lastObs -> obsHash lastObs |
| Nothing -> BS.empty |
| newObs = obs { obsHash = simpleHash (encodeObservation obs <> priorHash) } |
| newPos = (position agent) |
| { lastObservation = Just newObs |
| , memoryLog = memoryLog (position agent) ++ [newObs] |
| } |
| newBudget = (resourceBudget (decision agent)) |
| { currentUsage = let u = currentUsage (resourceBudget (decision agent)) |
| in u { observationUsed = observationUsed u + 1 } |
| } |
| newDecision = (decision agent) |
| { resourceBudget = newBudget |
| , decisionCount = decisionCount (decision agent) + 1 |
| } |
| in agent |
| { position = newPos |
| , decision = newDecision |
| , observationCount = observationCount agent + 1 |
| } |
|
|
| |
|
|
| moveAgent :: Agent -> [Double] -> Agent |
| moveAgent agent newCoords |
| | not (canMove (resourceBudget (decision agent))) = agent |
| | otherwise = |
| let newPos = (position agent) { coordinates = newCoords } |
| newBudget = (resourceBudget (decision agent)) |
| { currentUsage = let u = currentUsage (resourceBudget (decision agent)) |
| in u { movementUsed = movementUsed u + 1 } |
| } |
| newDecision = (decision agent) |
| { resourceBudget = newBudget |
| , explorationPath = explorationPath (decision agent) ++ [position agent] |
| , decisionCount = decisionCount (decision agent) + 1 |
| } |
| in agent |
| { position = newPos |
| , decision = newDecision |
| } |
|
|
| |
|
|
| sendMessage :: Agent -> AgentId -> String -> Agent |
| sendMessage agent targetId msg |
| | not (canMessage (resourceBudget (decision agent))) = agent |
| | otherwise = |
| let newBudget = (resourceBudget (decision agent)) |
| { currentUsage = let u = currentUsage (resourceBudget (decision agent)) |
| in u { messageUsed = messageUsed u + 1 } |
| } |
| newDecision = (decision agent) |
| { resourceBudget = newBudget |
| , decisionCount = decisionCount (decision agent) + 1 |
| } |
| in agent |
| { decision = newDecision |
| } |
|
|
| |
|
|
| agentStatus :: Agent -> String |
| agentStatus agent = |
| let pos = position agent |
| dec = decision agent |
| budget = resourceBudget dec |
| usage = currentUsage budget |
| movedCells = explorationPath dec |
| in intercalate " | " |
| [ "Agent:" ++ agentIdentity agent |
| , "Pos:" ++ show (coordinates pos) |
| , "Frame:" ++ show (observerFrame pos) |
| , "Goal:" ++ show (agentGoal dec) |
| , "Confidence:" ++ printf "%.2f" (confidenceLevel dec) |
| , "Movement:" ++ show (movementUsed usage) ++ "/" ++ show (movementBudget budget) |
| , "Observations:" ++ show (observationUsed usage) ++ "/" ++ show (observationBudget budget) |
| , "Messages:" ++ show (messageUsed usage) ++ "/" ++ show (messageBudget budget) |
| , "MemorySize:" ++ show (length (memoryLog pos)) |
| ] |
|
|
| |
| printf :: String -> Double -> String |
| printf fmt val = show val |
|
|