-
Notifications
You must be signed in to change notification settings - Fork 2
/
DP_matcher.rb
134 lines (119 loc) · 2.98 KB
/
DP_matcher.rb
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
require "./expression.rb"
class DPMatcher
def initialize()
@cache = {};
end
def match(x,y,i,j)
if(@cache[[i,j]] != nil) then
return @cache[[i,j]][0];
end
if x.size == i then
@cache[[i,j]] = [0, 3];
return 0;
end
if y.size == j then
@cache[[i,j]] = [0, 3];
return 0;
end
value = [];
value[0] = x[i].cmp(y[j]) + match(x,y,i+1,j+1)
value[1] = match(x, y, i ,j+1)
value[2] = match(x, y, i+1,j )
max_value = 0;
max_index = 0;
index = 0;
value.each{
|x|
if x > max_value then
max_value = x;
max_index = index;
end
index += 1;
}
@cache[[i,j]] = [max_value, max_index];
return max_value;
end
def get_pairs(x,y, start = 0)
@cache = {};
match(x, y, start, start);
pairs = [];
i = j = start;
curr = @cache[[i,j]][1]
while curr != 3
case curr
when 0 then
pairs += [[i,j]] if x[i].cmp(y[j]) > Float::EPSILON
i+=1;
j+=1;
when 1 then
j+=1;
when 2 then
i+=1;
end
curr = @cache[[i,j]][1]
end
return [@cache[[start, start]][0], pairs];
end
def generate_pairs(values1, values2)
pairs = get_pairs(values1, values2)[1]
for i in 0..pairs.size-1 do
if values1[pairs[i][0]].class == MetaExpression && values2[pairs[i][1]].class == MetaExpression then
pairs[i] += [generate_pairs(values1[pairs[i][0]].value, values2[pairs[i][1]].value)];
end
end
return pairs
end
# Filter pairs in 3-lines
# input: recursive pair array * 2
# output: [new_pair_array1, new_pair_array2]
def reconsider_pairs(pairs1, pairs2)
out_pairs1 = [];
out_pairs2 = [];
p1_index = 0;
p2_index = 0;
while p1_index != pairs1.size && p2_index != pairs2.size do
if (pairs1[p1_index][1] == pairs2[p2_index][0]) then
out_pairs1.append([pairs1[p1_index][0],pairs1[p1_index][1]])
out_pairs2.append([pairs2[p2_index][0],pairs2[p2_index][1]])
if(pairs1[p1_index].size > 2 && pairs1[p2_index].size > 2) then
internal_res = reconsider_pairs(pairs1[p1_index][2], pairs2[p2_index][2]);
out_pairs1.last.push(internal_res[0])
out_pairs2.last.push(internal_res[1])
end
p1_index += 1;
p2_index += 1;
next;
end
if(pairs1[p1_index][1] > pairs2[p2_index][0]) then
p2_index += 1;
next;
end
if(pairs1[p1_index][1] < pairs2[p2_index][0]) then
p1_index += 1;
next;
end
end
return [out_pairs1, out_pairs2];
end
# input: [meta1, meta2], [[i1,i2], [i1,i2], ....]
# output: float
def get_simularity(metas, pairs, n = [0])
sum = 0.0;
pairs.each do |pair|
if pair.size > 2 then
n[0] -= 1;
# magic numbers here
sum += get_simularity([metas[0].value[pair[0]], metas[1].value[pair[1]]], pair[2], n);
else
sum += metas[0].value[pair[0]].cmp(metas[1].value[pair[1]]);
end
end
n[0] += [metas[0].value.size(), metas[1].value.size()].max;
return sum;
end
def get_percent_simularity(metas, pairs)
n = [0];
s = get_simularity(metas, pairs, n);
return s / n[0].to_f;
end
end