private function run_discussion_order_once($cflt, $plist)
 {
     $m = new MinCostMaxFlow();
     $m->add_progressf(array($this, "mcmf_progress"));
     $this->set_progress("Preparing assignment optimizer");
     // paper nodes
     // set p->po edge cost so low that traversing that edge will
     // definitely lower total cost; all positive costs are <=
     // count($this->pcm), so this edge should have cost:
     $pocost = -(count($this->pcm) + 1);
     $this->mcmf_max_cost = $pocost * count($plist) * 0.75;
     $m->add_node(".s", "source");
     $m->add_edge(".source", ".s", 1, 0);
     foreach ($plist as $i => $pids) {
         $m->add_node("p{$i}", "p");
         $m->add_node("po{$i}", "po");
         $m->add_edge(".s", "p{$i}", 1, 0);
         $m->add_edge("p{$i}", "po{$i}", 1, $pocost);
         $m->add_edge("po{$i}", ".sink", 1, 0);
     }
     // conflict edges
     $plist2 = $plist;
     // need copy for different iteration ptr
     foreach ($plist as $i => $pid1) {
         foreach ($plist2 as $j => $pid2) {
             if ($i != $j) {
                 $pid1 = is_array($pid1) ? $pid1[count($pid1) - 1] : $pid1;
                 $pid2 = is_array($pid2) ? $pid2[0] : $pid2;
                 // cost of edge is number of different conflicts
                 $cost = count($cflt[$pid1] + $cflt[$pid2]) - count(array_intersect($cflt[$pid1], $cflt[$pid2]));
                 $m->add_edge("po{$i}", "p{$j}", 1, $cost);
             }
         }
     }
     // run MCMF
     $this->mcmf = $m;
     $m->shuffle();
     $m->run();
     // extract next roots
     $roots = array_keys($plist);
     $result = array();
     while (count($roots)) {
         $source = ".source";
         if (count($roots) !== count($plist)) {
             $source = "p" . $roots[mt_rand(0, count($roots) - 1)];
         }
         $pgroup = $igroup = array();
         foreach ($m->topological_sort($source, "p") as $v) {
             $pidx = (int) substr($v->name, 1);
             $igroup[] = $pidx;
             if (is_array($plist[$pidx])) {
                 $pgroup = array_merge($pgroup, $plist[$pidx]);
             } else {
                 $pgroup[] = $plist[$pidx];
             }
         }
         $result[] = $pgroup;
         $roots = array_values(array_diff($roots, $igroup));
     }
     // done
     $m->clear();
     // break circular refs
     $this->mcmf = null;
     $this->profile["maxflow"] += $m->maxflow_end_at - $m->maxflow_start_at;
     if ($m->mincost_start_at) {
         $this->profile["mincost"] += $m->mincost_end_at - $m->mincost_start_at;
     }
     return $result;
 }
예제 #2
0
}
foreach (array("u0", "u1", "u2") as $x) {
    foreach (array("p0", "p1", "p2") as $y) {
        $m->add_edge($x, $y, 1);
    }
}
$assignments = array();
foreach (range(100, 921384, 1247) as $seed) {
    $m->reset();
    srand($seed);
    // the shuffle() uses this seed
    $m->shuffle();
    $m->run();
    $assignments[mcmf_assignment_text($m)] = true;
}
$assignments = array_keys($assignments);
sort($assignments);
xassert_eqq(count($assignments), 6);
xassert_eqq($assignments[0], "u0 p0\nu1 p1\nu2 p2\n");
xassert_eqq($assignments[1], "u0 p0\nu1 p2\nu2 p1\n");
xassert_eqq($assignments[2], "u0 p1\nu1 p0\nu2 p2\n");
xassert_eqq($assignments[3], "u0 p1\nu1 p2\nu2 p0\n");
xassert_eqq($assignments[4], "u0 p2\nu1 p0\nu2 p1\n");
xassert_eqq($assignments[5], "u0 p2\nu1 p1\nu2 p0\n");
fwrite(STDERR, "- Phase 4 complete.\n");
$m = new MinCostMaxFlow();
$m->parse_dimacs("n 1 s\nn 2 t\nc ninfo 3 u0 u\nc ninfo 4 u1 u\nc ninfo 5 u2 u\nc ninfo 6 p0 p\nc ninfo 7 p1 p\nc ninfo 8 p2 p\na 1 3 1\na 1 4 1\na 1 5 1\na 3 6 0 1 0\na 3 7 0 1 -1\na 4 6 0 1 0\na 4 7 0 1 0\na 4 8 0 1 0\na 5 6 0 1 0\na 5 8 0 1 1\na 6 2 1\na 7 2 1\na 8 2 1");
$m->run();
xassert_eqq(mcmf_assignment_text($m), "u0 p1\nu1 p2\nu2 p0\n");
xassert_eqq(preg_replace('/^c[^\\n]*\\n/m', "", $m->mincost_dimacs_output()), "s -1\nf 1 3 1\nf 1 4 1\nf 1 5 1\nf 3 7 1\nf 4 8 1\nf 5 6 1\nf 6 2 1\nf 7 2 1\nf 8 2 1\n");
xassert_exit();