1 #ifndef CPPAD_CG_BIDIR_GRAPH_INCLUDED 2 #define CPPAD_CG_BIDIR_GRAPH_INCLUDED 27 std::vector<size_t> arguments;
28 std::vector<Path> usage;
38 using SourceCodePath =
typename CodeHandler<Base>::SourceCodePath;
40 std::map<Node*, PathNodeEdges<Base> > graph_;
44 inline bool empty()
const {
45 return graph_.empty();
48 inline void connect(
Node& node,
50 connect(graph_[&node], node, argument);
56 CPPADCG_ASSERT_UNKNOWN(argument < node.
getArguments().size());
57 CPPADCG_ASSERT_UNKNOWN(node.
getArguments()[argument].getOperation() !=
nullptr);
58 CPPADCG_ASSERT_UNKNOWN(&graph_[&node] == &nodeInfo);
60 nodeInfo.arguments.push_back(argument);
62 auto* aNode = node.
getArguments()[argument].getOperation();
66 inline bool contains(
Node& node)
const {
67 auto it = graph_.find(&node);
68 return it != graph_.end();
72 auto it = graph_.find(&node);
73 if (it != graph_.end())
80 auto it = graph_.find(&node);
81 if (it != graph_.end())
87 inline bool erase(
Node& node) {
88 return graph_.erase(&node) > 0;
101 size_t& bifIndex)
const {
103 std::vector<SourceCodePath> paths;
116 paths[0].reserve(20);
118 if (tail->usage.empty()) {
124 paths = findPathUpTo(expression, target);
125 if (paths.size() > 1)
128 if (paths[0][0].node != &expression) {
133 SourceCodePath pathCommon;
135 auto* n = paths[0][0].node;
136 auto* edges = find(*n);
137 CPPADCG_ASSERT_UNKNOWN(edges !=
nullptr);
140 n = edges->usage.begin()->node;
142 pathCommon.push_back(*edges->usage.begin());
143 if (n == &expression)
147 CPPADCG_ASSERT_UNKNOWN(edges !=
nullptr);
148 CPPADCG_ASSERT_UNKNOWN(!edges->usage.empty());
151 bifIndex = pathCommon.size();
153 std::reverse(pathCommon.begin(), pathCommon.end());
155 p.insert(p.begin(), pathCommon.begin(), pathCommon.end());
166 std::vector<SourceCodePath> findPathUpTo(
Node& node,
167 Node& target)
const {
170 auto* edges = find(*n);
171 CPPADCG_ASSERT_UNKNOWN(edges !=
nullptr);
173 std::vector<SourceCodePath> paths;
177 while (!edges->arguments.empty()) {
178 if (edges->arguments.size() > 1) {
180 size_t a1Index = edges->arguments[0];
181 const auto& a1 = n->getArguments()[a1Index];
182 paths = findPathUpTo(*a1.getOperation(), target);
183 if (paths.size() == 2) {
187 size_t a2Index = edges->arguments[1];
188 const auto& a2 = n->getArguments()[a2Index];
189 auto paths2 = findPathUpTo(*a2.getOperation(), target);
190 if (paths2.size() == 2) {
197 paths[1].reserve(paths2[0].size() + 1);
199 paths[1].insert(paths[1].begin() + 1, paths2[0].begin(), paths2[0].end());
203 size_t argIndex1 = *edges->arguments.begin();
206 n = n->getArguments()[argIndex1].getOperation();
208 CPPADCG_ASSERT_UNKNOWN(edges !=
nullptr);
217 void findPathDownThenUp() {
218 for (
const auto& arg0: tail->usage) {
224 size_t argIndex = arg0.argIndex;
227 CPPADCG_ASSERT_UNKNOWN(edges !=
nullptr);
232 if(edges->arguments.size() != 1)
235 if(edges->usage.empty())
237 n = edges->usage.begin()->node;
238 argIndex = edges->usage.begin()->argIndex;
241 CPPADCG_ASSERT_UNKNOWN(edges !=
nullptr);
244 CPPADCG_ASSERT_UNKNOWN(!edges->arguments.empty());
251 std::reverse(paths[0].begin(), paths[0].end());
253 if (edges->arguments.size() == 1) {
260 paths[1].reserve(20);
266 auto* n1 = paths[0][1].node;
267 size_t argIndex1 = n->
getArguments()[edges->arguments[0]].getOperation() == n1? edges->arguments[1]: edges->arguments[0];
273 CPPADCG_ASSERT_UNKNOWN(edges !=
nullptr);
275 while (!edges->arguments.empty()) {
276 argIndex1 = *edges->arguments.begin();
281 CPPADCG_ASSERT_UNKNOWN(edges !=
nullptr);
std::vector< SourceCodePath > findSingleBifurcation(Node &expression, Node &target, size_t &bifIndex) const
const std::vector< Argument< Base > > & getArguments() const