def _unfold(self, op: Operator, n: int) -> Optional[Operator]: """Unroll all possible operators from the grammar `g` starting from non-terminal `op` after `n` derivations. Parameters ---------- op : Operator starting rule (e.g., `g.start`) n : int number of derivations Returns ------- Optional[Operator] """ if isinstance(op, BasePipeline): steps = op.steps_list() new_maybe_steps: List[Optional[Operator]] = [ self._unfold(sop, n) for sop in op.steps_list() ] if None not in new_maybe_steps: new_steps: List[Operator] = cast(List[Operator], new_maybe_steps) step_map = {steps[i]: new_steps[i] for i in range(len(steps))} new_edges = [(step_map[s], step_map[d]) for s, d in op.edges()] return make_pipeline_graph(new_steps, new_edges, True) else: return None if isinstance(op, OperatorChoice): steps = [ s for s in (self._unfold(sop, n) for sop in op.steps_list()) if s ] return make_choice(*steps) if steps else None if isinstance(op, NonTerminal): return self._unfold(self._variables[op.name()], n - 1) if n > 0 else None if isinstance(op, IndividualOp): return op assert False, f"Unknown operator {op}"
def _sample(self, op: Operator, n: int) -> Optional[Operator]: """ Sample the grammar `g` starting from `g.start`, that is, choose one element at random for each possible choices. Parameters ---------- op : Operator starting rule (e.g., `g.start`) n : int number of derivations Returns ------- Optional[Operator] """ if isinstance(op, BasePipeline): steps = op.steps_list() new_maybe_steps: List[Optional[Operator]] = [ self._sample(sop, n) for sop in op.steps_list() ] if None not in new_maybe_steps: new_steps: List[Operator] = cast(List[Operator], new_maybe_steps) step_map = {steps[i]: new_steps[i] for i in range(len(steps))} new_edges = [(step_map[s], step_map[d]) for s, d in op.edges()] return make_pipeline_graph(new_steps, new_edges, True) else: return None if isinstance(op, OperatorChoice): return self._sample(random.choice(op.steps_list()), n) if isinstance(op, NonTerminal): return self._sample(getattr(self, op.name()), n - 1) if n > 0 else None if isinstance(op, IndividualOp): return op assert False, f"Unknown operator {op}"