package org.aksw.isomorphism; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Map.Entry; import java.util.NavigableMap; import java.util.TreeMap; import java.util.stream.Collectors; import org.aksw.combinatorics.solvers.GenericProblem; import com.google.common.collect.Iterables; /** * A simple cost based problem container implementation. * * Note: At present it does not handle dependencies between problems. * For instance, if an edge in graph falls into one equivalence class, then in the next step * the edge's neighbors (and only those) should be examined of whether they should be processed next. * * Right now, we attempt to refine all problems, instead of using information * about which ones are actually affected. * * * @author Claus Stadler * * @param <S> The solution type */ public class ProblemContainerImpl<S> implements ProblemContainer<S> { protected NavigableMap<? extends Comparable<?>, Collection<GenericProblem<S, ?>>> sizeToProblem; public ProblemContainerImpl(NavigableMap<? extends Comparable<?>, Collection<GenericProblem<S, ?>>> sizeToProblem) { super(); this.sizeToProblem = sizeToProblem; } // public void add(GenericProblem<S, ?> problem) { // double cost = problem.getEstimatedCost(); // sizeToProblem.put(cost, problem); // } // // public void addAll(Iterable<GenericProblem<S, ?>> problems) { // problems.forEach(x -> add(x)); // } // /** * Pick the estimated cheapest problem, * return a a problem collection with that generator removed * * @return */ public ProblemContainerPick<S> pick() { ProblemContainerPick<S> result; Entry<? extends Comparable<?>, Collection<GenericProblem<S, ?>>> currEntry = sizeToProblem.firstEntry(); if(currEntry != null) { Comparable<?> pickedKey = currEntry.getKey(); GenericProblem<S, ?> pickedProblem = Iterables.getFirst(currEntry.getValue(), null); NavigableMap<Comparable<?>, Collection<GenericProblem<S, ?>>> remaining = new TreeMap<>(); sizeToProblem.forEach((k, v) -> { Collection<GenericProblem<S, ?>> ps = v.stream().filter(i -> i != pickedProblem).collect(Collectors.toList()); remaining.computeIfAbsent(k, (x) -> new ArrayList<GenericProblem<S, ?>>()).addAll(ps); }); //ArrayListMultimap.create(sizeToProblem); //remaining.remove(pickedKey, pickedProblem); ProblemContainerImpl<S> r = new ProblemContainerImpl<>(remaining); result = null; //new ProblemContainerPick<>(pickedProblem, r); } else { throw new IllegalStateException(); } return result; } /** * Partition the content of the collection in regard to a partial solution. * This operation may return 'this' * * @param partialSolution */ public ProblemContainerImpl<S> refine(S partialSolution) { Collection<GenericProblem<S, ?>> tmp = sizeToProblem.values().stream() .flatMap(x -> x.stream()) .map(problem -> problem.refine(partialSolution)) .flatMap(x -> x.stream()) .collect(Collectors.toList()); NavigableMap<Long, Collection<GenericProblem<S, ?>>> sizeToProblem = IsoUtils.indexSolutionGenerators(tmp); ProblemContainerImpl<S> result = new ProblemContainerImpl<S>(sizeToProblem); return result; } @Override public boolean isEmpty() { boolean result = sizeToProblem.isEmpty(); return result; } @SafeVarargs public static <S> ProblemContainerImpl<S> create(GenericProblem<S, ?> ... problems) { Collection<GenericProblem<S, ?>> tmp = Arrays.asList(problems); ProblemContainerImpl<S> result = create(tmp); return result; } public static <S> ProblemContainerImpl<S> create(Collection<GenericProblem<S, ?>> problems) { NavigableMap<Long, Collection<GenericProblem<S, ?>>> sizeToProblem = IsoUtils.indexSolutionGenerators(problems); ProblemContainerImpl<S> result = new ProblemContainerImpl<>(sizeToProblem); return result; } }