blob: fa3d0ddf55e67883fb81e890dbc90f872994f8e8 [file] [log] [blame]
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -07001/*
2 * Copyright 2014 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18package org.onlab.graph;
19
20
21import java.util.Map;
22import java.util.List;
23import java.util.HashMap;
24import java.util.HashSet;
25import java.util.Set;
26import java.util.Random;
27
28
29/**
30 * SRLG Graph Search finds a pair of paths with disjoint risk groups; i.e
31 * if one path goes through an edge in risk group 1, the other path will go
32 * through no edges in risk group 1.
33 */
Jonathan Hartd9df7bd2015-11-10 17:10:25 -080034public class SrlgGraphSearch<V extends Vertex, E extends Edge<V>>
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -070035 extends AbstractGraphPathSearch<V, E> {
36
37 static final int ITERATIONS = 100;
38 static final int POPSIZE = 50;
39
40 boolean useSuurballe = false;
41
42 static final double INF = 100000000.0;
43
44 int numGroups;
45 Map<E, Integer> riskGrouping;
46
47 Graph<V, E> orig;
48 V src, dst;
49 EdgeWeight<V, E> weight;
50
51 /**
52 * Creates an SRLG graph search object with the given number
53 * of groups and given risk mapping.
54 *
55 * @param groups the number of disjoint risk groups
56 * @param grouping map linking edges to integral group assignments
57 */
Jonathan Hartd9df7bd2015-11-10 17:10:25 -080058 public SrlgGraphSearch(int groups, Map<E, Integer> grouping) {
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -070059 numGroups = groups;
60 riskGrouping = grouping;
61 }
62
63 /**
64 * Creates an SRLG graph search object from a map, inferring
65 * the number of groups and creating an integral mapping.
66 *
67 * @param grouping map linking edges to object group assignments,
68 * with same-group status linked to equality
69 */
Jonathan Hartd9df7bd2015-11-10 17:10:25 -080070 public SrlgGraphSearch(Map<E, Object> grouping) {
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -070071 if (grouping == null) {
72 useSuurballe = true;
73 return;
74 }
75 numGroups = 0;
76 HashMap<Object, Integer> tmpMap = new HashMap<>();
77 riskGrouping = new HashMap<>();
78 for (E key: grouping.keySet()) {
79 Object value = grouping.get(key);
80 if (!tmpMap.containsKey(value)) {
81 tmpMap.put(value, numGroups);
82 numGroups++;
83 }
84 riskGrouping.put(key, tmpMap.get(value));
85 }
86 }
87
88 @Override
89 public Result<V, E> search(Graph<V, E> graph, V src, V dst,
90 EdgeWeight<V, E> weight, int maxPaths) {
91 if (maxPaths == ALL_PATHS) {
92 maxPaths = POPSIZE;
93 }
94 if (useSuurballe) {
95 return new SuurballeGraphSearch<V, E>().search(graph, src, dst, weight, ALL_PATHS);
96 }
97 if (weight == null) {
98 weight = edge -> 1;
99 }
100 checkArguments(graph, src, dst);
101 orig = graph;
102 this.src = src;
103 this.dst = dst;
104 this.weight = weight;
105 List<Subset> best = new GAPopulation<Subset>()
106 .runGA(ITERATIONS, POPSIZE, maxPaths, new Subset(new boolean[numGroups]));
107 Set<DisjointPathPair> dpps = new HashSet<DisjointPathPair>();
108 for (Subset s: best) {
109 dpps.addAll(s.buildPaths());
110 }
111 Result<V, E> firstDijkstra = new DijkstraGraphSearch<V, E>()
112 .search(orig, src, dst, weight, 1);
113 return new Result<V, E>() {
114 final DefaultResult search = (DefaultResult) firstDijkstra;
115
116 public V src() {
117 return src;
118 }
119 public V dst() {
120 return dst;
121
122 }
123 public Set<Path<V, E>> paths() {
124 Set<Path<V, E>> pathsD = new HashSet<>();
125 for (DisjointPathPair<V, E> path: dpps) {
126 pathsD.add(path);
127 }
128 return pathsD;
129 }
130 public Map<V, Double> costs() {
131 return search.costs();
132
133 }
134 public Map<V, Set<E>> parents() {
135 return search.parents();
136
137 }
138 };
139 }
140
141 //finds the shortest path in the graph given a subset of edge types to use
142 private Result<V, E> findShortestPathFromSubset(boolean[] subset) {
143 Graph<V, E> graph = orig;
144 EdgeWeight<V, E> modified = new EdgeWeight<V, E>() {
145 final boolean[] subsetF = subset;
146
147 @Override
148 public double weight(E edge) {
149 if (subsetF[riskGrouping.get(edge)]) {
150 return weight.weight(edge);
151 }
152 return INF;
153 }
154 };
155
156 Result<V, E> res = new DijkstraGraphSearch<V, E>().search(graph, src, dst, modified, 1);
157 return res;
158 }
159 /**
160 * A subset is a type of GA organism that represents a subset of allowed shortest
161 * paths (and its complement). Its fitness is determined by the sum of the weights
162 * of the first two shortest paths.
163 */
164 class Subset implements GAOrganism {
165
166 boolean[] subset;
167 boolean[] not;
168 Random r = new Random();
169
170 /**
171 * Creates a Subset from the given subset array.
172 *
173 * @param sub subset array
174 */
175 public Subset(boolean[] sub) {
176 subset = sub.clone();
177 not = new boolean[subset.length];
178 for (int i = 0; i < subset.length; i++) {
179 not[i] = !subset[i];
180 }
181 }
182
183 @Override
184 public double fitness() {
185 Set<Path<V, E>> paths1 = findShortestPathFromSubset(subset).paths();
186 Set<Path<V, E>> paths2 = findShortestPathFromSubset(not).paths();
187 if (paths1.size() == 0 || paths2.size() == 0) {
188 return INF;
189 }
190 return paths1.iterator().next().cost() + paths2.iterator().next().cost();
191 }
192
193 @Override
194 public void mutate() {
195 int turns = r.nextInt((int) Math.sqrt(subset.length));
196 while (turns > 0) {
197 int choose = r.nextInt(subset.length);
198 subset[choose] = !subset[choose];
199 not[choose] = !not[choose];
200 turns--;
201 }
202 }
203
204 @Override
205 public GAOrganism crossWith(GAOrganism org) {
206 if (!(org.getClass().equals(getClass()))) {
207 return this;
208 }
209 Subset other = (Subset) (org);
210 boolean[] sub = new boolean[subset.length];
211 for (int i = 0; i < subset.length; i++) {
212 sub[i] = subset[i];
213 if (r.nextBoolean()) {
214 sub[i] = other.subset[i];
215 }
216 }
217 return new Subset(sub);
218 }
219
220 @Override
221 public GAOrganism random() {
222 boolean[] sub = new boolean[subset.length];
223 for (int i = 0; i < sub.length; i++) {
224 sub[i] = r.nextBoolean();
225 }
226 return new Subset(sub);
227 }
228
229 /**
230 * Builds the set of disjoint path pairs for a given subset
231 * using Dijkstra's algorithm on both the subset and complement
232 * and returning all pairs with one from each set.
233 *
234 * @return all shortest disjoint paths given this subset
235 */
236 public Set<DisjointPathPair> buildPaths() {
237 Set<DisjointPathPair> dpps = new HashSet<>();
238 for (Path<V, E> path1: findShortestPathFromSubset(subset).paths()) {
239 if (path1.cost() >= INF) {
240 continue;
241 }
242 for (Path<V, E> path2: findShortestPathFromSubset(not).paths()) {
243 if (path2.cost() >= INF) {
244 continue;
245 }
246 DisjointPathPair<V, E> dpp = new DisjointPathPair<>(path1, path2);
247 dpps.add(dpp);
248 }
249 }
250 return dpps;
251 }
252 }
253}