package edu.usc.enl.dynamicmeasurement.algorithms.tasks.hhh.flow.multiswitch; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * Created with IntelliJ IDEA. * User: Masoud * Date: 1/23/13 * Time: 8:53 AM <br/> * solves subset cover problem of item of type E */ public class SubSetCoverSolver<E> { /** * Can mess with sets and toCover * * @param toCover * @param sets * @param costs * @param solution * @param <F> the type of the key to recognize each set with * @return */ public <F> double solve(Set<E> toCover, Map<F, Set<E>> sets, Map<F, Double> costs, List<F> solution) { double costSum = 0; while (toCover.size() > 0) { //intersect sets with to cover { for (Iterator<Map.Entry<F, Set<E>>> iterator = sets.entrySet().iterator(); iterator.hasNext(); ) { Map.Entry<F, Set<E>> entry = iterator.next(); Set<E> set = entry.getValue(); set.retainAll(toCover); if (set.size() == 0) { iterator.remove(); } } } //find min avgweights double minWeight = -1; F minWeightSetIdentifier = null; for (Map.Entry<F, Set<E>> entry : sets.entrySet()) { Set<E> set = entry.getValue(); double avgWeightSet = costs.get(entry.getKey()) / set.size(); if (avgWeightSet < minWeight || minWeightSetIdentifier == null) { minWeightSetIdentifier = entry.getKey(); minWeight = avgWeightSet; } if (minWeight == 0) { // you cannot find a cost less than 0 break; } } if (minWeightSetIdentifier == null) { break; } costSum += costs.get(minWeightSetIdentifier); Set<E> set = sets.get(minWeightSetIdentifier); if (minWeightSetIdentifier instanceof DetailSolution) { ((DetailSolution) minWeightSetIdentifier).setUsefulFor(set, minWeight); } toCover.removeAll(set); solution.add(minWeightSetIdentifier); sets.remove(minWeightSetIdentifier); } if (toCover.size() == 0) { return costSum; } else { //unsuccessful // for (Set<E> es : setsTemp.values()) { // if (es.contains(toCoverTemp.iterator().next())){ // System.out.println("hey I still can contribute"); // } // } return -1; } } /** * If the identifier of each set implements this, it will be notified when it is used to cover a subset of the target set */ public static interface DetailSolution { public void setUsefulFor(Set monitorPoints, double avgCost); } }