def get_credibility(comparables_a, comparables_b, concordance, discordance, with_denominator, only_max_discordance, cv_crossed): def _get_credibility_idx(x, y, num_crossed, only_max_discordance): discordance_values = discordance[x][y].values() if set(discordance_values) == set([0]): # only zeros c_idx = concordance[x][y] elif 1 in discordance_values: # at least one '1' if not concordance[x][y] < 1: raise RuntimeError("When discordance == 1, " "concordance must be < 1.") c_idx = 0.0 elif only_max_discordance and not with_denominator: c_idx = concordance[x][y] * (1 - max(discordance_values)) else: factors = [] for d in discordance_values: if with_denominator: if d > concordance[x][y]: factor = (1 - d) / (1 - concordance[x][y]) else: factor = None else: factor = (1 - d) if factor: factors.append(factor) if factors == []: c_idx = concordance[x][y] else: discordance_aggr = reduce(lambda f1, f2: f1 * f2, factors) c_idx = (concordance[x][y] * discordance_aggr**(1 - num_crossed / num_total)) return c_idx two_way_comparison = True if comparables_a != comparables_b else False # 'num_total' == total number of criteria. # Instead of this monstrosity below, maybe it would be better to provide # 'criteria.xml' as another input..? num_total = len(discordance.values()[0].values()[0].keys()) credibility = Vividict() for a in comparables_a: for b in comparables_b: num_crossed = len(cv_crossed[a][b]) credibility[a][b] = _get_credibility_idx(a, b, num_crossed, only_max_discordance) if two_way_comparison: credibility[b][a] = _get_credibility_idx( b, a, num_crossed, only_max_discordance) return credibility