Skip to content

Commit 2aca25e

Browse files
committed
add A-star search algorithm
1 parent ba6550a commit 2aca25e

8 files changed

+154
-7
lines changed

Graph Computing.xmind

894 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.antfin.util;
2+
3+
4+
import java.util.List;
5+
6+
public class EuclideanDistance implements DistanceFunction {
7+
8+
public EuclideanDistance() {
9+
10+
}
11+
12+
public double calcDistance(List<Double> vector1, List<Double> vector2) {
13+
if (vector1.size() != vector2.size()) {
14+
throw new InternalError("ERROR: cannot calculate the distance "
15+
+ "between vectors of different sizes.");
16+
}
17+
18+
double sqSum = 0.0;
19+
for (int x = 0; x < vector1.size(); x++) {
20+
sqSum += Math.pow(vector1.get(x) - vector2.get(x), 2.0);
21+
}
22+
23+
return Math.sqrt(sqSum);
24+
} // end class euclideanDist(..)
25+
26+
@Override
27+
public double calcDistance(Object a, Object b) {
28+
return this.calcDistance((List<Double>) a, (List<Double>) b);
29+
}
30+
31+
}

src/main/java/com/antfin/util/GraphHelper.java

Lines changed: 92 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,23 @@
22

33
import com.alipay.kepler.util.SerDeHelper;
44
import com.antfin.arc.arch.message.graph.Edge;
5+
import com.antfin.arc.arch.message.graph.Vertex;
56
import com.antfin.arch.cstore.benchmark.RandomWord;
7+
import com.antfin.graph.Graph;
8+
import com.antfin.graph.refObj.Graph_Map_CSR;
69
import java.io.BufferedReader;
710
import java.io.File;
811
import java.io.FileOutputStream;
912
import java.io.IOException;
1013
import java.nio.charset.Charset;
1114
import java.nio.file.Files;
1215
import java.util.ArrayList;
16+
import java.util.Comparator;
1317
import java.util.HashMap;
1418
import java.util.List;
1519
import java.util.Map;
20+
import java.util.PriorityQueue;
21+
import java.util.Queue;
1622
import javafx.util.Pair;
1723

1824
public class GraphHelper {
@@ -111,7 +117,7 @@ public static Object loadObject(File file) throws IOException {
111117
}
112118

113119
public static void writeObject(Object object, File file) throws IOException {
114-
if(!file.getParentFile().exists()){
120+
if (!file.getParentFile().exists()) {
115121
file.getParentFile().mkdirs();
116122
}
117123
file.createNewFile();
@@ -122,15 +128,15 @@ public static void writeObject(Object object, File file) throws IOException {
122128
opStream.close();
123129
}
124130

125-
public static List<Edge<String, String>> loadEdges(String path){
131+
public static List<Edge<String, String>> loadEdges(String path) {
126132
List<Edge<String, String>> edges = new ArrayList<>();
127-
readKVFile(path).forEach(pair->{
133+
readKVFile(path).forEach(pair -> {
128134
edges.add(new Edge<>(pair.getKey(), pair.getValue(), RandomWord.getWords(100)));
129135
});
130136
return edges;
131137
}
132138

133-
public static List<Pair<String, String>> readKVFile(String path){
139+
public static List<Pair<String, String>> readKVFile(String path) {
134140
File file = new File(path);
135141
if (!file.exists()) {
136142
System.err.println(path + " is not exist!");
@@ -140,11 +146,11 @@ public static List<Pair<String, String>> readKVFile(String path){
140146
String line = null;
141147
while ((line = reader.readLine()) != null) {
142148
line = line.trim();
143-
if (line.length() == 0)
149+
if (line.length() == 0) {
144150
continue;
151+
}
145152
String[] vid = line.split(" ");
146-
if (vid.length != 2)
147-
{
153+
if (vid.length != 2) {
148154
System.err.println(line + " must include source and sink!");
149155
}
150156
pairs.add(new Pair<>(vid[0], vid[1]));
@@ -154,4 +160,83 @@ public static List<Pair<String, String>> readKVFile(String path){
154160
}
155161
return pairs;
156162
}
163+
164+
/**
165+
* return the closest distance from source to target by A* search algorithm.
166+
*/
167+
public static <K> double getClosestDistance(Vertex source, Vertex target, Graph graph, Map<K, List<Double>> embedding, DistanceFunction disFun) {
168+
return getClosestDistance((K) source.getId(), (K) target.getId(), graph, embedding, disFun);
169+
}
170+
171+
public static <K> double getClosestDistance(K source, K target, Graph graph, Map<K, List<Double>> embedding, DistanceFunction disFun) {
172+
if (source.equals(target)){
173+
return 0.0;
174+
}
175+
double distanceBetweenNodes = 0;
176+
Map<K, Integer> dictV;
177+
// build Adjacency Matrix
178+
if (graph instanceof Graph_Map_CSR) {
179+
dictV = ((Graph_Map_CSR) graph).getDictV();
180+
} else {
181+
dictV = new HashMap<>();
182+
System.err.format("The type of graph is not Graph_Map_CSR!");
183+
}
184+
// [H,G,F]
185+
double[][] distance = new double[dictV.size()][2];
186+
Queue<K> candidate = new PriorityQueue<K>(new Comparator<K>() {
187+
public int compare(K c1, K c2) {
188+
if (distance[dictV.get(c1)][2] > distance[dictV.get(c2)][2]) {
189+
return 1;
190+
} else if (distance[dictV.get(c1)][2] == distance[dictV.get(c2)][2]) {
191+
return 0;
192+
} else {
193+
return -1;
194+
}
195+
}
196+
});
197+
boolean[] closed = new boolean[dictV.size()];
198+
// record the path <node, parent>
199+
Map<K, K> shortestPath = new HashMap<>();
200+
// init
201+
distance[dictV.get(target)][1] = Double.MIN_VALUE;
202+
distance[dictV.get(source)][0] = disFun.calcDistance(embedding.get(source), embedding.get(target));
203+
distance[dictV.get(source)][1] = 0.0;
204+
distance[dictV.get(source)][2] = distance[dictV.get(source)][0] + distance[dictV.get(source)][1];
205+
candidate.add(source);
206+
while (!candidate.isEmpty()) {
207+
K cur = candidate.poll();
208+
closed[dictV.get(cur)] = true;
209+
for (Object e : ((List) graph.getEdge(cur))){
210+
K nbr = (K) ((Edge)e).getTargetId();
211+
if (!closed[dictV.get(nbr)]) {
212+
double h = disFun.calcDistance(embedding.get(nbr), embedding.get(target));
213+
double g = distance[dictV.get(cur)][1] + distanceBetweenNodes;
214+
double f = h + g;
215+
216+
if (!candidate.contains(nbr)) {
217+
shortestPath.put(nbr, cur);
218+
candidate.add(nbr);
219+
distance[dictV.get(nbr)][0] = h;
220+
distance[dictV.get(nbr)][1] = g;
221+
distance[dictV.get(nbr)][2] = f;
222+
} else if (f < distance[dictV.get(nbr)][2]) {
223+
shortestPath.put(nbr, cur);
224+
distance[dictV.get(nbr)][1] = g;
225+
distance[dictV.get(nbr)][2] = f;
226+
}
227+
}
228+
}
229+
if (cur.equals(target)) {
230+
StringBuilder sb = new StringBuilder();
231+
while (!shortestPath.get(target).equals(source)) {
232+
sb.append(target).append(" <- ");
233+
target = shortestPath.get(target);
234+
}
235+
sb.append(source);
236+
System.out.println("The path is: " + sb.reverse().toString());
237+
return distance[dictV.get(target)][1];
238+
}
239+
}
240+
return distance[dictV.get(target)][1];
241+
}
157242
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.antfin.util;
2+
3+
4+
import java.util.List;
5+
6+
public class ManhattanDistance implements DistanceFunction {
7+
8+
public ManhattanDistance() {
9+
10+
}
11+
12+
public double calcDistance(List<Double> vector1, List<Double> vector2) {
13+
if (vector1.size() != vector2.size()) {
14+
throw new InternalError("ERROR: cannot calculate the distance "
15+
+ "between vectors of different sizes.");
16+
}
17+
18+
double diffSum = 0.0;
19+
for (int x = 0; x < vector1.size(); x++) {
20+
diffSum += Math.abs(vector1.get(x) - vector2.get(x));
21+
}
22+
23+
return diffSum;
24+
}
25+
26+
@Override
27+
public double calcDistance(Object a, Object b) {
28+
return this.calcDistance((List<Double>)a, (List<Double>) b);
29+
}
30+
31+
}

0 commit comments

Comments
 (0)