package org.aksw.isomorphism; import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.stream.Stream; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Sets; import com.google.common.collect.TreeMultimap; public class Iso { /** * This is a generalized version of VF2: * * Given two sets of items A and B, in addition to matching items (such as nodes in a graph) directly, * it is possible to create mappings between *attributes* X and Y of these items. * For instance, if you are matching expressions, than this implementation can yield a mapping of variables appearing in it. * * * Relations between objects: In a graph setting, nodes are connected via edges. * We take advantage of this fact, that whenever two items are matched, we can process the equivalence classes * that contain the related objects and see if these classes become smaller than any other equiv classes so far. * * It is fine to leave * * The algorithm can be viewed as to unify solution *generating* and solution *validating* elements: * Consider a graph: If its edges are unlabeled, then equivalence classes of vertices can be built based on in/out degree * If however, the degrees are all the some, yet the edge labels vary significantly, it is possible to create equivalence classes from them * * * But this means, we have to abstract from the concrete objects we are matching (nodes, edges, quads, expressions) - and hence * the algorithm may only operate on equivalence class objects and partial solutions. * * * @param srcs The items to match with tgts * @param tgts * @param matchToPartialSolution * @param srcToEquivClass * @param tgtToEquivClass * @param partialSolution * @param candidatePairingGenerator A function that generates candidate * pairings on members of of an equivalence class in regard to a partial solution * @return */ // public static <A, B, PA, PB, X, Y, E extends Comparable<E>> Stream<Map<M, N>> iso( // Collection<A> srcs, // Collection<B> tgts, // BiFunction<A, B, Entry<X, Y>> matchToPartialSolution, // Function that returns a partial solution by matching A with B // Function<A, Collection<Triplet<A, PA>>> aRelations, // related items with A - could be predecessor and successor nodes // Function<B, Collection<Triplet<B, PB>>> bRelations, // related items with B // Function<? super A, E> srcToEquivClass, // Function<? super B, E> tgtToEquivClass, // Map<M, N> partialSolution, // // TriFunction< // Collection<? extends M>, // In: A collection of items from M // Collection<? extends N>, // In: A collection of items from N // Map<M, N>, // In: A partial solution // TreeMultimap<Number, Entry<Collection<M>, Collection<N>>> // Out: A stream of candidate pairings // > equivClassPartitioner, // // TriFunction< // ? super Collection<? extends M>, // In: A collection of items from M // ? super Collection<? extends N>, // In: A collection of items from N // Map<M, N>, // In: A partial solution // Stream<Entry<M, N>> // Out: A stream of candidate pairings // > candidatePairingGenerator) // { // Multimap<E, M> srcEquivClasses = indexItemsByEquivClass(srcs, srcToEquivClass); // Multimap<E, N> tgtEquivClasses = indexItemsByEquivClass(tgts, tgtToEquivClass); // // Stream<Map<M, N>> result = iso(srcEquivClasses, tgtEquivClasses); // return result; // } public static <M, N, E extends Comparable<E>> Stream<Map<M, N>> iso( Multimap<E, M> srcEquivClasses, Multimap<E, N> tgtEquivClasses) { Stream<Map<M, N>> result; // Create a list of all equiv classes and order it by the number of possible pairings // We use a tree multi map for that purpose TreeMultimap<Integer, E> sizeToEquivClasses = TreeMultimap.create(); Set<E> equivClasses = Sets.union(srcEquivClasses.keySet(), tgtEquivClasses.keySet()); for(E equivClass : equivClasses) { Collection<M> srcItems = srcEquivClasses.get(equivClass); Collection<N> tgtItems = tgtEquivClasses.get(equivClass); } // If there are a zero sized equiv classes, there can be no solution mappings Collection<E> zeroSizedEquivClasses = sizeToEquivClasses.get(0); if(!zeroSizedEquivClasses.isEmpty()) { result = Collections.<Map<M, N>>emptySet().stream(); } else { } return null; } public static <S, E> Multimap<E, S> indexItemsByEquivClass(Collection<S> items, Function<? super S, E> itemToEquivClass) { Multimap<E, S> result = HashMultimap.create(); for(S item : items) { E equivClass = itemToEquivClass.apply(item); result.put(equivClass, item); } return result; } }