コード例 #1
0
ファイル: ranker.py プロジェクト: tilgovi/crowdranker
def process_comparison(db, venue_id, user, sorted_items, new_item,
                       alpha_annealing=0.6):
    """ Function updates quality distributions and rank of submissions (items).

    Arguments:
        - sorted_items is a list of submissions id sorted by user such that
        rank(sorted_items[i]) > rank(sorted_items[j]) for i > j

        - new_item is an id of a submission from sorted_items which was new
        to the user. If sorted_items contains only two elements then
        new_item is None.
    """
    if sorted_items == None or len(sorted_items) <= 1:
        return None
    qdistr_param = get_qdistr_param(db, venue_id, sorted_items)
    # If qdistr_param is None then some submission does not have qualities yet,
    # therefore we cannot process comparison.
    if qdistr_param == None:
        return None
    rankobj = Rank.from_qdistr_param(sorted_items, qdistr_param,
                                     alpha=alpha_annealing)
    result = rankobj.update(sorted_items, new_item)
    # Updating the DB.
    for x in sorted_items:
        perc, avrg, stdev = result[x]
        # Updating submission table with its quality and error.
        db((db.submission.id == x) &
           (db.submission.venue_id == venue_id)).update(quality=avrg, error=stdev)
        # Saving then latest rank update date.
        db(db.venue.id == venue_id).update(latest_rank_update_date = datetime.utcnow())
コード例 #2
0
ファイル: ranker.py プロジェクト: gaybro8777/crowdranker
def rerun_processing_comparisons(db,
                                 venue_id,
                                 alpha_annealing=0.5,
                                 run_twice=False):

    # We reset the ranking to the initial values.
    # Gets a ranker object to do the ranking, initialized with all the submissions with
    # their default stdev and avg.
    sub = db(db.submission.venue_id == venue_id).select(db.submission.id)
    items = []
    qdistr_param = []
    for x in sub:
        items.append(x.id)
        qdistr_param.append(AVRG)
        qdistr_param.append(STDEV)
    rankobj = Rank.from_qdistr_param(items,
                                     qdistr_param,
                                     alpha=alpha_annealing)

    # Processes the list of comparisons.
    result = None
    comparison_list = db(db.comparison.venue_id == venue_id).select(
        orderby=db.comparison.date)
    for comp in comparison_list:
        # Processes the comparison, if valid.
        if comp.is_valid is None or comp.is_valid == True:
            # Reverses the list.
            sorted_items = util.get_list(comp.ordering)[::-1]
            if len(sorted_items) < 2:
                continue
            result = rankobj.update(sorted_items, new_item=comp.new_item)
    if run_twice:
        comparison_list = db(db.comparison.venue_id == venue_id).select(
            orderby=~db.comparison.date)
        for comp in comparison_list:
            # Processes the comparison, if valid.
            if comp.is_valid is None or comp.is_valid == True:
                # Reverses the list.
                sorted_items = util.get_list(comp.ordering)[::-1]
                if len(sorted_items) < 2:
                    continue
                result = rankobj.update(sorted_items, new_item=comp.new_item)

    # Writes the updated statistics to the db.  Note that result contains the result for
    # all the ids, due to how the rankobj has been initialized.
    if result is None:
        return
    for x in items:
        perc, avrg, stdev = result[x]
        db((db.submission.id == x)
           & (db.submission.venue_id == venue_id)).update(quality=avrg,
                                                          error=stdev,
                                                          percentile=perc)
    # Saving the latest rank update date.
    description = "Ranking without reputation system. All comparisons are used in chronological order"
    db(db.venue.id == venue_id).update(
        latest_rank_update_date=datetime.utcnow(),
        ranking_algo_description=description)
コード例 #3
0
ファイル: ranker.py プロジェクト: tilgovi/crowdranker
def rerun_processing_comparisons(db, venue_id, alpha_annealing=0.5, run_twice=False):

    # We reset the ranking to the initial values.
    # Gets a ranker object to do the ranking, initialized with all the submissions with
    # their default stdev and avg. 
    sub = db(db.submission.venue_id == venue_id).select(db.submission.id)
    items = []
    qdistr_param = []
    for x in sub:
        items.append(x.id)
        qdistr_param.append(AVRG)
        qdistr_param.append(STDEV)
    rankobj = Rank.from_qdistr_param(items, qdistr_param, alpha=alpha_annealing)

    # Processes the list of comparisons.
    result = None
    comparison_list = db(db.comparison.venue_id == venue_id).select(orderby=db.comparison.date)
    for comp in comparison_list:
	# Processes the comparison, if valid.
	if comp.is_valid is None or comp.is_valid == True:
	    # Reverses the list.
	    sorted_items = util.get_list(comp.ordering)[::-1]
	    if len(sorted_items) < 2:
		continue
	    result = rankobj.update(sorted_items, new_item=comp.new_item)
    if run_twice:
	comparison_list = db(db.comparison.venue_id == venue_id).select(orderby=~db.comparison.date)
	for comp in comparison_list:
	    # Processes the comparison, if valid.
	    if comp.is_valid is None or comp.is_valid == True:
		# Reverses the list.
		sorted_items = util.get_list(comp.ordering)[::-1]
		if len(sorted_items) < 2:
		    continue
		result = rankobj.update(sorted_items, new_item=comp.new_item)

    # Writes the updated statistics to the db.  Note that result contains the result for
    # all the ids, due to how the rankobj has been initialized.
    if result is None:
        return
    for x in items:
        perc, avrg, stdev = result[x]
        db((db.submission.id == x) &
           (db.submission.venue_id == venue_id)).update(quality=avrg, error=stdev, percentile=perc)
    # Saving the latest rank update date.
    description = "Ranking without reputation system. All comparisons are used in chronological order"
    db(db.venue.id == venue_id).update(latest_rank_update_date = datetime.utcnow(),
                                    ranking_algo_description = description)
コード例 #4
0
ファイル: ranker.py プロジェクト: gaybro8777/crowdranker
def evaluate_contributors(db, venue_id):
    """This function evaluates reviewers for a venue.
    Currently, this based on last comparisons made by each reviewer.
    TODO(luca,michael): should we use all comparisons instead?"""

    items, qdistr_param, _ = get_all_items_qdistr_param_and_users(db, venue_id)
    if items == None or len(items) == 0:
        return None
    # Obtaining list of users who did comparisons.
    comp_r = db(db.comparison.venue_id == venue_id).select(db.comparison.user)
    list_of_users = [x.user for x in comp_r]
    list_of_users = list(set(list_of_users))

    rankobj = Rank.from_qdistr_param(items, qdistr_param, cost_obj=None)
    for user in list_of_users:
        last_comparison = db((db.comparison.user == user)
                             & (db.comparison.venue_id == venue_id)).select(
                                 orderby=~db.comparison.date).first()
        if last_comparison == None:
            # Deleting the db.user_accuracy fot this venu_id and user.
            db((db.user_accuracy.venue_id == venue_id)
               & (db.user_accuracy.user == user)).delete()
            continue
        ordering = util.get_list(last_comparison.ordering)
        ordering = ordering[::-1]
        val = rankobj.evaluate_ordering(ordering)
        # Normalization
        num_subm_r = db(db.venue.id == venue_id).select(
            db.venue.number_of_submissions_per_reviewer).first()
        if num_subm_r is None or num_subm_r.number_of_submissions_per_reviewer is None:
            # For compatability with venues which do not have the constant.
            num_subm = 5
        else:
            num_subm = num_subm_r.number_of_submissions_per_reviewer
        # TODO(michael): num_subm can be zero, take care of it.
        val = min(1, val / float(num_subm))
        # Writing to the DB.
        db.user_accuracy.update_or_insert(
            (db.user_accuracy.venue_id == venue_id) &
            (db.user_accuracy.user == user),
            venue_id=venue_id,
            user=user,
            accuracy=val,
            reputation=None,
            n_ratings=len(ordering))
    # Saving the latest user evaluation date.
    db(db.venue.id == venue_id).update(
        latest_reviewers_evaluation_date=datetime.utcnow())
コード例 #5
0
ファイル: ranker.py プロジェクト: tilgovi/crowdranker
def evaluate_contributors(db, venue_id):
    """This function evaluates reviewers for a venue.
    Currently, this based on last comparisons made by each reviewer.
    TODO(luca,michael): should we use all comparisons instead?"""

    items, qdistr_param, _ = get_all_items_qdistr_param_and_users(db, venue_id)
    if items == None or len(items) == 0:
        return None
    # Obtaining list of users who did comparisons.
    comp_r = db(db.comparison.venue_id == venue_id).select(db.comparison.user)
    list_of_users = [x.user for x in comp_r]
    list_of_users = list(set(list_of_users))

    rankobj = Rank.from_qdistr_param(items, qdistr_param, cost_obj=None)
    for user in list_of_users:
        last_comparison = db((db.comparison.user == user)
            & (db.comparison.venue_id == venue_id)).select(orderby=~db.comparison.date).first()
        if last_comparison == None:
            # Deleting the db.user_accuracy fot this venu_id and user.
            db((db.user_accuracy.venue_id == venue_id) & (db.user_accuracy.user == user)).delete()
            continue
        ordering = util.get_list(last_comparison.ordering)
        ordering = ordering[::-1]
        val = rankobj.evaluate_ordering(ordering)
        # Normalization
        num_subm_r = db(db.venue.id == venue_id).select(db.venue.number_of_submissions_per_reviewer).first()
        if num_subm_r is None or num_subm_r.number_of_submissions_per_reviewer is None:
            # For compatability with venues which do not have the constant.
            num_subm = 5
        else:
            num_subm = num_subm_r.number_of_submissions_per_reviewer
        # TODO(michael): num_subm can be zero, take care of it.
        val = min(1, val/float(num_subm))
        # Writing to the DB.
        db.user_accuracy.update_or_insert((db.user_accuracy.venue_id == venue_id) &
                                          (db.user_accuracy.user == user),
                                           venue_id = venue_id,
                                           user = user,
                                           accuracy = val,
                                           reputation = None,
                                           n_ratings = len(ordering) )
    # Saving the latest user evaluation date.
    db(db.venue.id == venue_id).update(latest_reviewers_evaluation_date = datetime.utcnow())
コード例 #6
0
ファイル: ranker.py プロジェクト: gaybro8777/crowdranker
def process_comparison(db,
                       venue_id,
                       user,
                       sorted_items,
                       new_item,
                       alpha_annealing=0.6):
    """ Function updates quality distributions and rank of submissions (items).

    Arguments:
        - sorted_items is a list of submissions id sorted by user such that
        rank(sorted_items[i]) > rank(sorted_items[j]) for i > j

        - new_item is an id of a submission from sorted_items which was new
        to the user. If sorted_items contains only two elements then
        new_item is None.
    """
    if sorted_items == None or len(sorted_items) <= 1:
        return None
    qdistr_param = get_qdistr_param(db, venue_id, sorted_items)
    # If qdistr_param is None then some submission does not have qualities yet,
    # therefore we cannot process comparison.
    if qdistr_param == None:
        return None
    rankobj = Rank.from_qdistr_param(sorted_items,
                                     qdistr_param,
                                     alpha=alpha_annealing)
    result = rankobj.update(sorted_items, new_item)
    # Updating the DB.
    for x in sorted_items:
        perc, avrg, stdev = result[x]
        # Updating submission table with its quality and error.
        db((db.submission.id == x)
           & (db.submission.venue_id == venue_id)).update(quality=avrg,
                                                          error=stdev)
        # Saving then latest rank update date.
        db(db.venue.id == venue_id).update(
            latest_rank_update_date=datetime.utcnow())
コード例 #7
0
ファイル: ranker.py プロジェクト: tilgovi/crowdranker
def get_item(db, venue_id, user, old_items,
             can_rank_own_submissions=False,
             rank_cost_coefficient=0):
    """
    If a user did not have items to rank then old_items is None or empty string.

    If rank_cost_coefficient is equal zero then no cost function is used which
    corresponds to treating each submission equally.

    Description of a sampling method:
        For each submission we count how many time it was assigned as a task.
        Choose subset (rare_items) of submissions which have the smallest frequency.
        Then we compute probability of all possible mistaken comparisons
        between rare_items and old_items (item from previous tasks).
        After that we randomly sample an item proportional of probability of
        a mistake with the item.

        Note that code wich randomly samples item is in Rank.sample_item(...).
        To ensure that sampled item is from rare_items we initialize
        Rank object (rankobj) only with pool items which is a union of
        rare_items  and old_items.
        This way item is sampled as described above.
    """
    if old_items is None:
        old_items = []
    items, qdistr_param, _ = get_all_items_qdistr_param_and_users(db, venue_id)
    # If items is None then some submission does not have qualities yet,
    # we need to know qualities of for all submission to correctly choose an
    # item.
    if items == None or len(items) == 0:
        return None
    # Specifying cost object which implements cost function.
    cost_obj = Cost(cost_type='rank_power_alpha',
                   rank_cost_coefficient=rank_cost_coefficient)
    if rank_cost_coefficient == 0:
        cost_obj = None
    if not can_rank_own_submissions:
        # Find submission that is authored by the user.
        submission_ids = db((db.submission.venue_id == venue_id) &
                                (db.submission.user == user)).select(db.submission.id)
        users_submission_ids = [x.id for x in submission_ids]
    else:
        users_submission_ids = []
    # Counting how many times each submission was assigned.
    # TODO(michael): use the field in the submissions, once we confirm that this works.
    frequency = []
    for subm_id in items:
        if (subm_id not in users_submission_ids and
            subm_id not in old_items):
            count = db((db.task.submission_id == subm_id) &
                       (db.task.venue_id == venue_id)).count()
            frequency.append((subm_id, count))
    # Do we have items to sample from?
    if len(frequency) == 0:
        return None
    # Now let's find submissions which have the smalles count number.
    min_count = min([x[1] for x in frequency])
    rare_items = [x[0] for x in frequency if x[1] == min_count]
    if len(rare_items) == 1:
        return rare_items[0]
    # Constructing pool of items.
    pool_items = rare_items[:]
    pool_items.extend(old_items)
    # Fetching quality distribution parameters.
    qdistr_param_pool = []
    for subm_id in pool_items:
        idx = items.index(subm_id)
        qdistr_param_pool.append(qdistr_param[2 * idx])
        qdistr_param_pool.append(qdistr_param[2 * idx + 1])
    rankobj = Rank.from_qdistr_param(pool_items, qdistr_param_pool,
                                     cost_obj=cost_obj)
    return rankobj.sample_item(old_items, black_items=[])
コード例 #8
0
ファイル: ranker.py プロジェクト: tilgovi/crowdranker
def run_reputation_system(db, venue_id, alpha_annealing=0.5,
                          num_of_iterations=4, last_compar_param=10):
    """ Function calculates submission qualities, user's reputation, reviewer's
    quality and final grades.
    Arguments:
        - last_compar_param works as a switch between two types of reputation system
        If the argument is None then we update using all comparisons one time in chronological order.
        Otherwise we use "small alpha" approach, where last_compar_param is
        number of iterations.
    """
    # Reading the DB to get submission and user information.
    # Lists have l suffix, dictionaries user -> val have d suffix.
    user_l, subm_l, ordering_l, subm_d, ordering_d = read_db_for_rep_sys(db, venue_id, last_compar_param)
    # Initializing the rest of containers.
    qdistr_param_default = []
    for subm in subm_l:
        qdistr_param_default.append(AVRG)
        qdistr_param_default.append(STDEV)
    rep_d = {user: alpha_annealing for user in user_l}
    accuracy_d = {user: 0 for user in user_l}

    # Okay, now we are ready to run main iterations.
    result = None
    for it in xrange(num_of_iterations):
        # In the beginning of iteration initialize rankobj with default
        # submissions qualities.
        rankobj = Rank.from_qdistr_param(subm_l, qdistr_param_default,
                                         alpha=alpha_annealing)
        # Okay, now we update quality distributions with comparisons
        # using reputation of users as annealing coefficient.
        if last_compar_param is None:
            # Using all comparisons in chronological order.
            for ordering, user in ordering_l:
                alpha = rep_d[user]
                result = rankobj.update(ordering, alpha_annealing=alpha)
        else:
            # Using only last comparisons and iterating many times with small alpha.
            for i in xrange(last_compar_param):
                # Genarating random permutation.
                idxs = range(len(ordering_l))
                random.shuffle(idxs)
                for idx in idxs:
                    ordering, user = ordering_l[idx]
                    alpha = rep_d[user]
                    alpha = 1 - (1 - alpha) ** (1.0/(4*last_compar_param))
                    #alpha = alpha / float(2*last_compar_param)
                    result = rankobj.update(ordering, alpha_annealing=alpha)
        if result is None:
            return
        # Computing reputation.
        for user in rep_d:
            if subm_d.has_key(user):
                perc, avrg, stdev = result[subm_d[user]]
                rank = perc / 100.0
            else:
                rank = 0.5 # TODO(michael): Should we trust unknown reviewer?
            if ordering_d.has_key(user):
                ordering = ordering_d[user]
                accuracy = rankobj.evaluate_ordering_using_dirichlet(ordering)
            else:
                accuracy = 0
            accuracy_d[user] = accuracy
            # Computer user's reputation.
            rep_d[user] = (rank * accuracy) ** 0.5

    # Computing submission grades.
    subm_grade_d = {}
    for user, subm in subm_d.iteritems():
        perc, avrg, stdev = result[subm]
        subm_grade_d[subm] = perc / 100.0
    # Computing final grades.
    perc_final_d, final_grade_d = compute_final_grades_helper(user_l, subm_grade_d, rep_d)
    if last_compar_param is None:
        description = "Reputation system on all comparisons in chronological order"
        if num_of_iterations == 1:
            description = "Ranking without reputation system. All comparisons are used in chronological order"
    else:
        description = "Reputation system with small alpha and only last comparisons"
        if num_of_iterations == 1:
            description = "No reputation system and small alpha !?!?"
    # Writing to the BD.
    write_to_db_for_rep_sys(db, venue_id, result, subm_l, user_l, ordering_d,
                            accuracy_d, rep_d, perc_final_d, final_grade_d,
                            ranking_algo_description=description)
コード例 #9
0
ファイル: ranker.py プロジェクト: gaybro8777/crowdranker
def get_item(db,
             venue_id,
             user,
             old_items,
             can_rank_own_submissions=False,
             rank_cost_coefficient=0):
    """
    If a user did not have items to rank then old_items is None or empty string.

    If rank_cost_coefficient is equal zero then no cost function is used which
    corresponds to treating each submission equally.

    Description of a sampling method:
        For each submission we count how many time it was assigned as a task.
        Choose subset (rare_items) of submissions which have the smallest frequency.
        Then we compute probability of all possible mistaken comparisons
        between rare_items and old_items (item from previous tasks).
        After that we randomly sample an item proportional of probability of
        a mistake with the item.

        Note that code wich randomly samples item is in Rank.sample_item(...).
        To ensure that sampled item is from rare_items we initialize
        Rank object (rankobj) only with pool items which is a union of
        rare_items  and old_items.
        This way item is sampled as described above.
    """
    if old_items is None:
        old_items = []
    items, qdistr_param, _ = get_all_items_qdistr_param_and_users(db, venue_id)
    # If items is None then some submission does not have qualities yet,
    # we need to know qualities of for all submission to correctly choose an
    # item.
    if items == None or len(items) == 0:
        return None
    # Specifying cost object which implements cost function.
    cost_obj = Cost(cost_type='rank_power_alpha',
                    rank_cost_coefficient=rank_cost_coefficient)
    if rank_cost_coefficient == 0:
        cost_obj = None
    if not can_rank_own_submissions:
        # Find submission that is authored by the user.
        submission_ids = db((db.submission.venue_id == venue_id)
                            & (db.submission.user == user)).select(
                                db.submission.id)
        users_submission_ids = [x.id for x in submission_ids]
    else:
        users_submission_ids = []
    # Counting how many times each submission was assigned.
    # TODO(michael): use the field in the submissions, once we confirm that this works.
    frequency = []
    for subm_id in items:
        if (subm_id not in users_submission_ids and subm_id not in old_items):
            count = db((db.task.submission_id == subm_id)
                       & (db.task.venue_id == venue_id)).count()
            frequency.append((subm_id, count))
    # Do we have items to sample from?
    if len(frequency) == 0:
        return None
    # Now let's find submissions which have the smalles count number.
    min_count = min([x[1] for x in frequency])
    rare_items = [x[0] for x in frequency if x[1] == min_count]
    if len(rare_items) == 1:
        return rare_items[0]
    # Constructing pool of items.
    pool_items = rare_items[:]
    pool_items.extend(old_items)
    # Fetching quality distribution parameters.
    qdistr_param_pool = []
    for subm_id in pool_items:
        idx = items.index(subm_id)
        qdistr_param_pool.append(qdistr_param[2 * idx])
        qdistr_param_pool.append(qdistr_param[2 * idx + 1])
    rankobj = Rank.from_qdistr_param(pool_items,
                                     qdistr_param_pool,
                                     cost_obj=cost_obj)
    return rankobj.sample_item(old_items, black_items=[])
コード例 #10
0
ファイル: ranker.py プロジェクト: gaybro8777/crowdranker
def run_reputation_system(db,
                          venue_id,
                          alpha_annealing=0.5,
                          num_of_iterations=4,
                          last_compar_param=10):
    """ Function calculates submission qualities, user's reputation, reviewer's
    quality and final grades.
    Arguments:
        - last_compar_param works as a switch between two types of reputation system
        If the argument is None then we update using all comparisons one time in chronological order.
        Otherwise we use "small alpha" approach, where last_compar_param is
        number of iterations.
    """
    # Reading the DB to get submission and user information.
    # Lists have l suffix, dictionaries user -> val have d suffix.
    user_l, subm_l, ordering_l, subm_d, ordering_d = read_db_for_rep_sys(
        db, venue_id, last_compar_param)
    # Initializing the rest of containers.
    qdistr_param_default = []
    for subm in subm_l:
        qdistr_param_default.append(AVRG)
        qdistr_param_default.append(STDEV)
    rep_d = {user: alpha_annealing for user in user_l}
    accuracy_d = {user: 0 for user in user_l}

    # Okay, now we are ready to run main iterations.
    result = None
    for it in xrange(num_of_iterations):
        # In the beginning of iteration initialize rankobj with default
        # submissions qualities.
        rankobj = Rank.from_qdistr_param(subm_l,
                                         qdistr_param_default,
                                         alpha=alpha_annealing)
        # Okay, now we update quality distributions with comparisons
        # using reputation of users as annealing coefficient.
        if last_compar_param is None:
            # Using all comparisons in chronological order.
            for ordering, user in ordering_l:
                alpha = rep_d[user]
                result = rankobj.update(ordering, alpha_annealing=alpha)
        else:
            # Using only last comparisons and iterating many times with small alpha.
            for i in xrange(last_compar_param):
                # Genarating random permutation.
                idxs = range(len(ordering_l))
                random.shuffle(idxs)
                for idx in idxs:
                    ordering, user = ordering_l[idx]
                    alpha = rep_d[user]
                    alpha = 1 - (1 - alpha)**(1.0 / (4 * last_compar_param))
                    #alpha = alpha / float(2*last_compar_param)
                    result = rankobj.update(ordering, alpha_annealing=alpha)
        if result is None:
            return
        # Computing reputation.
        for user in rep_d:
            if subm_d.has_key(user):
                perc, avrg, stdev = result[subm_d[user]]
                rank = perc / 100.0
            else:
                rank = 0.5  # TODO(michael): Should we trust unknown reviewer?
            if ordering_d.has_key(user):
                ordering = ordering_d[user]
                accuracy = rankobj.evaluate_ordering_using_dirichlet(ordering)
            else:
                accuracy = 0
            accuracy_d[user] = accuracy
            # Computer user's reputation.
            rep_d[user] = (rank * accuracy)**0.5

    # Computing submission grades.
    subm_grade_d = {}
    for user, subm in subm_d.iteritems():
        perc, avrg, stdev = result[subm]
        subm_grade_d[subm] = perc / 100.0
    # Computing final grades.
    perc_final_d, final_grade_d = compute_final_grades_helper(
        user_l, subm_grade_d, rep_d)
    if last_compar_param is None:
        description = "Reputation system on all comparisons in chronological order"
        if num_of_iterations == 1:
            description = "Ranking without reputation system. All comparisons are used in chronological order"
    else:
        description = "Reputation system with small alpha and only last comparisons"
        if num_of_iterations == 1:
            description = "No reputation system and small alpha !?!?"
    # Writing to the BD.
    write_to_db_for_rep_sys(db,
                            venue_id,
                            result,
                            subm_l,
                            user_l,
                            ordering_d,
                            accuracy_d,
                            rep_d,
                            perc_final_d,
                            final_grade_d,
                            ranking_algo_description=description)
コード例 #11
0
ファイル: ranker.py プロジェクト: mdipierro/crowdranker
def run_reputation_system(db, venue_id, alpha_annealing=0.5,
                          num_of_iterations=4):
    """ Function calculates:
            - reputation for each user
            - user precision (quality as a reviewer)
    """
    # Fetching submission id and authors.
    # TODO(michael): take care of a case when a user has multiple submission.
    sub = db(db.submission.venue_id == venue_id).select(db.submission.id,
                                                        db.submission.author)
    items = []
    author2item = {}
    qdistr_param_default = []
    for x in sub:
        items.append(x.id)
        author2item[x.author] = x.id
        qdistr_param_default.append(AVRG)
        qdistr_param_default.append(STDEV)
    # Fetching list of comparisons.
    comparison_list_r = db(db.comparison.venue_id == venue_id).select(orderby=db.comparison.date)
    # Creating dictionaries
    # author: reputation
    # author: accuracy (confedence or reviewer's grade)
    # author: last ordering
    author2rep, author2accuracy, author2ordering = {}, {}, {}
    # Initializing these dictionaries.
    for comp in comparison_list_r:
        # Check if comparison is valid.
        if comp.is_valid is None or comp.is_valid == True:
            # Reverses the list.
            sorted_items = util.get_list(comp.ordering)[::-1]
            if len(sorted_items) < 2:
                continue
            author2ordering[comp.author] = sorted_items
            # Initializing reviewers reputation and accuracy.
            author2rep[comp.author] = alpha_annealing
            author2accuracy[comp.author] = -1
    # Okay, now we are ready to run main iterations.
    result = None
    for it in xrange(num_of_iterations):
        # In the beginning of iteration initialize rankobj with default
        # items qualities.
        rankobj = Rank.from_qdistr_param(items, qdistr_param_default,
                                         alpha=alpha_annealing)
        # Okay, now we update quality distributions with comparisons
        # using reputation of users as annealing coefficient.
        for comp in comparison_list_r:
            # Processes the comparison, if valid.
            if comp.is_valid is None or comp.is_valid == True:
                # Reverses the list.
                sorted_items = util.get_list(comp.ordering)[::-1]
                if len(sorted_items) < 2:
                    continue
                alpha = author2rep[comp.author]
                annealing_type='before_normalization_uniform'
                #annealing_type='after_normalization'
                #annealing_type='before_normalization_gauss'
                result = rankobj.update(sorted_items, new_item=comp.new_item,
                                        alpha_annealing=alpha,
                                        annealing_type=annealing_type)
        # In the end of the iteration compute reputation to use in the next iteration.
        if result is None:
            return
        for user_id in author2rep:
            if author2item.has_key(user_id):
                perc, avrg, stdev = result[author2item[user_id]]
                rank = perc / 100.0
            else:
                rank = 1 # TODO(michael): Should we trust unknown reviewer?
            ordering = author2ordering[user_id]
            accuracy = rankobj.evaluate_ordering_using_dirichlet(ordering)
            author2accuracy[user_id] = accuracy
            # Computer user's reputation.
            author2rep[user_id] = (rank * accuracy) ** 0.5
    # Updating the DB with submission ranking, users' accuracy and reputation.
    for x in items:
        perc, avrg, stdev = result[x]
        db((db.submission.id == x) &
           (db.submission.venue_id == venue_id)).update(quality=avrg, error=stdev, percentile=perc)
    for user_id in author2accuracy:
        db.user_accuracy.update_or_insert((db.user_accuracy.venue_id == venue_id) &
                                  (db.user_accuracy.user_id == user_id),
                                   venue_id = venue_id,
                                   user_id = user_id,
                                   accuracy = author2accuracy[user_id],
                                   reputation = author2rep[user_id],
                                   n_ratings = len(author2ordering[user_id]) )
    # Saving evaluation date.
    t = datetime.utcnow()
    db(db.venue.id == venue_id).update(latest_reviewers_evaluation_date = t,
                                       latest_rank_update_date = t)
    # Computing final grades for convenience.
    # TODO(michael): instead of calling method we can compute final directly
    # to optimize db access.
    compute_final_grades(db, venue_id)