in ax/core/batch_trial.py [0:0]
def is_factorial(self) -> bool:
"""Return true if the trial's arms are a factorial design with
no linked factors.
"""
# To match the model behavior, this should probably actually be pulled
# from exp.parameters. However, that seems rather ugly when this function
# intuitively should just depend on the arms.
sufficient_factors = all(len(arm.parameters or []) >= 2 for arm in self.arms)
if not sufficient_factors:
return False
param_levels: DefaultDict[str, Dict[Union[str, float], int]] = defaultdict(dict)
for arm in self.arms:
for param_name, param_value in arm.parameters.items():
# Expected `Union[float, str]` for 2nd anonymous parameter to call
# `dict.__setitem__` but got `Optional[Union[bool, float, str]]`.
# pyre-fixme[6]: Expected `Union[float, str]` for 1st param but got `...
param_levels[param_name][param_value] = 1
param_cardinality = 1
for param_values in param_levels.values():
param_cardinality *= len(param_values)
return len(self.arms) == param_cardinality