33import logging
44from abc import ABC , abstractmethod
55from copy import copy
6- from itertools import combinations
6+ from itertools import permutations
77from typing import TYPE_CHECKING
88
99import numpy as np
@@ -47,7 +47,7 @@ def link_satellites(self, satellites: list["Satellite"]) -> None:
4747
4848 @abstractmethod # pragma: no cover
4949 def communication_pairs (self ) -> list [tuple ["Satellite" , "Satellite" ]]:
50- """List pairs of satellite that should share data.
50+ """List pairs of satellite that should share data, in the form (sender, recipient) .
5151
5252 To define a new communication type, this method must be implemented.
5353 """
@@ -68,12 +68,13 @@ def communicate(self) -> None:
6868 f"Communicating data between { len (communication_pairs )} pairs of satellites"
6969 )
7070
71- if len (communication_pairs ) == comb (len (self .satellites ), 2 ):
71+ if len (communication_pairs ) == 2 * comb (len (self .satellites ), 2 ):
7272 self ._communicate_all ()
7373 else :
74- for sat_1 , sat_2 in communication_pairs :
75- sat_1 .data_store .stage_communicated_data (sat_2 .data_store .data )
76- sat_2 .data_store .stage_communicated_data (sat_1 .data_store .data )
74+ for sat_sender , sat_receiver in communication_pairs :
75+ sat_receiver .data_store .stage_communicated_data (
76+ sat_sender .data_store .data
77+ )
7778 for satellite in self .satellites :
7879 satellite .data_store .update_with_communicated_data ()
7980
@@ -116,7 +117,7 @@ def __init__(self, *args, **kwargs) -> None:
116117
117118 def communication_pairs (self ) -> list [tuple ["Satellite" , "Satellite" ]]:
118119 """Return all possible communication pairs."""
119- return list (combinations (self .satellites , 2 ))
120+ return list (permutations (self .satellites , 2 ))
120121
121122
122123class LOSCommunication (CommunicationMethod ):
@@ -177,6 +178,7 @@ def communication_pairs(self) -> list[tuple["Satellite", "Satellite"]]:
177178 for sat_2 , logger in logs .items ():
178179 if any (logger .hasAccess ):
179180 pairs .append ((sat_1 , sat_2 ))
181+ pairs .append ((sat_2 , sat_1 ))
180182 return pairs
181183
182184 def communicate (self ) -> None :
@@ -208,7 +210,7 @@ def communication_pairs(self) -> list[tuple["Satellite", "Satellite"]]:
208210 pairs = []
209211 n_components , labels = connected_components (graph , directed = False )
210212 for comp in range (n_components ):
211- for i_sat_1 , i_sat_2 in combinations (np .where (labels == comp )[0 ], 2 ):
213+ for i_sat_1 , i_sat_2 in permutations (np .where (labels == comp )[0 ], 2 ):
212214 pairs .append ((self .satellites [i_sat_1 ], self .satellites [i_sat_2 ]))
213215 return pairs
214216
@@ -222,4 +224,30 @@ class LOSMultiCommunication(MultiDegreeCommunication, LOSCommunication):
222224 pass
223225
224226
227+ class BroadcastCommunication (CommunicationMethod ):
228+ def communication_pairs (self ) -> list [tuple ["Satellite" , "Satellite" ]]:
229+ """Return pairs of satellites that used broadcast action."""
230+ broadcasters = []
231+ for satellite in self .satellites :
232+ if any (
233+ hasattr (act , "broadcast_pending" ) and act .broadcast_pending
234+ for act in satellite .action_builder .action_spec
235+ ):
236+ broadcasters .append (satellite )
237+
238+ pairs = super ().communication_pairs ()
239+ pairs = [
240+ (sat_sender , sat_receiver )
241+ for sat_sender , sat_receiver in pairs
242+ if sat_sender in broadcasters
243+ ]
244+
245+ for satellite in broadcasters :
246+ for act in satellite .action_builder .action_spec :
247+ if hasattr (act , "broadcast_pending" ):
248+ act .broadcast_pending = False
249+
250+ return pairs
251+
252+
225253__all__ = []
0 commit comments