You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
317 lines
11 KiB
317 lines
11 KiB
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
var PowerEdge = (function () {
|
|
function PowerEdge(source, target, type) {
|
|
this.source = source;
|
|
this.target = target;
|
|
this.type = type;
|
|
}
|
|
return PowerEdge;
|
|
}());
|
|
exports.PowerEdge = PowerEdge;
|
|
var Configuration = (function () {
|
|
function Configuration(n, edges, linkAccessor, rootGroup) {
|
|
var _this = this;
|
|
this.linkAccessor = linkAccessor;
|
|
this.modules = new Array(n);
|
|
this.roots = [];
|
|
if (rootGroup) {
|
|
this.initModulesFromGroup(rootGroup);
|
|
}
|
|
else {
|
|
this.roots.push(new ModuleSet());
|
|
for (var i = 0; i < n; ++i)
|
|
this.roots[0].add(this.modules[i] = new Module(i));
|
|
}
|
|
this.R = edges.length;
|
|
edges.forEach(function (e) {
|
|
var s = _this.modules[linkAccessor.getSourceIndex(e)], t = _this.modules[linkAccessor.getTargetIndex(e)], type = linkAccessor.getType(e);
|
|
s.outgoing.add(type, t);
|
|
t.incoming.add(type, s);
|
|
});
|
|
}
|
|
Configuration.prototype.initModulesFromGroup = function (group) {
|
|
var moduleSet = new ModuleSet();
|
|
this.roots.push(moduleSet);
|
|
for (var i = 0; i < group.leaves.length; ++i) {
|
|
var node = group.leaves[i];
|
|
var module = new Module(node.id);
|
|
this.modules[node.id] = module;
|
|
moduleSet.add(module);
|
|
}
|
|
if (group.groups) {
|
|
for (var j = 0; j < group.groups.length; ++j) {
|
|
var child = group.groups[j];
|
|
var definition = {};
|
|
for (var prop in child)
|
|
if (prop !== "leaves" && prop !== "groups" && child.hasOwnProperty(prop))
|
|
definition[prop] = child[prop];
|
|
moduleSet.add(new Module(-1 - j, new LinkSets(), new LinkSets(), this.initModulesFromGroup(child), definition));
|
|
}
|
|
}
|
|
return moduleSet;
|
|
};
|
|
Configuration.prototype.merge = function (a, b, k) {
|
|
if (k === void 0) { k = 0; }
|
|
var inInt = a.incoming.intersection(b.incoming), outInt = a.outgoing.intersection(b.outgoing);
|
|
var children = new ModuleSet();
|
|
children.add(a);
|
|
children.add(b);
|
|
var m = new Module(this.modules.length, outInt, inInt, children);
|
|
this.modules.push(m);
|
|
var update = function (s, i, o) {
|
|
s.forAll(function (ms, linktype) {
|
|
ms.forAll(function (n) {
|
|
var nls = n[i];
|
|
nls.add(linktype, m);
|
|
nls.remove(linktype, a);
|
|
nls.remove(linktype, b);
|
|
a[o].remove(linktype, n);
|
|
b[o].remove(linktype, n);
|
|
});
|
|
});
|
|
};
|
|
update(outInt, "incoming", "outgoing");
|
|
update(inInt, "outgoing", "incoming");
|
|
this.R -= inInt.count() + outInt.count();
|
|
this.roots[k].remove(a);
|
|
this.roots[k].remove(b);
|
|
this.roots[k].add(m);
|
|
return m;
|
|
};
|
|
Configuration.prototype.rootMerges = function (k) {
|
|
if (k === void 0) { k = 0; }
|
|
var rs = this.roots[k].modules();
|
|
var n = rs.length;
|
|
var merges = new Array(n * (n - 1));
|
|
var ctr = 0;
|
|
for (var i = 0, i_ = n - 1; i < i_; ++i) {
|
|
for (var j = i + 1; j < n; ++j) {
|
|
var a = rs[i], b = rs[j];
|
|
merges[ctr] = { id: ctr, nEdges: this.nEdges(a, b), a: a, b: b };
|
|
ctr++;
|
|
}
|
|
}
|
|
return merges;
|
|
};
|
|
Configuration.prototype.greedyMerge = function () {
|
|
for (var i = 0; i < this.roots.length; ++i) {
|
|
if (this.roots[i].modules().length < 2)
|
|
continue;
|
|
var ms = this.rootMerges(i).sort(function (a, b) { return a.nEdges == b.nEdges ? a.id - b.id : a.nEdges - b.nEdges; });
|
|
var m = ms[0];
|
|
if (m.nEdges >= this.R)
|
|
continue;
|
|
this.merge(m.a, m.b, i);
|
|
return true;
|
|
}
|
|
};
|
|
Configuration.prototype.nEdges = function (a, b) {
|
|
var inInt = a.incoming.intersection(b.incoming), outInt = a.outgoing.intersection(b.outgoing);
|
|
return this.R - inInt.count() - outInt.count();
|
|
};
|
|
Configuration.prototype.getGroupHierarchy = function (retargetedEdges) {
|
|
var _this = this;
|
|
var groups = [];
|
|
var root = {};
|
|
toGroups(this.roots[0], root, groups);
|
|
var es = this.allEdges();
|
|
es.forEach(function (e) {
|
|
var a = _this.modules[e.source];
|
|
var b = _this.modules[e.target];
|
|
retargetedEdges.push(new PowerEdge(typeof a.gid === "undefined" ? e.source : groups[a.gid], typeof b.gid === "undefined" ? e.target : groups[b.gid], e.type));
|
|
});
|
|
return groups;
|
|
};
|
|
Configuration.prototype.allEdges = function () {
|
|
var es = [];
|
|
Configuration.getEdges(this.roots[0], es);
|
|
return es;
|
|
};
|
|
Configuration.getEdges = function (modules, es) {
|
|
modules.forAll(function (m) {
|
|
m.getEdges(es);
|
|
Configuration.getEdges(m.children, es);
|
|
});
|
|
};
|
|
return Configuration;
|
|
}());
|
|
exports.Configuration = Configuration;
|
|
function toGroups(modules, group, groups) {
|
|
modules.forAll(function (m) {
|
|
if (m.isLeaf()) {
|
|
if (!group.leaves)
|
|
group.leaves = [];
|
|
group.leaves.push(m.id);
|
|
}
|
|
else {
|
|
var g = group;
|
|
m.gid = groups.length;
|
|
if (!m.isIsland() || m.isPredefined()) {
|
|
g = { id: m.gid };
|
|
if (m.isPredefined())
|
|
for (var prop in m.definition)
|
|
g[prop] = m.definition[prop];
|
|
if (!group.groups)
|
|
group.groups = [];
|
|
group.groups.push(m.gid);
|
|
groups.push(g);
|
|
}
|
|
toGroups(m.children, g, groups);
|
|
}
|
|
});
|
|
}
|
|
var Module = (function () {
|
|
function Module(id, outgoing, incoming, children, definition) {
|
|
if (outgoing === void 0) { outgoing = new LinkSets(); }
|
|
if (incoming === void 0) { incoming = new LinkSets(); }
|
|
if (children === void 0) { children = new ModuleSet(); }
|
|
this.id = id;
|
|
this.outgoing = outgoing;
|
|
this.incoming = incoming;
|
|
this.children = children;
|
|
this.definition = definition;
|
|
}
|
|
Module.prototype.getEdges = function (es) {
|
|
var _this = this;
|
|
this.outgoing.forAll(function (ms, edgetype) {
|
|
ms.forAll(function (target) {
|
|
es.push(new PowerEdge(_this.id, target.id, edgetype));
|
|
});
|
|
});
|
|
};
|
|
Module.prototype.isLeaf = function () {
|
|
return this.children.count() === 0;
|
|
};
|
|
Module.prototype.isIsland = function () {
|
|
return this.outgoing.count() === 0 && this.incoming.count() === 0;
|
|
};
|
|
Module.prototype.isPredefined = function () {
|
|
return typeof this.definition !== "undefined";
|
|
};
|
|
return Module;
|
|
}());
|
|
exports.Module = Module;
|
|
function intersection(m, n) {
|
|
var i = {};
|
|
for (var v in m)
|
|
if (v in n)
|
|
i[v] = m[v];
|
|
return i;
|
|
}
|
|
var ModuleSet = (function () {
|
|
function ModuleSet() {
|
|
this.table = {};
|
|
}
|
|
ModuleSet.prototype.count = function () {
|
|
return Object.keys(this.table).length;
|
|
};
|
|
ModuleSet.prototype.intersection = function (other) {
|
|
var result = new ModuleSet();
|
|
result.table = intersection(this.table, other.table);
|
|
return result;
|
|
};
|
|
ModuleSet.prototype.intersectionCount = function (other) {
|
|
return this.intersection(other).count();
|
|
};
|
|
ModuleSet.prototype.contains = function (id) {
|
|
return id in this.table;
|
|
};
|
|
ModuleSet.prototype.add = function (m) {
|
|
this.table[m.id] = m;
|
|
};
|
|
ModuleSet.prototype.remove = function (m) {
|
|
delete this.table[m.id];
|
|
};
|
|
ModuleSet.prototype.forAll = function (f) {
|
|
for (var mid in this.table) {
|
|
f(this.table[mid]);
|
|
}
|
|
};
|
|
ModuleSet.prototype.modules = function () {
|
|
var vs = [];
|
|
this.forAll(function (m) {
|
|
if (!m.isPredefined())
|
|
vs.push(m);
|
|
});
|
|
return vs;
|
|
};
|
|
return ModuleSet;
|
|
}());
|
|
exports.ModuleSet = ModuleSet;
|
|
var LinkSets = (function () {
|
|
function LinkSets() {
|
|
this.sets = {};
|
|
this.n = 0;
|
|
}
|
|
LinkSets.prototype.count = function () {
|
|
return this.n;
|
|
};
|
|
LinkSets.prototype.contains = function (id) {
|
|
var result = false;
|
|
this.forAllModules(function (m) {
|
|
if (!result && m.id == id) {
|
|
result = true;
|
|
}
|
|
});
|
|
return result;
|
|
};
|
|
LinkSets.prototype.add = function (linktype, m) {
|
|
var s = linktype in this.sets ? this.sets[linktype] : this.sets[linktype] = new ModuleSet();
|
|
s.add(m);
|
|
++this.n;
|
|
};
|
|
LinkSets.prototype.remove = function (linktype, m) {
|
|
var ms = this.sets[linktype];
|
|
ms.remove(m);
|
|
if (ms.count() === 0) {
|
|
delete this.sets[linktype];
|
|
}
|
|
--this.n;
|
|
};
|
|
LinkSets.prototype.forAll = function (f) {
|
|
for (var linktype in this.sets) {
|
|
f(this.sets[linktype], Number(linktype));
|
|
}
|
|
};
|
|
LinkSets.prototype.forAllModules = function (f) {
|
|
this.forAll(function (ms, lt) { return ms.forAll(f); });
|
|
};
|
|
LinkSets.prototype.intersection = function (other) {
|
|
var result = new LinkSets();
|
|
this.forAll(function (ms, lt) {
|
|
if (lt in other.sets) {
|
|
var i = ms.intersection(other.sets[lt]), n = i.count();
|
|
if (n > 0) {
|
|
result.sets[lt] = i;
|
|
result.n += n;
|
|
}
|
|
}
|
|
});
|
|
return result;
|
|
};
|
|
return LinkSets;
|
|
}());
|
|
exports.LinkSets = LinkSets;
|
|
function intersectionCount(m, n) {
|
|
return Object.keys(intersection(m, n)).length;
|
|
}
|
|
function getGroups(nodes, links, la, rootGroup) {
|
|
var n = nodes.length, c = new Configuration(n, links, la, rootGroup);
|
|
while (c.greedyMerge())
|
|
;
|
|
var powerEdges = [];
|
|
var g = c.getGroupHierarchy(powerEdges);
|
|
powerEdges.forEach(function (e) {
|
|
var f = function (end) {
|
|
var g = e[end];
|
|
if (typeof g == "number")
|
|
e[end] = nodes[g];
|
|
};
|
|
f("source");
|
|
f("target");
|
|
});
|
|
return { groups: g, powerEdges: powerEdges };
|
|
}
|
|
exports.getGroups = getGroups;
|
|
//# sourceMappingURL=powergraph.js.map
|