-
Notifications
You must be signed in to change notification settings - Fork 0
/
Calculators.py
93 lines (79 loc) · 3.7 KB
/
Calculators.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import math
from functools import reduce
import CustomLib
from Enums import SubmissionType
class WeightCalculator:
@staticmethod
def calc_simple_voting(user, similar_user, sim_value):
return 1
@staticmethod
def calc_weighted_voting(user, similar_user, sim_value):
similarity_sum = reduce(lambda acc, item: acc + item[1], user.similarities, 0)
# CustomLib.debug_print("weighted", user, sim_value, sum)
return float(sim_value) / similarity_sum
@staticmethod
def calc_positional_voting(user, similar_user, sim_value):
return 1.0 / (user.similarities.index((similar_user, sim_value)) + 1)
class SimilarityCalculator:
@staticmethod
def calc_jaccard_neighbours(user1, user2):
user1_neighbours = list(user1.projections.keys())
user2_neighbours = list(user2.projections.keys())
intersection_val = CustomLib.intersection_length(user1_neighbours, user2_neighbours)
union_val = CustomLib.union_length(user1_neighbours, user2_neighbours)
ans = 0 if union_val == 0 else intersection_val / union_val
return ans
@staticmethod
def calc_jaccard_problems(user1, user2):
if user2 not in user1.projections:
# CustomLib.debug_print("Jaccard check", )
return 0
intersection_val = user1.projections[user2]
union_val = CustomLib.union_length(user1.problems_solved + user1.problems_unsolved,
user2.problems_solved + user2.problems_unsolved)
ans = 0 if union_val == 0 else intersection_val / union_val
return ans
@staticmethod
def calc_edge_weight(user1, user2):
return 0 if user2 not in user1.projections \
else user1.projections[user2]
@staticmethod
def calc_common_neighbours(user1, user2):
intersection = CustomLib.intersection(user1.projections, user2.projections)
ans = reduce(lambda acc, user: acc + user1.projections[user] + user2.projections[user], intersection, 0)
return ans
@staticmethod
def calc_adar_atamic(user1, user2):
user1_neighbourhood = user1.projections
user2_neighbourhood = user2.projections
intersection = CustomLib.intersection(user1_neighbourhood,
user2_neighbourhood)
ans = reduce(lambda acc, user: acc + (user1_neighbourhood[user] + user2_neighbourhood[user])
/ math.log(1 + reduce(lambda acc2, i: acc2 + i,
user.projections.values(),
0)
),
intersection,
0)
return ans
@staticmethod
def calc_preferential(user1, user2):
ans = reduce(lambda acc, i: acc + i, user1.projections.values(), 0) * \
reduce(lambda acc, i: acc + i, user2.projections.values(), 0)
return ans
def calc_edge(user1, user2):
intersection = CustomLib.intersection(user1.submissions_stats, user2.submissions_stats)
ans = 0
for i in intersection:
s1 = user1.submissions_stats[i]
s2 = user2.submissions_stats[i]
solved = [SubmissionType.solved_with_few,
SubmissionType.solved_with_many]
unsolved = [SubmissionType.unsolved_with_few,
SubmissionType.unsolved_with_many]
if s1.submission_type == s2.submission_type:
ans += 1
elif (s1.submission_type in solved and s2.submission_type in solved)\
or (s1.submission_type in unsolved and s2.submission_type in unsolved):
ans += 0.7
return ans