1*a65addddSAndroid Build Coastguard Worker /* 2*a65addddSAndroid Build Coastguard Worker * Copyright 2014 Google Inc. All rights reserved. 3*a65addddSAndroid Build Coastguard Worker * 4*a65addddSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*a65addddSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*a65addddSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*a65addddSAndroid Build Coastguard Worker * 8*a65addddSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*a65addddSAndroid Build Coastguard Worker * 10*a65addddSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*a65addddSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*a65addddSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*a65addddSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*a65addddSAndroid Build Coastguard Worker * limitations under the License. 15*a65addddSAndroid Build Coastguard Worker */ 16*a65addddSAndroid Build Coastguard Worker 17*a65addddSAndroid Build Coastguard Worker #ifndef FRUIT_META_GRAPH_H 18*a65addddSAndroid Build Coastguard Worker #define FRUIT_META_GRAPH_H 19*a65addddSAndroid Build Coastguard Worker 20*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/immutable_map.h> 21*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/map.h> 22*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/set.h> 23*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/triplet.h> 24*a65addddSAndroid Build Coastguard Worker 25*a65addddSAndroid Build Coastguard Worker namespace fruit { 26*a65addddSAndroid Build Coastguard Worker namespace impl { 27*a65addddSAndroid Build Coastguard Worker namespace meta { 28*a65addddSAndroid Build Coastguard Worker 29*a65addddSAndroid Build Coastguard Worker // A Graph is a Map from each node to a set containing its neighbors. 30*a65addddSAndroid Build Coastguard Worker 31*a65addddSAndroid Build Coastguard Worker using GetGraphNodes = GetImmutableMapKeys; 32*a65addddSAndroid Build Coastguard Worker 33*a65addddSAndroid Build Coastguard Worker using GraphFindNeighbors = FindInImmutableMap; 34*a65addddSAndroid Build Coastguard Worker 35*a65addddSAndroid Build Coastguard Worker using GraphContainsNode = ImmutableMapContainsKey; 36*a65addddSAndroid Build Coastguard Worker 37*a65addddSAndroid Build Coastguard Worker // Returns a loop in the given graph as a Vector<N1, ..., Nk> such that the graph contains a loop 38*a65addddSAndroid Build Coastguard Worker // N1->...->Nk->N1, or None if there are no loops. 39*a65addddSAndroid Build Coastguard Worker struct GraphFindLoop { 40*a65addddSAndroid Build Coastguard Worker template <typename G> 41*a65addddSAndroid Build Coastguard Worker struct apply { 42*a65addddSAndroid Build Coastguard Worker using ImmutableG = VectorToImmutableMap(G); 43*a65addddSAndroid Build Coastguard Worker 44*a65addddSAndroid Build Coastguard Worker // DfsVisit(VisitedSet, VisitingSet, Node) does a DFS visit starting at Node and returns a 45*a65addddSAndroid Build Coastguard Worker // Triplet<NewVisitedSet, Loop, IsLoopComplete>, where Loop is the Vector representing the part 46*a65addddSAndroid Build Coastguard Worker // of the loop starting at Node (if any loop was found) or Null otherwise. 47*a65addddSAndroid Build Coastguard Worker struct DfsVisit { 48*a65addddSAndroid Build Coastguard Worker template <typename VisitedSet, typename VisitingSet, typename Node> 49*a65addddSAndroid Build Coastguard Worker struct apply { 50*a65addddSAndroid Build Coastguard Worker using NewVisitingSet = AddToSetUnchecked(VisitingSet, Node); 51*a65addddSAndroid Build Coastguard Worker 52*a65addddSAndroid Build Coastguard Worker struct VisitSingleNeighbor { 53*a65addddSAndroid Build Coastguard Worker // CurrentResult is a Triplet<VisitedSet, Loop, IsLoopComplete> (where IsLoopComplete 54*a65addddSAndroid Build Coastguard Worker // is only meaningful when Loop is not None). 55*a65addddSAndroid Build Coastguard Worker template <typename CurrentResult, typename Neighbor> 56*a65addddSAndroid Build Coastguard Worker struct apply { 57*a65addddSAndroid Build Coastguard Worker using type = If(IsNone(typename CurrentResult::Second), 58*a65addddSAndroid Build Coastguard Worker // Go ahead, no loop found yet. 59*a65addddSAndroid Build Coastguard Worker DfsVisit(typename CurrentResult::First, NewVisitingSet, Neighbor), 60*a65addddSAndroid Build Coastguard Worker // Found a loop in another neighbor of the same node, we don't need to 61*a65addddSAndroid Build Coastguard Worker // visit this neighbor. 62*a65addddSAndroid Build Coastguard Worker CurrentResult); 63*a65addddSAndroid Build Coastguard Worker }; 64*a65addddSAndroid Build Coastguard Worker }; 65*a65addddSAndroid Build Coastguard Worker 66*a65addddSAndroid Build Coastguard Worker using NewVisitedSet = AddToSet(VisitedSet, Node); 67*a65addddSAndroid Build Coastguard Worker using Neighbors = GraphFindNeighbors(ImmutableG, Node); 68*a65addddSAndroid Build Coastguard Worker using Result = FoldVector(Neighbors, VisitSingleNeighbor, ConsTriplet(NewVisitedSet, None, Bool<false>)); 69*a65addddSAndroid Build Coastguard Worker using type = If(IsNone(Neighbors), 70*a65addddSAndroid Build Coastguard Worker // No neighbors. 71*a65addddSAndroid Build Coastguard Worker ConsTriplet(NewVisitedSet, None, Bool<false>), 72*a65addddSAndroid Build Coastguard Worker If(IsInSet(Node, VisitingSet), 73*a65addddSAndroid Build Coastguard Worker // We've just found a loop, since Node is another node that we're currently 74*a65addddSAndroid Build Coastguard Worker // visiting 75*a65addddSAndroid Build Coastguard Worker Triplet<VisitedSet, Vector<Node>, Bool<false>>, 76*a65addddSAndroid Build Coastguard Worker If(IsNone(GetSecond(Result)), 77*a65addddSAndroid Build Coastguard Worker // No loop found. 78*a65addddSAndroid Build Coastguard Worker Result, 79*a65addddSAndroid Build Coastguard Worker // Found a loop 80*a65addddSAndroid Build Coastguard Worker If(GetThird(Result) /* IsLoopComplete */, Result, 81*a65addddSAndroid Build Coastguard Worker If(VectorEndsWith(GetSecond(Result) /* Loop */, Node), 82*a65addddSAndroid Build Coastguard Worker // The loop is complete now. 83*a65addddSAndroid Build Coastguard Worker ConsTriplet(GetFirst(Result), GetSecond(Result), Bool<true>), 84*a65addddSAndroid Build Coastguard Worker // Loop still not complete, add the current node. 85*a65addddSAndroid Build Coastguard Worker ConsTriplet(GetFirst(Result), PushFront(GetSecond(Result), Node), Bool<false>)))))); 86*a65addddSAndroid Build Coastguard Worker }; 87*a65addddSAndroid Build Coastguard Worker }; 88*a65addddSAndroid Build Coastguard Worker 89*a65addddSAndroid Build Coastguard Worker struct VisitStartingAtNode { 90*a65addddSAndroid Build Coastguard Worker // CurrentResult is a Pair<CurrentVisitedSet, Loop> 91*a65addddSAndroid Build Coastguard Worker template <typename CurrentResult, typename Node> 92*a65addddSAndroid Build Coastguard Worker struct apply { 93*a65addddSAndroid Build Coastguard Worker using DfsResult = DfsVisit(GetFirst(CurrentResult), EmptySet, Node); 94*a65addddSAndroid Build Coastguard Worker using type = If(IsNone(GetSecond(CurrentResult)), 95*a65addddSAndroid Build Coastguard Worker // No loop found yet. 96*a65addddSAndroid Build Coastguard Worker MakePair(GetFirst(DfsResult), GetSecond(DfsResult)), 97*a65addddSAndroid Build Coastguard Worker // Found a loop, return early 98*a65addddSAndroid Build Coastguard Worker CurrentResult); 99*a65addddSAndroid Build Coastguard Worker }; 100*a65addddSAndroid Build Coastguard Worker }; 101*a65addddSAndroid Build Coastguard Worker 102*a65addddSAndroid Build Coastguard Worker using type = GetSecond(FoldVector(GetMapKeys(G), VisitStartingAtNode, Pair<EmptySet, None>)); 103*a65addddSAndroid Build Coastguard Worker }; 104*a65addddSAndroid Build Coastguard Worker }; 105*a65addddSAndroid Build Coastguard Worker 106*a65addddSAndroid Build Coastguard Worker } // namespace meta 107*a65addddSAndroid Build Coastguard Worker } // namespace impl 108*a65addddSAndroid Build Coastguard Worker } // namespace fruit 109*a65addddSAndroid Build Coastguard Worker 110*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_META_GRAPH_H 111