in onnxconverter_common/topology.py [0:0]
def topological_operator_iterator(self):
"""
This is an iterator of all operators in Topology object.
Operators may be produced in a topological order. If you want to
simply go though all operators without considering their
topological structure, please use another function,
unordered_operator_iterator.
"""
self._initialize_graph_status_for_traversing()
priorities = {
'tensorToProbabilityMap': 2,
'tensorToLabel': 1
}
while not all(operator.is_evaluated for scope in self.scopes
for operator in scope.operators.values()):
is_evaluation_happened = False
for operator in sorted(self.unordered_operator_iterator(),
key=lambda op: priorities[op.type]
if op.type in priorities else 0):
if (all(variable.is_fed for variable in operator.inputs)
and not operator.is_evaluated):
# Check if over-writing problem occurs (i.e., multiple
# operators produce results on one variable).
for variable in operator.outputs:
# Throw an error if this variable has been treated as
# an output somewhere
if variable.is_fed:
raise RuntimeError(
"A variable is already assigned ({}) "
"for operator '{}' (name='{}'). This "
"may still happen if a converter is a "
"combination of sub-operators and one of "
"of them is producing this output. "
"In that case, an identity node must be "
"added.".format(
variable, operator.type,
operator.onnx_name))
# Mark this variable as filled
variable.is_fed = True
# Make this operator as handled
operator.is_evaluated = True
is_evaluation_happened = True
# Send out an operator
yield operator
# This step may create new nodes if the
# the converter is called while looping on
# the nodes. The outputs of an operator
# are not necessary the inputs of the next
# one and but can processed by other ONNX nodes
# inserted in the container. As a result, some
# variables never have is_fed set to True which
# is updated now unless they are an operator
# output.
known_outputs = {}
for op in self.unordered_operator_iterator():
for out in op.outputs:
if hasattr(out, 'onnx_name'):
known_outputs[out.onnx_name] = out
else:
known_outputs[out] = out
for variable in self.unordered_variable_iterator():
if variable.is_fed:
continue
if variable.onnx_name in known_outputs:
continue
update = False if self.root_names and variable.onnx_name not in self.root_names else True
if update:
variable.is_fed = True
is_evaluation_happened = True
# After scanning through the whole computational graph, at
# least one operator should be evaluated. If not, we need
# to terminate this procedure to avoid dead lock.
if not is_evaluation_happened:
break