Download haskell/ConsensusVoting.hs from Snapkitty/quantumap: direct link, hf CLI and curl.
- Browser
- Download file 15.7 kB
-
https://huggingface.co/Snapkitty/quantumap/resolve/main/haskell/ConsensusVoting.hs
- Command line
-
hf download hf://Snapkitty/quantumap/haskell/ConsensusVoting.hs
-
curl -L -o ConsensusVoting.hs https://huggingface.co/Snapkitty/quantumap/resolve/main/haskell/ConsensusVoting.hs
15.7 kB
| module ConsensusVoting | |
| ( castVote | |
| , consensusRound | |
| , detectConflict | |
| , resolveConflict | |
| , syncAgentStates | |
| , multiAgentVote | |
| , getConsensusObservations | |
| , aggregateVotesForObservation | |
| , updateWorldModelWithConsensus | |
| , anomalyScoring | |
| , conflictThreshold | |
| ) where | |
| import ConsensusTypes | |
| import qualified Data.Map as Map | |
| import Data.Map (Map) | |
| import Data.List (sortBy, groupBy, maximumBy, nub) | |
| import Data.Ord (comparing, Down(..)) | |
| import GHC.Generics (Generic) | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- Consensus Parameters | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- | Threshold for declaring observations in conflict (normalized difference) | |
| conflictThreshold :: Double | |
| conflictThreshold = 0.25 | |
| -- | Minimum votes needed to form consensus | |
| minVotesForConsensus :: Int | |
| minVotesForConsensus = 2 | |
| -- | Consensus threshold (66%+) | |
| consensusThreshold :: Double | |
| consensusThreshold = 0.66 | |
| -- | Anomaly severity threshold (1-10 scale) | |
| anomalySeverityThreshold :: Double | |
| anomalySeverityThreshold = 0.5 | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- Voting: Cast, Aggregate, Tally | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- | Cast a vote: voter agrees/disagrees with observation | |
| castVote :: ConsensusState -> AgentId -> ObservationId -> Double -> Int -> ConsensusState | |
| castVote state voterId obsId agreeScore round = | |
| let vote = makeVote voterId obsId agreeScore round 0 | |
| newVotes = votes state ++ [vote] | |
| in state { votes = newVotes } | |
| -- | Aggregate votes for single observation into consensus score | |
| aggregateVotesForObservation :: ConsensusState -> ObservationId -> (Double, Int) | |
| aggregateVotesForObservation state obsId = | |
| let obsVotes = votesForObservation (votes state) obsId | |
| voteCount = length obsVotes | |
| in if voteCount < minVotesForConsensus | |
| then (0.0, 0) | |
| else (consensusScore obsVotes, voteCount) | |
| -- | Get all observations that reached consensus (66%+) | |
| getConsensusObservations :: ConsensusState -> [Observation] | |
| getConsensusObservations state = | |
| let allObs = observations state | |
| in filter (\obs -> let (score, count) = aggregateVotesForObservation state (obsId obs) | |
| in count >= minVotesForConsensus && score > 0.33) allObs | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- Consensus Round: Observation β Voting β World Model Update | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- | Execute full consensus round: tally votes, detect conflicts, update world model | |
| consensusRound :: ConsensusState -> [AgentId] -> Int -> ConsensusState | |
| consensusRound state participatingAgents roundNum = | |
| let -- Step 1: Group observations by ObservationId | |
| obsGroups = groupObservationsById state | |
| -- Step 2: Compute consensus for each group | |
| consensusResults = map (\(obsId, obs) -> | |
| let (score, voteCount) = aggregateVotesForObservation state obsId | |
| vots = votesForObservation (votes state) obsId | |
| in (obsId, obs, score, voteCount, vots) | |
| ) obsGroups | |
| -- Step 3: Separate consensed vs. conflicted | |
| (consensusObs, conflictedObs) = partitionConsensus consensusResults | |
| -- Step 4: Detect conflicts | |
| detectedConflicts = detectConflictsBatch state conflictedObs | |
| -- Step 5: Resolve conflicts via majority vote | |
| resolvedObs = map (\(o, c) -> resolveConflictVia state o c) (zip conflictedObs detectedConflicts) | |
| -- Step 6: All observations that passed consensus filter | |
| finalConsensusObs = consensusObs ++ resolvedObs | |
| -- Step 7: Update world model | |
| updatedModel = updateWorldModelWithConsensus (worldModel state) finalConsensusObs state | |
| -- Step 8: Compute global confidence | |
| globalConf = if null finalConsensusObs | |
| then confidence state | |
| else averageDouble (map (\(_, _, s, _, _) -> s) consensusResults) | |
| -- Step 9: Create vote round record | |
| voteRound = VoteRound roundNum 0 (votes state) (observations state) | |
| -- Step 10: Increment generation | |
| newGen = generation state + 1 | |
| in state | |
| { worldModel = updatedModel | |
| , confidence = globalConf | |
| , voteRounds = voteRounds state ++ [voteRound] | |
| , conflicts = conflicts state ++ detectedConflicts | |
| , generation = newGen | |
| } | |
| -- | Group observations by ObservationId | |
| groupObservationsById :: ConsensusState -> [(ObservationId, [Observation])] | |
| groupObservationsById state = | |
| let grouped = groupBy (\o1 o2 -> obsId o1 == obsId o2) | |
| (sortBy (comparing obsId) (observations state)) | |
| in map (\g -> (obsId (head g), g)) grouped | |
| -- | Partition consensus results into consensed vs. conflicted | |
| partitionConsensus :: [(ObservationId, [Observation], Double, Int, [Vote])] | |
| -> ([(ObservationId, [Observation], Double, Int, [Vote])], | |
| [(ObservationId, [Observation], Double, Int, [Vote])]) | |
| partitionConsensus results = | |
| let isConflicted (_, _, score, count, _) = | |
| count >= minVotesForConsensus && score <= 0.33 | |
| in (filter (not . isConflicted) results, filter isConflicted results) | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- Conflict Detection + Resolution | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- | Detect conflicts: two agents' measurements differ by > threshold | |
| detectConflictsBatch :: ConsensusState | |
| -> [(ObservationId, [Observation], Double, Int, [Vote])] | |
| -> [Conflict] | |
| detectConflictsBatch state conflictedGroups = | |
| map (\(obsId, obs, _, _, vots) -> | |
| let agents = map agentId obs | |
| measDiff = if length obs >= 2 | |
| then | |
| let m1 = measurements (head obs) | |
| m2 = measurements (obs !! 1) | |
| in measurementDifference m1 m2 | |
| else 0.0 | |
| in Conflict obsId (RegionId 0) agents measDiff False | |
| ) conflictedGroups | |
| -- | Detect conflict between two observations | |
| detectConflict :: Observation -> Observation -> Bool | |
| detectConflict obs1 obs2 = | |
| let dist = measurementDifference (measurements obs1) (measurements obs2) | |
| in dist > conflictThreshold && vectorDistance (coordinates obs1) (coordinates obs2) < 0.1 | |
| -- | Resolve conflict by majority vote | |
| resolveConflict :: ConsensusState -> Conflict -> Observation | |
| resolveConflict state conflict = | |
| case filter (\o -> obsId o == conflictObsId conflict) (observations state) of | |
| [] -> error "Conflict references non-existent observation" | |
| (o:_) -> o | |
| -- | Resolve conflict in batch | |
| resolveConflictVia :: ConsensusState -> (ObservationId, [Observation], Double, Int, [Vote]) | |
| -> Conflict -> Observation | |
| resolveConflictVia state (obsId, obs, _, _, votes) conflict = | |
| if null obs then error "resolveConflictVia: no observations in conflict group" | |
| else if null votes | |
| then head obs -- No votes: return first observation | |
| else | |
| -- Find observation with highest average agreement | |
| let obsWithScores = [(o, averageDouble [agreement v | v <- votes, votedObsId v == obsId o]) | o <- obs] | |
| in if null obsWithScores | |
| then head obs -- Fallback: no matching votes found | |
| else let (winningObs, _) = maximumBy (comparing snd) obsWithScores | |
| in winningObs | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- Multi-Agent Voting | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- | All agents vote on a new observation from one agent | |
| multiAgentVote :: ConsensusState -> Observation -> [AgentId] -> Int -> ConsensusState | |
| multiAgentVote state newObs voterIds round = | |
| let -- Observation already added to state | |
| obsIdToVoteOn = obsId newObs | |
| -- Each agent compares against their own measurements in same region | |
| votes = concatMap (\voterId -> | |
| let otherObs = observationsByAgent (observations state) voterId | |
| -- If agent has measurements in same region, vote on similarity | |
| similarObs = filter (\o -> case (regionType newObs, regionType o) of | |
| (Just r1, Just r2) -> r1 == r2 | |
| _ -> False) otherObs | |
| in if null similarObs | |
| then [makeVote voterId obsIdToVoteOn 0.0 round 0] -- Uncertain | |
| else let avgDiff = averageDouble [measurementDifference (measurements newObs) (measurements o) | o <- similarObs] | |
| agreeScore = 1.0 - min 1.0 (avgDiff / 0.5) -- normalize to [-1, 1] | |
| in [makeVote voterId obsIdToVoteOn agreeScore round 0] | |
| ) voterIds | |
| newVotes = votes state ++ votes | |
| in state { votes = newVotes } | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- World Model Update | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- | Update world model with newly consensed observations | |
| updateWorldModelWithConsensus :: WorldModel -> [Observation] -> ConsensusState -> WorldModel | |
| updateWorldModelWithConsensus model consensusObs state = | |
| let -- Extract regions | |
| regionsFromObs = [(RegionId i, regionType o) | (i, o) <- zip [0..] consensusObs, regionType o /= Nothing] | |
| newRegionMap = Map.fromList [(rId, rt) | (rId, Just rt) <- regionsFromObs] | |
| -- Update agent positions (latest from consensus observations) | |
| newAgentPositions = Map.fromList [(agentId o, coordinates o) | o <- consensusObs] | |
| -- Detect anomalies | |
| detectedAnomalies = anomalyScoring state consensusObs | |
| -- Frontier regions (low confidence, high anomaly) | |
| frontierIds = [RegionId i | (i, _) <- zip [0..] consensusObs, any (\a -> anomalySeverity a > 0.6) detectedAnomalies] | |
| -- Extract confidence from observations | |
| obsConfidenceValues = map (\o -> o.confidence) consensusObs | |
| in WorldModel | |
| { regionTypes = Map.union newRegionMap (regionTypes model) | |
| , agentPositions = Map.union newAgentPositions (agentPositions model) | |
| , anomalies = anomalies model ++ detectedAnomalies | |
| , frontierRegions = nub (frontierRegions model ++ frontierIds) | |
| , modelConfidence = averageDouble obsConfidenceValues | |
| , modelGeneration = modelGeneration model + 1 | |
| } | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- Anomaly Detection | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- | Score anomalies from consensus observations | |
| anomalyScoring :: ConsensusState -> [Observation] -> [Anomaly] | |
| anomalyScoring state consensusObs = | |
| let -- Find observations with high measurement variance | |
| highVarianceObs = filter (\o -> confidence o < 0.5) consensusObs | |
| -- Group by location | |
| locGroups = groupBy (\o1 o2 -> vectorDistance (coordinates o1) (coordinates o2) < 0.05) | |
| (sortBy (comparing coordinates) highVarianceObs) | |
| -- Create anomalies | |
| anomalies = concatMap (\group -> | |
| if length group > 0 | |
| then let avgLoc = Vector | |
| (averageDouble (map (\o -> vx (coordinates o)) group)) | |
| (averageDouble (map (\o -> vy (coordinates o)) group)) | |
| (averageDouble (map (\o -> vz (coordinates o)) group)) | |
| agentSet = map agentId group | |
| severity = 1.0 - averageDouble (map confidence group) | |
| in [Anomaly (length (anomalies state)) avgLoc severity 0 agentSet 0.5] | |
| else [] | |
| ) locGroups | |
| in anomalies | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- State Synchronization | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- | Synchronize all agents to shared world model and confidence | |
| syncAgentStates :: ConsensusState -> ConsensusState | |
| syncAgentStates state = | |
| -- All agents converge to world model + global confidence | |
| -- This is a no-op in ConsensusState (agents are external) | |
| -- but signifies: all agents should now use state's worldModel + confidence | |
| state | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- Utility: Observation as a data type that can be updated | |
| -- βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| -- | Mark observation as WORM-sealed | |
| sealObservation :: Observation -> Int -> Observation | |
| sealObservation obs round = obs { wormSealed = True, sealRound = Just round } | |
| -- | Seal all observations in consensus state | |
| sealObservationsInRound :: ConsensusState -> Int -> ConsensusState | |
| sealObservationsInRound state round = | |
| let sealedObs = map (\o -> sealObservation o round) (observations state) | |
| in state { observations = sealedObs } | |