| 1105 | } |
| 1106 | |
| 1107 | void FixOperatorOrdering(Model* model) { |
| 1108 | std::unordered_set<string> arrays_behind_us; |
| 1109 | for (const auto& array_entry : model->GetArrayMap()) { |
| 1110 | if (!GetOpWithOutput(*model, array_entry.first)) { |
| 1111 | arrays_behind_us.insert(array_entry.first); |
| 1112 | } |
| 1113 | } |
| 1114 | arrays_behind_us.insert(model->optional_arrays.begin(), |
| 1115 | model->optional_arrays.end()); |
| 1116 | std::vector<std::unique_ptr<Operator>> old_operators; |
| 1117 | std::swap(old_operators, model->operators); |
| 1118 | std::set<std::size_t> remaining; |
| 1119 | for (std::size_t i = 0; i < old_operators.size(); i++) { |
| 1120 | remaining.insert(i); |
| 1121 | } |
| 1122 | std::unordered_map<string, string> reason_why_leftover; |
| 1123 | while (true) { |
| 1124 | bool inserted_something = false; |
| 1125 | for (const auto& i : remaining) { |
| 1126 | bool can_insert = true; |
| 1127 | auto& op = old_operators[i]; |
| 1128 | CHECK(op); |
| 1129 | for (const auto& input : op->inputs) { |
| 1130 | if (!IsConstantParameterArray(*model, input) && |
| 1131 | !arrays_behind_us.count(input)) { |
| 1132 | for (const string& output : op->outputs) { |
| 1133 | reason_why_leftover[output] = input; |
| 1134 | } |
| 1135 | can_insert = false; |
| 1136 | break; |
| 1137 | } |
| 1138 | } |
| 1139 | if (can_insert) { |
| 1140 | model->operators.emplace_back(nullptr); |
| 1141 | for (const auto& output : op->outputs) { |
| 1142 | arrays_behind_us.insert(output); |
| 1143 | } |
| 1144 | std::swap(op, model->operators.back()); |
| 1145 | remaining.erase(i); |
| 1146 | inserted_something = true; |
| 1147 | break; |
| 1148 | } |
| 1149 | } |
| 1150 | if (!inserted_something) { |
| 1151 | break; |
| 1152 | } |
| 1153 | } |
| 1154 | if (!remaining.empty()) { |
| 1155 | LOG(ERROR) |
| 1156 | << "No viable ordering of operators was found. " |
| 1157 | << "Here is a 'backtrace' of at least one part of the graph that is " |
| 1158 | << "problematic. It starts with the first operator that has as " |
| 1159 | << "problematic input array, and then walks back the graph to " |
| 1160 | << "the operator that produced that input array, etc., until we find " |
| 1161 | << "the root cause:"; |
| 1162 | LOG(ERROR) << "BEGIN TRACE OF OPERATOR WITH BAD INPUT"; |
| 1163 | LOG(ERROR) << "Here is the first-encountered operator with a bad input: "; |
| 1164 | const Operator* bad_op = old_operators[*remaining.begin()].get(); |
no test coverage detected