11import logging
2- from collections .abc import Callable , Iterable , Sequence
2+ from collections .abc import Callable , Sequence
33from dataclasses import dataclass , field
44
55from umbi .datatypes import Numeric , is_numeric_a_probability
@@ -157,21 +157,23 @@ def validate(self) -> None:
157157 def new_state_choice (
158158 self ,
159159 state : int ,
160- targets : Iterable [int ] | None = None ,
161- target_prob : Callable [[int ], Numeric | None ] | None = None ,
160+ targets : Sequence [int ] | None = None ,
161+ probs : Sequence [Numeric ] | None = None ,
162+ target_prob : Callable [[int ], Numeric ] | None = None ,
162163 ) -> int :
163164 """Add a choice to the given state.
164165 :param state: source state for the new choice
165166 :param targets: optional iterable of target states for the branches of the new choice
167+ :param probs: optional probabilities for the new branches
166168 :param target_prob: optional function mapping target states to branch probabilities
167169 :return: the new choice index
168170 """
169171 # self.state_space._check_entity(state)
170172 choice = self ._new_choice ()
171173 self .state_to_choices [state ].append (choice )
172174 self ._choice_to_state [choice ] = state
173- if targets is not None and target_prob is not None :
174- self .new_choice_branches (choice , targets = targets , target_prob = target_prob )
175+ if targets is not None :
176+ self .new_choice_branches (choice , targets = targets , probs = probs , target_prob = target_prob )
175177 return choice
176178
177179 def remove_choice (self , choice : int ) -> list [int ]:
@@ -193,33 +195,56 @@ def remove_choices(self, choices: Sequence[int]) -> None:
193195 for choice in choices :
194196 self .remove_choice (choice )
195197
196- def new_choice_branch (self , choice : int , target : int | None = None , prob : Numeric | None = None ) -> int :
197- """Add a branch to the given choice and return it."""
198+ def new_choice_branch (
199+ self ,
200+ choice : int ,
201+ target : int ,
202+ prob : Numeric | None = None ,
203+ target_prob : Callable [[int ], Numeric ] | None = None ,
204+ ) -> int :
205+ """Add a branch to the given choice and return it.
206+ :param choice: source choice for the new branch
207+ :param target: target state for the new branch
208+ :param prob: optional probability for the new branch
209+ :param target_prob: optional function mapping target states to branch probabilities
210+ :note: if the ATS has branch probabilities, either prob or target_prob must be provided, but not both
211+ :return: the new branch index
212+ """
198213 self ._choice_space .check_entity (choice )
199- if target is not None :
200- self ._state_space .check_entity (target )
214+ self ._state_space .check_entity (target )
201215 new_branch = self ._new_branch ()
202216 self ._choice_to_branches [choice ].append (new_branch )
203217 self ._branch_to_choice [new_branch ] = choice
204- if target is not None :
205- self ._branch_to_target [new_branch ] = target
218+ self ._branch_to_target [new_branch ] = target
219+ if prob is None and target_prob is not None :
220+ prob = target_prob (target )
206221 if prob is not None :
207222 self ._branch_to_probability [new_branch ] = prob
208223 return new_branch
209224
210225 def new_choice_branches (
211- self , choice : int , targets : Iterable [int ], target_prob : Callable [[int ], Numeric | None ]
226+ self ,
227+ choice : int ,
228+ targets : Sequence [int ],
229+ probs : Sequence [Numeric ] | None = None ,
230+ target_prob : Callable [[int ], Numeric ] | None = None ,
212231 ) -> list [int ]:
213232 """Add branches to the given choice for multiple targets.
214233 :param choice: choice to add branches to
215234 :param targets: target states for the new branches
216- :param target_prob: function mapping target states to branch probabilities
235+ :param probs: optional probabilities for the new branches
236+ :param target_prob: optional function mapping target states to branch probabilities
237+ :note: if the ATS has branch probabilities, either probs or target_prob must be provided, but not both
217238 :return: list of new branches added
218239 """
219240 new_branches = []
220- for target in targets :
221- prob = target_prob (target )
222- branch = self .new_choice_branch (choice , target = target , prob = prob )
241+ if probs is not None and len (probs ) != len (targets ):
242+ raise ValueError ("Length of probs must match length of targets." )
243+ for target_idx , target in enumerate (targets ):
244+ prob = None
245+ if probs is not None :
246+ prob = probs [target_idx ]
247+ branch = self .new_choice_branch (choice , target = target , prob = prob , target_prob = target_prob )
223248 new_branches .append (branch )
224249 return new_branches
225250
0 commit comments