package org.aksw.jena_sparql_api.sparql_path2;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
import org.aksw.jena_sparql_api.utils.model.Triplet;
import org.aksw.jena_sparql_api.utils.model.TripletPath;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
public class BidirectionalSearch<S, G, V, E> {
// protected NfaExecution<V> forwards;
// protected NfaExecution<V> backwards;
protected NfaFrontier<S, G, V, E> fwdFrontier;
protected NfaFrontier<S, G, V, E> bwdFrontier;
protected Set<NestedPath<V, E>> accepted = new HashSet<>();
protected Function<TripletPath<V, E>, Boolean> pathCallback;
// public BidirectionalSearch(NfaExecution<V> forwards, NfaExecution<V> backwards) {
// this.forwards = forwards;
// this.backwards = backwards;
// }
public static <S, V, E> Set<TripletPath<V, E>> intersect(NfaFrontier<S, V, V, E> fwd, NfaFrontier<S, V, V, E> bwd) {
Set<TripletPath<V, E>> result = new HashSet<>();
// Get the sets of states where the frontiers meet
Set<S> fwdStates = fwd.getCurrentStates();
Set<S> bwdStates = bwd.getCurrentStates();
Set<S> commonStates = Sets.intersection(fwdStates, bwdStates);
for(S state : commonStates) {
Multimap<V, NestedPath<V, E>> fwdNodeToPaths = fwd.getPaths(state);
Multimap<V, NestedPath<V, E>> bwdNodeToPaths = bwd.getPaths(state);
Set<V> fwdNodes = fwdNodeToPaths.keySet();
Set<V> bwdNodes = bwdNodeToPaths.keySet();
Set<V> commonNodes = Sets.union(fwdNodes, bwdNodes);
for(V node : commonNodes) {
Collection<NestedPath<V, E>> fwdPaths = fwdNodeToPaths.get(node);
Collection<NestedPath<V, E>> bwdPaths = bwdNodeToPaths.get(node);
for(NestedPath<V, E> fwdPath : fwdPaths) {
for(NestedPath<V, E> bwdPath : bwdPaths) {
TripletPath<V, E> fwdPart = fwdPath.asSimplePath();
TripletPath<V, E> bwdPart = bwdPath.asSimplePath().reverse();
V start = fwdPart.getStart();
V end = fwdPart.getEnd();
List<Triplet<V, E>> triples = new ArrayList<>();
triples.addAll(fwdPart.getTriplets());
triples.addAll(bwdPart.getTriplets());
TripletPath<V, E> path = new TripletPath<>(start, end, triples);
result.add(path);
}
}
}
}
return result;
}
}