blob: 82107ca478d6cb669ca9c1e108d288a3329eebe1 [file] [log] [blame]
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -07003 *
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;
Andrey Komarov2398d962016-09-26 15:11:23 +030049 EdgeWeigher<V, E> weigher;
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -070050
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
Andrey Komarov2398d962016-09-26 15:11:23 +030089 protected Result<V, E> internalSearch(Graph<V, E> graph, V src, V dst,
90 EdgeWeigher<V, E> weigher, int maxPaths) {
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -070091 if (maxPaths == ALL_PATHS) {
92 maxPaths = POPSIZE;
93 }
94 if (useSuurballe) {
Andrey Komarov2398d962016-09-26 15:11:23 +030095 return new SuurballeGraphSearch<V, E>().search(graph, src, dst, weigher, ALL_PATHS);
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -070096 }
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -070097 orig = graph;
98 this.src = src;
99 this.dst = dst;
Andrey Komarov2398d962016-09-26 15:11:23 +0300100 this.weigher = weigher;
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700101 List<Subset> best = new GAPopulation<Subset>()
102 .runGA(ITERATIONS, POPSIZE, maxPaths, new Subset(new boolean[numGroups]));
103 Set<DisjointPathPair> dpps = new HashSet<DisjointPathPair>();
104 for (Subset s: best) {
105 dpps.addAll(s.buildPaths());
106 }
107 Result<V, E> firstDijkstra = new DijkstraGraphSearch<V, E>()
Andrey Komarov2398d962016-09-26 15:11:23 +0300108 .search(orig, src, dst, weigher, 1);
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700109 return new Result<V, E>() {
110 final DefaultResult search = (DefaultResult) firstDijkstra;
111
112 public V src() {
113 return src;
114 }
115 public V dst() {
116 return dst;
117
118 }
119 public Set<Path<V, E>> paths() {
120 Set<Path<V, E>> pathsD = new HashSet<>();
121 for (DisjointPathPair<V, E> path: dpps) {
122 pathsD.add(path);
123 }
124 return pathsD;
125 }
Andrey Komarov2398d962016-09-26 15:11:23 +0300126 public Map<V, Weight> costs() {
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700127 return search.costs();
128
129 }
130 public Map<V, Set<E>> parents() {
131 return search.parents();
132
133 }
134 };
135 }
136
137 //finds the shortest path in the graph given a subset of edge types to use
138 private Result<V, E> findShortestPathFromSubset(boolean[] subset) {
139 Graph<V, E> graph = orig;
Andrey Komarov2398d962016-09-26 15:11:23 +0300140 EdgeWeigher<V, E> modified = new EdgeWeigher<V, E>() {
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700141 final boolean[] subsetF = subset;
142
143 @Override
Andrey Komarov2398d962016-09-26 15:11:23 +0300144 public Weight weight(E edge) {
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700145 if (subsetF[riskGrouping.get(edge)]) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300146 return weigher.weight(edge);
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700147 }
Andrey Komarov2398d962016-09-26 15:11:23 +0300148 return weigher.getNonViableWeight();
149 }
150
151 @Override
152 public Weight getInitialWeight() {
153 return weigher.getInitialWeight();
154 }
155
156 @Override
157 public Weight getNonViableWeight() {
158 return weigher.getNonViableWeight();
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700159 }
160 };
161
162 Result<V, E> res = new DijkstraGraphSearch<V, E>().search(graph, src, dst, modified, 1);
163 return res;
164 }
165 /**
166 * A subset is a type of GA organism that represents a subset of allowed shortest
167 * paths (and its complement). Its fitness is determined by the sum of the weights
168 * of the first two shortest paths.
169 */
170 class Subset implements GAOrganism {
171
172 boolean[] subset;
173 boolean[] not;
174 Random r = new Random();
175
176 /**
177 * Creates a Subset from the given subset array.
178 *
179 * @param sub subset array
180 */
181 public Subset(boolean[] sub) {
182 subset = sub.clone();
183 not = new boolean[subset.length];
184 for (int i = 0; i < subset.length; i++) {
185 not[i] = !subset[i];
186 }
187 }
188
189 @Override
Andrey Komarov2398d962016-09-26 15:11:23 +0300190 public Comparable fitness() {
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700191 Set<Path<V, E>> paths1 = findShortestPathFromSubset(subset).paths();
192 Set<Path<V, E>> paths2 = findShortestPathFromSubset(not).paths();
Jon Hallcbd1b392017-01-18 20:15:44 -0800193 if (paths1.isEmpty() || paths2.isEmpty()) {
Andrey Komarov2398d962016-09-26 15:11:23 +0300194 return weigher.getNonViableWeight();
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700195 }
Andrey Komarov2398d962016-09-26 15:11:23 +0300196 return paths1.iterator().next().cost().merge(paths2.iterator().next().cost());
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700197 }
198
199 @Override
200 public void mutate() {
201 int turns = r.nextInt((int) Math.sqrt(subset.length));
202 while (turns > 0) {
203 int choose = r.nextInt(subset.length);
204 subset[choose] = !subset[choose];
205 not[choose] = !not[choose];
206 turns--;
207 }
208 }
209
210 @Override
211 public GAOrganism crossWith(GAOrganism org) {
212 if (!(org.getClass().equals(getClass()))) {
213 return this;
214 }
215 Subset other = (Subset) (org);
216 boolean[] sub = new boolean[subset.length];
217 for (int i = 0; i < subset.length; i++) {
218 sub[i] = subset[i];
219 if (r.nextBoolean()) {
220 sub[i] = other.subset[i];
221 }
222 }
223 return new Subset(sub);
224 }
225
226 @Override
227 public GAOrganism random() {
228 boolean[] sub = new boolean[subset.length];
229 for (int i = 0; i < sub.length; i++) {
230 sub[i] = r.nextBoolean();
231 }
232 return new Subset(sub);
233 }
234
235 /**
236 * Builds the set of disjoint path pairs for a given subset
237 * using Dijkstra's algorithm on both the subset and complement
238 * and returning all pairs with one from each set.
239 *
240 * @return all shortest disjoint paths given this subset
241 */
242 public Set<DisjointPathPair> buildPaths() {
243 Set<DisjointPathPair> dpps = new HashSet<>();
244 for (Path<V, E> path1: findShortestPathFromSubset(subset).paths()) {
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700245 for (Path<V, E> path2: findShortestPathFromSubset(not).paths()) {
Nikhil Cheerlaf7c2e1a2015-07-09 12:06:37 -0700246 DisjointPathPair<V, E> dpp = new DisjointPathPair<>(path1, path2);
247 dpps.add(dpp);
248 }
249 }
250 return dpps;
251 }
252 }
253}