wiki:BossaExampleTwo

Version 5 (modified by davea, 16 years ago) (diff)

--

Example 2: replication

This example uses the same type of jobs as example 1, but does replication to increase the accuracy of results. Every job is sent to at least two different volunteers.

We'll use the following job distribution policy:

  • Initially all jobs have the default priority (1)
  • When we send the first instance of a job we set its priority to 2, so that we'll get another instance soon.
  • When a 2nd or subsequent instance is issued we set the priority to 0.
  • When an instance times out, or finished but without consensus, we set the priority to 2.

We'll use the following replication policy:

  • A job is considered finished if either
    • Two volunteers reported "no ellipse found";
    • Two volunteers found ellipses, and their centers are within 20 pixels;
  • If ten instances have been performed and neither condition holds, the job is marked as "inconclusive" and no further instances are issued.

When the first instance of a job is issued, its priority is left at 1; this allows another instance to be issued immediately.

function job_issued($job, $inst, $user) {
    $insts = $job->get_instances();
    if (count($insts) > 1) {
        $job->set_priority(0);
    }
}

When an instance is finished, we check whether there are now two consistent responses. If so we mark the job as DONE. If there are 10 finished instances, we mark it as INCONCLUSIVE. Otherwise we set its priority to 2, so that we'll get another instance.

function job_finished($job, $inst) {
    $response = null;
    if (get_str('submit', true)) {
        $response->have_ellipse = 0;
    } else {
        $response->have_ellipse = 1;
        $response->cx = get_int('pic_x');
        $response->cy = get_int('pic_y');
    }
    $inst->update_info($response);

    // see if job is done
    //
    $insts = $job->get_finished_instances();
    $n = count($insts);

    $results = null;
    foreach ($insts as $inst) {
        $results[] = $inst->get_info();
    }
    for ($i=0; $i<$n-1; $i++) {
        $r1 = $results[$i];
        for ($j=$i+1; $j<$n; $j++) {
            $r2 = $results[$j];
            if (compatible($r1, $r2)) {
                $job->update_state(BOSSA_JOB_DONE);
                return;
            }
        }
    }
    if ($n >= 10) {
        $job->update_state(BOSSA_JOB_INCONCLUSIVE);
        return;
    }
}

// two results are compatible if neither found an ellipse,
// or they both did and centers are within 20 pixels
//
function compatible($r1, $r2) {
    if ($r1->have_ellipse) {
        if ($r2->have_ellipse) {
            $dx = ($r1->cx - $r2->cx);
            $dy = ($r1->cy - $r2->cy);
            $dsq = $dx*$dx + $dy*$dy;
            return ($dsq < 400);
        } else return false;
    } else {
        return !$r2->have_ellipse;
    }
}