3333# Data structures
3434# ---------------------------------------------------------------------------
3535
36+
3637@dataclass
3738class ScheduleSelection :
3839 """A participant's chosen schedule together with its version counter."""
@@ -43,10 +44,7 @@ class ScheduleSelection:
4344 def __eq__ (self , other : object ) -> bool :
4445 if not isinstance (other , ScheduleSelection ):
4546 return NotImplemented
46- return (
47- np .array_equal (self .schedule , other .schedule )
48- and self .counter == other .counter
49- )
47+ return np .array_equal (self .schedule , other .schedule ) and self .counter == other .counter
5048
5149 def __hash__ (self ) -> int :
5250 return hash ((tuple (float (v ) for v in self .schedule ), self .counter ))
@@ -67,8 +65,7 @@ def __eq__(self, other: object) -> bool:
6765 if set (self .schedule_choices ) != set (other .schedule_choices ):
6866 return False
6967 return all (
70- self .schedule_choices [k ] == other .schedule_choices [k ]
71- for k in self .schedule_choices
68+ self .schedule_choices [k ] == other .schedule_choices [k ] for k in self .schedule_choices
7269 )
7370
7471 def __hash__ (self ) -> int :
@@ -106,9 +103,7 @@ def __eq__(self, other: object) -> bool:
106103 )
107104
108105 def __hash__ (self ) -> int :
109- return hash (
110- (self .participant_id , self .schedules .tobytes (), self .perf , self .present )
111- )
106+ return hash ((self .participant_id , self .schedules .tobytes (), self .perf , self .present ))
112107
113108 def __repr__ (self ) -> str :
114109 return (
@@ -128,9 +123,8 @@ class TargetParams:
128123 def __eq__ (self , other : object ) -> bool :
129124 if not isinstance (other , TargetParams ):
130125 return NotImplemented
131- return (
132- np .array_equal (self .schedule , other .schedule )
133- and np .array_equal (self .weights , other .weights )
126+ return np .array_equal (self .schedule , other .schedule ) and np .array_equal (
127+ self .weights , other .weights
134128 )
135129
136130 def __hash__ (self ) -> int :
@@ -142,10 +136,7 @@ def __hash__(self) -> int:
142136 )
143137
144138 def __repr__ (self ) -> str :
145- return (
146- f"TargetParams(schedule={ self .schedule .tolist ()} , "
147- f"weights={ self .weights .tolist ()} )"
148- )
139+ return f"TargetParams(schedule={ self .schedule .tolist ()} , weights={ self .weights .tolist ()} )"
149140
150141
151142@dataclass
@@ -168,6 +159,7 @@ class WorkingMemory(OptimizationMessage):
168159# Default performance function
169160# ---------------------------------------------------------------------------
170161
162+
171163def cohda_default_performance (
172164 cluster_schedule : np .ndarray ,
173165 target_params : TargetParams ,
@@ -178,7 +170,7 @@ def cohda_default_performance(
178170 :param target_params: Target schedule and weights.
179171 :returns: ``-sum(weights * abs(target - column_sums))``.
180172 """
181- sum_cs = cluster_schedule .sum (axis = 0 ) # (n_intervals,)
173+ sum_cs = cluster_schedule .sum (axis = 0 ) # (n_intervals,)
182174 diff = np .abs (target_params .schedule - sum_cs )
183175 return - float (np .sum (diff * target_params .weights ))
184176
@@ -187,6 +179,7 @@ def cohda_default_performance(
187179# Local decider hierarchy
188180# ---------------------------------------------------------------------------
189181
182+
190183class LocalDecider :
191184 """Abstract strategy for selecting a local schedule in the decide step."""
192185
@@ -218,6 +211,7 @@ def initial_schedule(self, memory: WorkingMemory) -> np.ndarray:
218211# COHDAAlgorithmData
219212# ---------------------------------------------------------------------------
220213
214+
221215class COHDAAlgorithmData (DistributedAlgorithm ):
222216 """Per-participant COHDA state machine.
223217
@@ -255,6 +249,7 @@ async def on_exchange_message(
255249# Core algorithmic functions
256250# ---------------------------------------------------------------------------
257251
252+
258253def merge_sysconfigs (
259254 sysconfig_i : SystemConfig ,
260255 sysconfig_j : SystemConfig ,
@@ -271,8 +266,7 @@ def merge_sysconfigs(
271266 modified = False
272267 for aid in all_ids :
273268 if aid in choices_i and (
274- aid not in choices_j
275- or choices_i [aid ].counter >= choices_j [aid ].counter
269+ aid not in choices_j or choices_i [aid ].counter >= choices_j [aid ].counter
276270 ):
277271 new_choices [aid ] = choices_i [aid ]
278272 else :
@@ -378,9 +372,7 @@ def perceive(
378372 counter = cohda_data .counter + 1 ,
379373 )
380374 cohda_data .counter += 1
381- current_sysconfig = SystemConfig (
382- dict (own_memory .system_config .schedule_choices )
383- )
375+ current_sysconfig = SystemConfig (dict (own_memory .system_config .schedule_choices ))
384376 else :
385377 current_sysconfig = own_memory .system_config
386378
@@ -456,9 +448,7 @@ def _decide_default(
456448 candidate : SolutionCandidate ,
457449) -> tuple [SystemConfig , SolutionCandidate ]:
458450 """Evaluate all feasible schedules; keep the best-performing candidate."""
459- possible = [
460- np .array (s , dtype = float ) for s in decider .schedule_provider (cohda_data .memory )
461- ]
451+ possible = [np .array (s , dtype = float ) for s in decider .schedule_provider (cohda_data .memory )]
462452 current_best = candidate
463453 if current_best .perf is None :
464454 current_best = _evaluated (
@@ -469,9 +459,7 @@ def _decide_default(
469459
470460 for schedule in possible :
471461 if decider .is_local_acceptable (schedule ):
472- new_cand = create_from_updated_sysconf (
473- cohda_data .participant_id , sysconfig , schedule
474- )
462+ new_cand = create_from_updated_sysconf (cohda_data .participant_id , sysconfig , schedule )
475463 new_perf = cohda_data .performance_function (
476464 new_cand .schedules , cohda_data .memory .target_params
477465 )
@@ -521,9 +509,7 @@ async def process_exchange_message(
521509 sysconf , candidate = perceive (algorithm_data , messages )
522510
523511 if sysconf != old_sysconf or candidate != old_candidate :
524- sysconf , candidate = decide (
525- algorithm_data , algorithm_data .decider , sysconf , candidate
526- )
512+ sysconf , candidate = decide (algorithm_data , algorithm_data .decider , sysconf , candidate )
527513 wm = act (algorithm_data , sysconf , candidate )
528514 for other in carrier .others (str (algorithm_data .participant_id )):
529515 carrier .send_to_other (wm , other )
@@ -533,6 +519,7 @@ async def process_exchange_message(
533519# Factory helpers
534520# ---------------------------------------------------------------------------
535521
522+
536523def create_cohda_start_message (
537524 target_schedule : list [float ] | np .ndarray ,
538525 weights : list [float ] | np .ndarray | None = None ,
0 commit comments