package org.aksw.jena_sparql_api.concept_cache.combinatorics;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import org.aksw.combinatorics.solvers.ProblemNeighborhoodAware;
import org.aksw.jena_sparql_api.utils.MapUtils;
import org.aksw.jena_sparql_api.utils.NodeTransformSignaturize;
import org.apache.jena.sparql.core.Quad;
import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.graph.NodeTransform;
import org.apache.jena.sparql.graph.NodeTransformLib;
import com.codepoetics.protonpack.functions.TriFunction;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
public class Refinement {
public static ProblemNeighborhoodAware<Map<Var, Var>, Var> groupToProblem(Entry<Set<Quad>, Set<Quad>> group, Map<Var, Var> newBase) {
ProblemNeighborhoodAware<Map<Var, Var>, Var> result = new ProblemVarMappingQuad(group.getKey(), group.getValue(), newBase);
return result;
}
public static <T> Collection<ProblemNeighborhoodAware<Map<Var, Var>, Var>> groupsToProblems(
Map<?, Entry<Set<T>, Set<T>>> groups,
Map<Var, Var> newBase,
TriFunction<Set<T>, Set<T>, Map<Var, Var>, ProblemNeighborhoodAware<Map<Var, Var>, Var>> groupToProblem) {
Collection<ProblemNeighborhoodAware<Map<Var, Var>, Var>> result = groups.values().stream()
.map(e -> groupToProblem.apply(e.getKey(), e.getValue(), newBase)) //new ProblemVarMappingQuad(e.getKey(), e.getValue(), newBase))
.collect(Collectors.toList());
return result;
}
/**
* Signature construction:
* - Variables that were already renamed must not be remapped again
* - Variables of the 'as' that clash with the renaming (ps.values()) must be renamed first
*
*
*/
public static <T> Collection<ProblemNeighborhoodAware<Map<Var, Var>, Var>> refineGeneric(
Collection<? extends T> as,
Collection<? extends T> bs,
Map<Var, Var> baseSolution,
Map<Var, Var> partialSolution,
BiFunction<NodeTransform, T, T> transformer,
TriFunction<Set<T>, Set<T>, Map<Var, Var>, ProblemNeighborhoodAware<Map<Var, Var>, Var>> groupToProblem
)
{
Map<Var, Var> newBase = MapUtils.mergeIfCompatible(baseSolution, partialSolution);
Map<T, Entry<Set<T>, Set<T>>> groups = Refinement.refineGeneric(as, bs, newBase, transformer);
Collection<ProblemNeighborhoodAware<Map<Var, Var>, Var>> result = groupsToProblems(groups, newBase, groupToProblem);
return result;
}
public static <T> Map<T, Entry<Set<T>, Set<T>>> refineGeneric(
Collection<? extends T> as,
Collection<? extends T> bs,
Map<Var, Var> newBase,
BiFunction<NodeTransform, T, T> transformer
)
{
Map<T, Entry<Set<T>, Set<T>>> result;
if(newBase == null) {
result = null;
} else {
NodeTransform signaturizer = NodeTransformSignaturize.create(newBase);
Multimap<T, T> sigToAs = HashMultimap.create();
as.forEach(q -> {
T sig = transformer.apply(signaturizer, q);
sigToAs.put(sig, q);
});
// TODO - Is having a .distinct().collect... safe here?
Map<Var, Var> identity = newBase.values().stream().distinct().collect(Collectors.toMap(x -> x, x -> x));
NodeTransform s2 = NodeTransformSignaturize.create(identity);
Multimap<T, T> sigToBs = HashMultimap.create();
bs.forEach(q -> {
T sig = transformer.apply(s2, q);
sigToBs.put(sig, q);
});
result = MapUtils.groupByKey(sigToAs.asMap(), sigToBs.asMap());
// System.out.println("sigToAs: " + sigToAs);
// System.out.println("sigToBs: " + sigToBs);
// result.values().stream().forEach(e ->
// System.out.println(" Refined to " + e + " from " + as + " - " + bs + " via " + newBase));
}
return result;
}
// public static Map<Quad, Entry<Set<Quad>, Set<Quad>>> refine(
// Collection<? extends Quad> as,
// Collection<? extends Quad> bs,
// Map<Var, Var> newBase)
// {
// Map<Quad, Entry<Set<Quad>, Set<Quad>>> result =
// refineGeneric(as, bs, newBase, (nodeTransform, quad) -> NodeTransformLib.transform(nodeTransform, quad));
// return result;
//
// /*
// Map<Quad, Entry<Set<Quad>, Set<Quad>>> result;
//
// if(newBase == null) {
// result = null;
// } else {
// NodeTransform signaturizer = NodeTransformSignaturize.create(newBase);
//
// Multimap<Quad, Quad> sigToAs = HashMultimap.create();
// as.forEach(q -> {
// Quad sig = NodeTransformLib.transform(signaturizer, q);
// sigToAs.put(sig, q);
// });
//
// Map<Var, Var> identity = newBase.values().stream().collect(Collectors.toMap(x -> x, x -> x));
// NodeTransform s2 = NodeTransformSignaturize.create(identity);
// Multimap<Quad, Quad> sigToBs = HashMultimap.create();
// bs.forEach(q -> {
// Quad sig = NodeTransformLib.transform(s2, q);
// sigToBs.put(sig, q);
// });
//
// result = ProblemVarMappingQuad.groupByKey(sigToAs.asMap(), sigToBs.asMap());
//
// System.out.println("sigToAs: " + sigToAs);
// System.out.println("sigToBs: " + sigToBs);
// result.values().stream().forEach(e ->
// System.out.println(" Refined to " + e + " from " + as + " - " + bs + " via " + newBase));
// }
// return result;
// */
// }
public static Collection<ProblemNeighborhoodAware<Map<Var, Var>, Var>> groupsToProblems(Map<Quad, Entry<Set<Quad>, Set<Quad>>> group, Map<Var, Var> newBase) {
Collection<ProblemNeighborhoodAware<Map<Var, Var>, Var>> result = group.values().stream()
.map(e -> new ProblemVarMappingQuad(e.getKey(), e.getValue(), newBase))
.collect(Collectors.toList());
return result;
}
public static Collection<ProblemNeighborhoodAware<Map<Var, Var>, Var>> refineQuads(
Collection<? extends Quad> as,
Collection<? extends Quad> bs,
Map<Var, Var> baseSolution,
Map<Var, Var> partialSolution) {
Collection<ProblemNeighborhoodAware<Map<Var, Var>, Var>> result = refineGeneric(
as,
bs,
baseSolution,
partialSolution,
(nodeTransform, quad) -> NodeTransformLib.transform(nodeTransform, quad),
(newAs, newBs, newBase) -> new ProblemVarMappingQuad(newAs, newBs, newBase)
);
return result;
}
public static Collection<ProblemNeighborhoodAware<Map<Var, Var>, Var>> refineExprs(
Collection<? extends Expr> as,
Collection<? extends Expr> bs,
Map<Var, Var> baseSolution,
Map<Var, Var> partialSolution) {
Collection<ProblemNeighborhoodAware<Map<Var, Var>, Var>> result = refineGeneric(
as,
bs,
baseSolution,
partialSolution,
(nodeTransform, expr) -> NodeTransformLib.transform(nodeTransform, expr),
(newAs, newBs, newBase) -> new ProblemVarMappingExpr(newAs, newBs, newBase)
);
return result;
}
}