@Override public Solution pack(double upperBound) { Set<Cycle> matching = new HashSet<Cycle>(); double objVal = 0.0; Set<Vertex> matchedVerts = new HashSet<Vertex>(); long start = System.nanoTime(); // First, use every altruist by packing chains if (maxChainSize > 1) { for (Vertex alt : pool.getAltruists()) { // Can't sample any chains from isolated altruists if (pool.outgoingEdgesOf(alt).isEmpty()) { continue; } Cycle chain = sampleAChain(alt, matchedVerts, maxChainSize, usingFailureProbabilities); // Couldn't find a legal path from this altruist if (null == chain) { continue; } // We check legality of the chain during generation, so add all verts and chain to matching Set<Vertex> cVerts = Cycle.getConstituentVertices(chain, pool); matchedVerts.addAll(cVerts); objVal += chain.getWeight(); matching.add(chain); // If we hit the upper bound, break out if (objVal >= upperBound) { break; } } } // Second, pack remaining vertices in cycles (using a VertexShufflePacker) VertexShufflePacker cyclePacker = new VertexShufflePacker( this.pool, this.cycles, this.membership, this.shuffleType, matchedVerts); Solution cyclesOnly = cyclePacker.pack(upperBound - objVal); // Add these packed cycles to our full matching matching.addAll(cyclesOnly.getMatching()); objVal += cyclesOnly.getObjectiveValue(); long end = System.nanoTime(); long totalTime = end - start; // Construct formal matching, return Solution sol = new Solution(); sol.setMatching(matching); sol.setObjectiveValue(objVal); sol.setSolveTime(totalTime); return sol; }
public static void removeKidneyToLiverEdges( Pool pool, Random r, double probKidneyToLiver, double pctKidney) { IOUtil.dPrintln("Removing edges from some kidney donors to liver pairs."); // First, label the vertices as either kidney- or liver-needing (all altruists are assumed // kidney) Set<Vertex> kidneyPairedDonors = new HashSet<Vertex>(); Set<Vertex> liverPairedDonors = new HashSet<Vertex>(); for (VertexPair vp : pool.getPairs()) { if (r.nextDouble() < pctKidney) { kidneyPairedDonors.add(vp); } else { liverPairedDonors.add(vp); } } for (VertexAltruist alt : pool.getAltruists()) { kidneyPairedDonors.add(alt); } // Next, for each kidney-paired donor, determine if that donor is willing // to give a liver. If not, remove all outgoing edges to liver-paired donors Set<Edge> edgesToRemove = new HashSet<Edge>(); for (Vertex kidneyV : kidneyPairedDonors) { boolean willingToGive = (r.nextDouble() < probKidneyToLiver); willingToGive &= !(kidneyV.isAltruist()); // disallow any kidney altruists from given to liver pairs if (willingToGive) { continue; } for (Edge e : pool.outgoingEdgesOf(kidneyV)) { if (liverPairedDonors.contains(pool.getEdgeTarget(e))) { edgesToRemove.add(e); } } } int removedEdgeCt = 0; for (Edge e : edgesToRemove) { pool.removeEdge(e); removedEdgeCt++; } IOUtil.dPrintln( "Removed " + removedEdgeCt + " edges from kidney donors to liver pairs (" + pool.edgeSet().size() + " remain)."); }