#include "dag_layout.h" using namespace dags; using namespace graph_data; DAGLayerHelper::DAGLayerHelper(const Node& bind) : bind_node(bind) { } Node DAGLayerHelper::bindPoint() const { return this->bind_node; } int& dags::DAGLayerHelper::inputCount() { return this->input_count; } int dags::DAGLayerHelper::layerValue() const { return this->layer_v; } void dags::DAGLayerHelper::setLayerValue(int v) { this->layer_v = v; } void DAGLayerHelper::nextAppend(std::shared_ptr inst) { if (this->next_points.contains(inst)) return; this->next_points.append(inst); inst->input_count++; } QList> DAGLayerHelper::nextNodes() const { return this->next_points; } DAGOrderHelper::DAGOrderHelper(std::shared_ptr bind) : layer_bind(bind) { this->layer_number = bind->layerValue(); } DAGOrderHelper::DAGOrderHelper(std::shared_ptr f, std::shared_ptr t) : relate_bind(f), towards_to(t) { } bool DAGOrderHelper::isFakeNode() const { return !this->layer_bind; } std::shared_ptr dags::DAGOrderHelper::layerNode() const { return this->layer_bind; } std::shared_ptr dags::DAGOrderHelper::tailsNode() const { return this->relate_bind; } std::shared_ptr dags::DAGOrderHelper::headsNode() const { return this->towards_to; } int dags::DAGOrderHelper::layerNumber() const { return this->layer_number; } void dags::DAGOrderHelper::setLayerNumber(int v) { this->layer_number = v; } QVariant dags::DAGOrderHelper::sortNumber() const { return this->sort_number; } void dags::DAGOrderHelper::setSortNumber(double v) { this->sort_number = v; } QList> DAGOrderHelper::getUpstreamNodes() const { return this->__prev_layer_nodes; } void DAGOrderHelper::appendUpstreamNode(std::shared_ptr inst) { this->__prev_layer_nodes.append(inst); } void DAGGraph::rebuildFromEdges(const QList& arrow_list) { for (auto& arr : arrow_list) { auto start = arr.startPoint(); std::shared_ptr start_helper; if (this->graph_inst.contains(start.name())) { start_helper = this->graph_inst[start.name()]; } else { start_helper = std::make_shared(start); this->graph_inst[start.name()] = start_helper; } auto end = arr.endPoint(); std::shared_ptr< DAGLayerHelper> end_helper; if (this->graph_inst.contains(end.name())) { end_helper = this->graph_inst[end.name()]; } else { end_helper = std::make_shared(end); this->graph_inst[end.name()] = end_helper; } start_helper->nextAppend(end_helper); } } QList> dags::DAGGraph::nodeWithLayout() const { return this->node_with_layout; } int dags::DAGGraph::maxLayerCount() const { return this->max_layer_count; } std::shared_ptr DAGGraph::spawns_peak(QList>& ref_set) { for (auto inst : ref_set) { if (!inst->inputCount()) { for (auto it_nxt : inst->nextNodes()) { it_nxt->inputCount()--; if (!ref_set.contains(it_nxt)) ref_set << it_nxt; } ref_set.removeAll(inst); this->graph_inst.remove(inst->bindPoint().name()); return inst; } } for (auto inst : this->graph_inst.values()) { if (!inst->inputCount()) { if (ref_set.contains(inst)) ref_set.removeAll(inst); for (auto it_nxt : inst->nextNodes()) { it_nxt->inputCount()--; if (!ref_set.contains(it_nxt)) ref_set << it_nxt; } this->graph_inst.remove(inst->bindPoint().name()); return inst; } } if (this->graph_inst.size()) { throw "在有向无环图中发现环形回路。"; } return std::shared_ptr(); } void DAGGraph::graph_recovery(const QList>& sort_seqs) { for (auto it : sort_seqs) { it->inputCount() = 0; } for (auto it : sort_seqs) { for (auto nxt : it->nextNodes()) { nxt->inputCount()++; } } this->graph_inst.clear(); for (auto it : sort_seqs) { this->graph_inst[it->bindPoint().name()] = it; } } int DAGGraph::node_layering(const std::shared_ptr& inst, int layer_current) { auto max_remains = layer_current; if (!layer_current || inst->layerValue() < layer_current) { inst->setLayerValue(layer_current); for (auto fork : inst->nextNodes()) { max_remains = std::max(this->node_layering(fork, inst->layerValue() + 1), max_remains); } } return max_remains + 1; } int DAGGraph::node_layering_adj(std::shared_ptr inst) { if (inst->inputCount() > 1) return inst->layerValue() - 1; if (!inst->nextNodes().size()) return inst->layerValue() - 1; auto layer_number = INT_MAX; for (auto cinst : inst->nextNodes()) { layer_number = std::min(layer_number, this->node_layering_adj(cinst)); } inst->setLayerValue(layer_number); return inst->layerValue() - 1; } QList> DAGGraph::tidy_graph_nodes() { QHash> nodes_temp; for (auto node : this->graph_inst.values()) { nodes_temp[node->bindPoint().name()] = std::make_shared(node); } QList> temp_array(nodes_temp.values()); for (auto node : this->graph_inst.values()) { for (auto next : node->nextNodes()) { auto node_links = QList>{ nodes_temp[node->bindPoint().name()] }; for (auto layer_index = node->layerValue() + 1; layer_index < next->layerValue(); ++layer_index) { node_links.append(std::make_shared(node, next)); node_links.last()->setLayerNumber(layer_index); } node_links.append(nodes_temp[next->bindPoint().name()]); for (auto idx = 1; idx < node_links.size(); ++idx) { auto start_point = node_links[idx - 1]; auto end_point = node_links[idx]; end_point->appendUpstreamNode(start_point); } temp_array.append(node_links.mid(1, node_links.size() - 2)); } } return temp_array; } #include void DAGGraph::graph_layer_nodes_sort_forward(int layer_index, const QList>& nodes) { QList> nodes_within_current_layer; std::copy_if(nodes.begin(), nodes.end(), std::back_inserter(nodes_within_current_layer), [=](std::shared_ptr ins) { return ins->layerNumber() == layer_index; }); if (nodes_within_current_layer.size()) { // 计算当前层次所有节点排序 if (!layer_index) { for (auto idx = 0; idx < nodes_within_current_layer.size(); ++idx) { auto target_node = nodes_within_current_layer[idx]; if (target_node->sortNumber().isNull()) target_node->setSortNumber(idx + 1); } } else if (layer_index > 0) { QList> nodes_fixed; for (auto target_node : nodes_within_current_layer) { auto upstream_list = target_node->getUpstreamNodes(); std::sort(upstream_list.begin(), upstream_list.end(), [](std::shared_ptr a, std::shared_ptr b) { return a->sortNumber() < b->sortNumber(); }); if (upstream_list.size()) { auto sort_anchor = upstream_list[(upstream_list.size() - 1) / 2]; target_node->setSortNumber(sort_anchor->sortNumber().toInt()); nodes_fixed << sort_anchor; } } QList> nodes_hangout; std::copy_if(nodes_within_current_layer.begin(), nodes_within_current_layer.end(), std::back_inserter(nodes_hangout), [](std::shared_ptr ins) { return ins->sortNumber().isNull(); }); if (nodes_hangout.size()) { auto min_anchor = std::min_element(nodes_fixed.begin(), nodes_fixed.end(), [](std::shared_ptr a, std::shared_ptr b) { return a->sortNumber() < b->sortNumber(); }); for (int idx = 0; idx < nodes_hangout.size(); ++idx) { nodes_hangout[idx]->setSortNumber((*min_anchor)->sortNumber().toInt() - idx - 1); } } std::sort(nodes_within_current_layer.begin(), nodes_within_current_layer.end(), [](std::shared_ptr a, std::shared_ptr b) { return a->sortNumber() < b->sortNumber(); }); // 提取当前层次节点排序值 this->current_nodelist_filling_indi(nodes_within_current_layer); } this->nodes_sort_with_above(layer_index, nodes); this->graph_layer_nodes_sort_forward(layer_index + 1, nodes); } } /* bool dags::DAGGraph::current_layer_filling_indi(int layer_index, const QList>& nodes) { // 提取本层次节点 QList> nodes_within_current_layer; std::copy_if(nodes.begin(), nodes.end(), std::back_inserter(nodes_within_current_layer), [=](std::shared_ptr ins) { return ins->layerNumber() == layer_index; }); if (!nodes_within_current_layer.size()) return false; std::sort(nodes_within_current_layer.begin(), nodes_within_current_layer.end(), [](std::shared_ptra, std::shared_ptr b)->bool { auto prevs_a = a->getUpstreamNodes(); auto prevs_b = b->getUpstreamNodes(); if (!prevs_a.size() && !prevs_b.size()) return a > b; if (!prevs_a.size()) return true; if (!prevs_b.size()) return false; auto upnode_a = std::min_element(prevs_a.begin(), prevs_a.end(), [](std::shared_ptr a, std::shared_ptr b) { return a->sortNumber() < b->sortNumber(); }); auto upnode_b = std::min_element(prevs_b.begin(), prevs_b.end(), [](std::shared_ptr a, std::shared_ptr b) { return a->sortNumber() < b->sortNumber(); }); return (*upnode_a)->sortNumber() < (*upnode_b)->sortNumber(); }); this->current_nodelist_filling_indi(nodes_within_current_layer); } */ bool dags::DAGGraph::current_nodelist_filling_indi(const QList>& nodes_within_current_layer) { // 提取节点划分档次 QList ordered_values; std::transform(nodes_within_current_layer.begin(), nodes_within_current_layer.end(), std::back_inserter(ordered_values), [=](std::shared_ptr ins) { return ins->sortNumber().toInt(); }); ordered_values = ordered_values.toSet().toList(); std::sort(ordered_values.begin(), ordered_values.end()); if (ordered_values.size() == nodes_within_current_layer.size()) return false; // 填缝 ordered_values << ordered_values.last() + 1; for (auto idx = 1; idx < ordered_values.size(); ++idx) { auto prev_sortv = ordered_values[idx - 1]; auto curr_sortv = ordered_values[idx]; QList> pick_ups; std::copy_if(nodes_within_current_layer.begin(), nodes_within_current_layer.end(), std::back_inserter(pick_ups), [=](std::shared_ptr ins) { return ins->sortNumber() >= prev_sortv && ins->sortNumber() < curr_sortv; }); for (int idx = 0; idx < std::min(curr_sortv - prev_sortv, pick_ups.size()); idx++) { auto target_node = pick_ups[idx]; target_node->setSortNumber(prev_sortv + idx); } if (curr_sortv - prev_sortv < pick_ups.size()) { auto npicks = pick_ups.mid(curr_sortv - prev_sortv); auto inc_span = 1.0 / (npicks.size() + 4); for (auto idx = 0; idx < npicks.size(); ++idx) { auto nsortv = curr_sortv - 1 + (idx + 1) * inc_span; npicks[idx]->setSortNumber(nsortv); } } } return true; } void dags::DAGGraph::nodes_sort_with_above(int layer_index, const QList>& nodes) { // 提取所有已知节点 QList> sorting_nodes; std::copy_if(nodes.begin(), nodes.end(), std::back_inserter(sorting_nodes), [&](std::shared_ptr n) { return n->layerNumber() <= layer_index; }); // 排序值提取与重排 QList sort_values; std::transform(sorting_nodes.begin(), sorting_nodes.end(), std::back_inserter(sort_values), [](std::shared_ptr n)->double { return n->sortNumber().toDouble(); }); sort_values = sort_values.toSet().toList(); std::sort(sort_values.begin(), sort_values.end()); // 检索排序中轴 auto temp_anchor = std::make_pair(DBL_MAX, -1); for (int nidx = 0; nidx < sort_values.size(); ++nidx) { auto value_span = std::abs(sort_values[nidx]); if (value_span <= temp_anchor.first) temp_anchor = std::make_pair(value_span, nidx); } // 排序值重整 for (int sorting_idx = 0; sorting_idx < sorting_nodes.size(); ++sorting_idx) { auto node = sorting_nodes[sorting_idx]; auto node_sortv = node->sortNumber().toDouble(); auto sort_idx = sort_values.indexOf(node_sortv); node->setSortNumber(sort_idx - temp_anchor.second); } //for (auto n : sorting_nodes) { // qDebug() << n->layerNumber() << n->sortNumber().toDouble(); //} //qDebug() << "=============================="; } void dags::DAGGraph::graph_adjust_after_layout(const QList>& total_nodes) { auto layer_index = this->maxLayerCount() - 1; while (layer_index > -1) { auto nlist = this->layer_adjust_via_next_sibling(layer_index, total_nodes); if (this->current_nodelist_filling_indi(nlist)) this->nodes_sort_with_belows(layer_index, total_nodes); layer_index--; }; } QList> dags::DAGGraph::layer_adjust_via_next_sibling(int curr_layer, const QList>& total_nodes) { QList> curr_layer_nodes; std::copy_if(total_nodes.begin(), total_nodes.end(), std::back_inserter(curr_layer_nodes), [&](std::shared_ptr inst) { return inst->layerNumber() == curr_layer; }); for (auto node : curr_layer_nodes) { this->node_adjust_via_next_sibling(node, total_nodes); } std::sort(curr_layer_nodes.begin(), curr_layer_nodes.end(), [](std::shared_ptra, std::shared_ptr b)->bool { auto prevs_a = a->getUpstreamNodes(); auto prevs_b = b->getUpstreamNodes(); if (!prevs_a.size() && !prevs_b.size()) return a > b; if (!prevs_a.size()) return true; if (!prevs_b.size()) return false; auto upnode_a = std::min_element(prevs_a.begin(), prevs_a.end(), [](std::shared_ptr a, std::shared_ptr b) { return a->sortNumber() < b->sortNumber(); }); auto upnode_b = std::min_element(prevs_b.begin(), prevs_b.end(), [](std::shared_ptr a, std::shared_ptr b) { return a->sortNumber() < b->sortNumber(); }); return (*upnode_a)->sortNumber() < (*upnode_b)->sortNumber(); }); return curr_layer_nodes; } void dags::DAGGraph::node_adjust_via_next_sibling(std::shared_ptr curr_node, const QList>& total_nodes) { // 计算下游调整参考节点 QList> next_layer_nodes; std::copy_if(total_nodes.begin(), total_nodes.end(), std::back_inserter(next_layer_nodes), [&](std::shared_ptr inst) { if (inst->layerNumber() == curr_node->layerNumber() + 1) { if (curr_node->isFakeNode()) { if (inst->isFakeNode()) { return curr_node->tailsNode() == inst->tailsNode() && curr_node->headsNode() == inst->headsNode(); } return curr_node->headsNode() == inst->layerNode(); } else { if (inst->isFakeNode()) { return curr_node->layerNode() == inst->tailsNode(); } else { auto next_vnodes = curr_node->layerNode()->nextNodes(); return next_vnodes.contains(inst->layerNode()); } } } return false; }); std::sort(next_layer_nodes.begin(), next_layer_nodes.end(), [](std::shared_ptr a, std::shared_ptr b) { return a->sortNumber() < b->sortNumber(); }); if (next_layer_nodes.size()) { curr_node->setSortNumber(next_layer_nodes.first()->sortNumber().toDouble()); } } void dags::DAGGraph::nodes_sort_with_belows(int curr_layer, const QList>& total_nodes) { // 提取所有已知节点 QList> sorting_nodes; std::copy_if(total_nodes.begin(), total_nodes.end(), std::back_inserter(sorting_nodes), [=](std::shared_ptr ins) { return ins->layerNumber() >= curr_layer; }); // 排序值提取与重排 QList sort_values; std::transform(sorting_nodes.begin(), sorting_nodes.end(), std::back_inserter(sort_values), [](std::shared_ptr n)->double { return n->sortNumber().toDouble(); }); sort_values = sort_values.toSet().toList(); std::sort(sort_values.begin(), sort_values.end()); // 检索排序中轴 auto temp_anchor = std::make_pair(DBL_MAX, -1); for (int nidx = 0; nidx < sort_values.size(); ++nidx) { auto value_span = std::abs(sort_values[nidx]); if (value_span <= temp_anchor.first) temp_anchor = std::make_pair(value_span, nidx); } // 排序值重整 for (int sorting_idx = 0; sorting_idx < sorting_nodes.size(); ++sorting_idx) { auto node = sorting_nodes[sorting_idx]; auto sort_idx = sort_values.indexOf(node->sortNumber().toDouble()); node->setSortNumber(sort_idx - temp_anchor.second); } } void dags::DAGGraph::node_adjust_ingraph_forward(const QList>& total_nodes) { int layer_index = 0; while (this->node_adjust_inlayer_forward(layer_index, total_nodes)) { this->sort_index_partition_indi(layer_index, total_nodes); this->nodes_sort_with_above(layer_index, total_nodes); layer_index++; } //for (auto idx = 0; idx < layer_index; ++idx) { // this->sort_index_partition_indi(idx, total_nodes); // this->nodes_sort_with_above(idx, total_nodes); //} } bool dags::DAGGraph::node_adjust_inlayer_forward(int curr_layer, const QList>& total_nodes) { // 挑选当前层次节点 QList> curr_layer_nodes; std::copy_if(total_nodes.begin(), total_nodes.end(), std::back_inserter(curr_layer_nodes), [&](std::shared_ptr inst) { return inst->layerNumber() == curr_layer; }); if (!curr_layer_nodes.size()) return false; // 计算排序系数 QList, qlonglong, qlonglong, qlonglong, qlonglong>> orders_helper; std::transform(curr_layer_nodes.begin(), curr_layer_nodes.end(), std::back_inserter(orders_helper), [&](std::shared_ptr ins) { auto val_p = this->node_evaluate_with_upstream(ins, total_nodes); auto val_n = this->node_evaluate_with_downstream(ins, total_nodes); return std::make_tuple(ins, val_n.first, val_n.second, val_p.first, val_p.second); }); // 排序当前层次节点 std::sort(orders_helper.begin(), orders_helper.end(), []( std::tuple, qlonglong, qlonglong, qlonglong, qlonglong> a, std::tuple, qlonglong, qlonglong, qlonglong, qlonglong> b) { auto prev_nodesa = std::get<0>(a)->getUpstreamNodes(); auto prev_nodesb = std::get<0>(b)->getUpstreamNodes(); if (!prev_nodesa.size() && !prev_nodesb.size()) return a < b; if (prev_nodesa.size() && prev_nodesb.size()) { if (std::get<3>(a) == std::get<3>(b)) { if (std::get<4>(a) == std::get<4>(b)) { if (std::get<1>(a) == std::get<1>(b)) { return std::get<2>(a) < std::get<2>(b); } return std::get<1>(a) < std::get<1>(b); } return std::get<4>(a) < std::get<4>(b); } return std::get<3>(a) < std::get<3>(b); } if (prev_nodesa.size()) { return false; } return true; //if (std::get<1>(a) == std::get<1>(b)) { // if (std::get<2>(a) == std::get<2>(b)) { // if (std::get<3>(a) == std::get<3>(b)) { // return std::get<4>(a) < std::get<4>(b); // } // return std::get<3>(a) < std::get<3>(b); // } // return std::get<2>(a) < std::get<2>(b); //} //return std::get<1>(a) < std::get<1>(b); }); QList sort_values; std::transform(curr_layer_nodes.begin(), curr_layer_nodes.end(), std::back_inserter(sort_values), [](std::shared_ptr ins) { return ins->sortNumber().toInt(); }); std::sort(sort_values.begin(), sort_values.end()); // 重新设定节点次序 for (auto idx = 0; idx < sort_values.size(); ++idx) { std::get<0>(orders_helper[idx])->setSortNumber(sort_values[idx]); } return true; } bool dags::DAGGraph::sort_index_partition_indi(int layer_index, const QList>& total_nodes) { // 提取层次节点并排序节点 QList> nodes_within_current_layer; std::copy_if(total_nodes.begin(), total_nodes.end(), std::back_inserter(nodes_within_current_layer), [=](std::shared_ptr inst) { return layer_index == inst->layerNumber(); }); std::sort(nodes_within_current_layer.begin(), nodes_within_current_layer.end(), [](std::shared_ptr a, std::shared_ptr b) { return a->sortNumber() < b->sortNumber(); }); if (!nodes_within_current_layer.size()) return false; // 获取布局系数 QList, QVariant>> sort_helper; for (auto& inst : nodes_within_current_layer) { auto prev_nodes = inst->getUpstreamNodes(); if (!prev_nodes.size()) { sort_helper.append(std::make_pair(inst, QVariant())); continue; } auto anchor_it = std::min_element(prev_nodes.begin(), prev_nodes.end(), [](std::shared_ptr a, std::shared_ptr b) { return a->layerNumber() < b->layerNumber(); }); sort_helper.append(std::make_pair(inst, (*anchor_it)->sortNumber())); } QList sort_backup; std::transform(sort_helper.begin(), sort_helper.end(), std::back_inserter(sort_backup), [](std::pair, QVariant> u) { return u.second; }); auto aligned_items_count = std::count_if(sort_backup.begin(), sort_backup.end(), [](QVariant u) { return !u.isNull(); }); if (!aligned_items_count) return false; // 补全布局系数 QVariant start_value; for (auto idx = 0; idx < sort_helper.size(); ++idx) { auto curr_u = sort_helper[idx]; if (!curr_u.second.isNull()) { start_value = curr_u.second; if (idx > 0) { auto u = sort_helper[0]; sort_helper[0] = std::make_pair(u.first, start_value.toInt() - 1); } break; } } for (int idx = 1; idx < sort_helper.size(); ++idx) { auto prev_u = sort_helper[idx - 1]; auto curr_u = sort_helper[idx]; if (curr_u.second.isNull()) { sort_helper[idx] = std::make_pair(curr_u.first, prev_u.second); } if (curr_u.second < prev_u.second) { sort_helper[idx] = std::make_pair(curr_u.first, prev_u.second); } } double sub_sum = 0; // 计算修正系数 for (auto ndx = 0; ndx < sort_backup.size(); ndx++) { auto valbk = sort_backup[ndx]; auto val2 = sort_helper[ndx].second; if (!valbk.isNull()) { sub_sum += val2.toDouble() - valbk.toDouble(); } } auto val_revised = sub_sum / aligned_items_count; std::for_each(sort_helper.begin(), sort_helper.end(), [=](std::pair, QVariant> u) { u.first->setSortNumber(u.second.toDouble() - val_revised); }); this->current_nodelist_filling_indi(nodes_within_current_layer); return true; } std::pair dags::DAGGraph::node_evaluate_with_downstream(std::shared_ptr node, const QList>& total_nodes) { decltype(node) next_node; if (node->isFakeNode()) { auto n_data = node->headsNode(); next_node = *std::find_if(total_nodes.begin(), total_nodes.end(), [&](decltype(node) n) { if (!n->isFakeNode()) { return n->layerNode() == n_data; } return false; }); } else { auto n_datas = node->layerNode()->nextNodes(); if (!n_datas.size()) return std::make_pair(node->layerNumber(), node->sortNumber().toLongLong()); QList> next_nodes; std::transform(n_datas.begin(), n_datas.end(), std::back_inserter(next_nodes), [&](std::shared_ptr inst) { auto rst = std::find_if(total_nodes.begin(), total_nodes.end(), [&](decltype(node) n) { if (!n->isFakeNode()) { return n->layerNode() == inst; } return false; }); return *rst; }); next_node = *std::min_element(next_nodes.begin(), next_nodes.end(), [](std::shared_ptr a, std::shared_ptr b) { if (a->layerNumber() == b->layerNumber()) return a->sortNumber() < b->sortNumber(); return a->layerNumber() < b->layerNumber(); }); } return std::make_pair(next_node->layerNumber(), next_node->sortNumber().toLongLong()); } std::pair dags::DAGGraph::node_evaluate_with_upstream(std::shared_ptr node, const QList>& total_nodes) { auto prim_nodes = node->getUpstreamNodes(); if (!prim_nodes.size()) return std::make_pair(node->layerNumber(), node->sortNumber().toLongLong()); QList> prev_nodes; std::transform(prim_nodes.begin(), prim_nodes.end(), std::back_inserter(prev_nodes), [&](std::shared_ptr ins) { if (!ins->isFakeNode()) { return ins; } auto prev_data = ins->tailsNode(); auto target_it = std::find_if(total_nodes.begin(), total_nodes.end(), [&](std::shared_ptr nins) { if (!nins->isFakeNode()) return nins->layerNode() == prev_data; return false; }); return *target_it; }); auto prev_it = std::min_element(prev_nodes.begin(), prev_nodes.end(), [](std::shared_ptr a, std::shared_ptr b) { if (a->layerNumber() == b->layerNumber()) return a->sortNumber() < b->sortNumber(); return a->layerNumber() < b->layerNumber(); }); return std::make_pair((*prev_it)->layerNumber(), (*prev_it)->sortNumber().toLongLong()); } void dags::DAGGraph::primitiveGraphLayout() { QList> sort_seqs; QList> refs; while (1) { auto peaks = this->spawns_peak(refs); if (!peaks) break; sort_seqs.append(peaks); } this->graph_recovery(sort_seqs); for (auto item : sort_seqs) { if (!item->inputCount()) { this->max_layer_count = std::max(this->max_layer_count, this->node_layering(item, 0)); } } for (auto item : sort_seqs) { if (!item->inputCount()) { this->node_layering_adj(item); } } auto tidy_nodes = this->tidy_graph_nodes(); this->graph_layer_nodes_sort_forward(0, tidy_nodes); this->node_with_layout = tidy_nodes; } void dags::DAGGraph::forwardsLayoutImpls() { this->graph_layer_nodes_sort_forward(0, this->node_with_layout); } void dags::DAGGraph::backwardsLayoutImpls() { this->graph_adjust_after_layout(this->node_with_layout); } void dags::DAGGraph::adjustLayoutImpls() { this->node_adjust_ingraph_forward(this->node_with_layout); }