| 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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 |
3x
3x
3x
3x
676x
676x
7078x
7078x
676x
676x
3x
816x
816x
1959x
1959x
256x
1703x
1703x
560x
3x
167x
167x
684x
167x
3x
165x
674x
165x
165x
674x
3x
163x
163x
163x
163x
163x
163x
163x
670x
163x
3x
165x
1527x
1527x
165x
674x
674x
12x
662x
662x
6989x
6989x
1460x
1460x
662x
237x
237x
237x
425x
425x
165x
3x
6915x
6915x
16041x
16041x
16041x
5305x
1610x
3x
3x
14017x
14017x
7160x
6857x
3x
10764x
| /*!
GPII Canopy Matchmaker
Copyright 2012 OCAD University
Copyright 2012 Antranig Basman
Licensed under the New BSD license. You may not use this file except in
compliance with this License.
The research leading to these results has received funding from the European Union's
Seventh Framework Programme (FP7/2007-2013) under grant agreement no. 289016.
You may obtain a copy of the License at
https://github.com/GPII/universal/blob/master/LICENSE.txt
*/
"use strict";
var fluid = fluid || require("infusion");
var gpii = gpii || fluid.registerNamespace("gpii");
fluid.registerNamespace("gpii.canopyMatchMaker.utils");
gpii.canopyMatchMaker.utils.computeFitness = function (leaves, solution, ontologicalMetricFunction) {
var vector = [];
for (var i = 0; i < leaves.length; ++i) {
var leaf = leaves[i];
vector[i] = ontologicalMetricFunction(leaf, solution);
}
vector = vector.sort(gpii.canopyMatchMaker.utils.sortDescending);
return vector;
};
gpii.canopyMatchMaker.utils.compareFitness = function (solA, solB) {
var i = 0, fitA = solA.fitness, fitB = solB.fitness;
for (; ; ++i) {
var endA = i === fitA.length, endB = i === fitB.length;
if (endA || endB) {
return endA && endB ? 0 : (endB ? -1 : 1);
}
var diff = fitB[i] - fitA[i];
if (diff !== 0) {
return diff;
}
}
};
/*
* @leaves {object}
* @solrecs {object} map of solutions keyed by solution id.
*/
gpii.canopyMatchMaker.utils.sortSolutions = function (solutions) {
var solArr = [];
for (var i in solutions) {
solArr.push(solutions[i]);
}
return solArr.sort(gpii.canopyMatchMaker.utils.compareFitness);
};
/*
* @leaves {object}
* @solrecs {object} map of solutions keyed by solution id.
*/
gpii.canopyMatchMaker.utils.rankSolutions = function (leaves, solrecs, ontologicalMetricFunction) {
fluid.each(solrecs, function (solrec) {
solrec.fitness = gpii.canopyMatchMaker.utils.computeFitness(leaves, solrec.skeleton, ontologicalMetricFunction);
});
var solArr = gpii.canopyMatchMaker.utils.sortSolutions(solrecs);
return fluid.transform(solArr, function (value) {
return value.index;
});
};
/*
* @leaves {object}
* @solrecs {object} map of solutions keyed by solution id.
*/
gpii.canopyMatchMaker.utils.disposeStrategy = function (leaves, solrecs, data, ontologyMetadata) {
var ontologicalMetricName = fluid.get(ontologyMetadata, "ontologicalMetricFunction") || "gpii.canopyMatchMaker.utils.prefixLength";
var ontologicalMetricFunction = fluid.getGlobalValue(ontologicalMetricName);
// if we already have priority for some solutions, accept these and reject any applications
// of same type.
gpii.matchMakerFramework.utils.disposeFromPriority(solrecs, data);
// rank remaining solutions based on fit to preferences
var ranked = gpii.canopyMatchMaker.utils.rankSolutions(leaves, solrecs, ontologicalMetricFunction);
// dispose based on canopy
var disposed = gpii.canopyMatchMaker.utils.disposeFromCanopy(leaves, ranked, solrecs, data, ontologicalMetricFunction);
// re-key by solution id:
var togo = {};
fluid.each(disposed, function (val) {
togo[val.index] = val;
});
return togo;
};
gpii.canopyMatchMaker.utils.disposeFromCanopy = function (leaves, ranked, solrecs, data, ontologicalMetricFunction) {
// Set default canopy to negative leaf depth. To raise the canopy, a preference needs to
// match at least one level into the leaf.
var canopy = fluid.transform(leaves, function (leaf) {
var leafDepth = fluid.pathUtil.parseEL(leaf).length;
return -leafDepth;
});
for (var i = 0; i < ranked.length; ++i) {
var sol = solrecs[ranked[i]];
if (sol.disposition === "reject") {
continue;
}
var inCanopy = false;
for (var j = 0; j < leaves.length; ++j) {
var depth = ontologicalMetricFunction(leaves[j], sol.skeleton);
if (depth > canopy[j]) {
inCanopy = true;
canopy[j] = depth;
}
}
if (inCanopy) {
sol.disposition = "accept";
sol.dispositionReason = "Was the solution of this type that best fit user preferences";
gpii.matchMakerFramework.utils.rejectFromTypes(data.solutionTypes[sol.index],
data.solutionTypeMapping, solrecs, "Another solution (" + sol.index +
") covering more preferences was found found.");
} else {
sol.disposition = "reject";
sol.dispositionReason = "Was not in canopy.";
}
}
return solrecs;
};
/** Returns a non-positive number indicating by how many path segments the supplied
* path fails to index correctly into the supplied model. A return value of 0
* indicates that the path indexes fully
*/
gpii.canopyMatchMaker.utils.prefixLength = function (path, model) {
var segs = fluid.pathUtil.parseEL(path);
for (var i = 0; i < segs.length; ++i) {
var seg = segs[i];
model = model[seg];
if (model === undefined) {
return i - segs.length;
}
}
return 0;
};
fluid.registerNamespace("gpii.canopyMatchMaker.utils.ISO24751");
gpii.canopyMatchMaker.utils.ISO24751.ontologicalMetric = function (path, model) {
var segs = fluid.pathUtil.parseEL(path);
// if it's an application setting and the application is not matching, consider worst fit
if (segs[0] === "applications" && fluid.get(model, ["applications", segs[1]]) === undefined) {
return -Infinity;
} else { // else do fitting as usual
return gpii.canopyMatchMaker.utils.prefixLength(path, model);
}
};
// only used by canopyMatchMaker - moved from MatchMakerFramework
gpii.canopyMatchMaker.utils.sortDescending = function (numA, numB) {
return numB - numA;
};
|