pm4js
Version:
Process Mining for Javascript
474 lines (459 loc) • 12.8 kB
JavaScript
class OcelGraphs {
static getObjectsLifecycle(ocel) {
let lif = {};
let objects = ocel["ocel:objects"];
for (let objId in objects) {
lif[objId] = [];
}
let events = ocel["ocel:events"];
for (let evId in events) {
let eve = events[evId];
for (let objId of eve["ocel:omap"]) {
lif[objId].push(evId);
}
}
return lif;
}
static eventsRelationGraph(ocel) {
let lif = OcelGraphs.getObjectsLifecycle(ocel);
let eveRelGraph = {};
for (let evId in ocel["ocel:events"]) {
eveRelGraph[evId] = {};
}
for (let objId in lif) {
let objLif = lif[objId];
let i = 0;
while (i < objLif.length - 1) {
let j = i + 1;
while (j < objLif.length) {
eveRelGraph[objLif[i]][objLif[j]] = 0;
eveRelGraph[objLif[j]][objLif[i]] = 0;
j++;
}
i++;
}
}
return eveRelGraph;
}
static objectInteractionGraph(ocel) {
let ret = {};
let events = ocel["ocel:events"];
let objects = ocel["ocel:objects"];
let evIds = Object.keys(events);
for (let evId of evIds) {
let eve = events[evId];
for (let objId of eve["ocel:omap"]) {
for (let objId2 of eve["ocel:omap"]) {
if (objId != objId2) {
ret[[objId, objId2]] = 0;
}
}
}
}
return OcelGraphs.transformArrayToDictArray(Object.keys(ret));
}
static objectDescendantsGraph(ocel) {
let ret = {};
let events = ocel["ocel:events"];
let objects = ocel["ocel:objects"];
let evIds = Object.keys(events);
let seenObjects = {};
for (let evId of evIds) {
let eve = events[evId];
for (let objId of eve["ocel:omap"]) {
if (objId in seenObjects) {
for (let objId2 of eve["ocel:omap"]) {
if (!(objId2 in seenObjects)) {
ret[[objId, objId2]] = 0;
}
}
}
}
for (let objId of eve["ocel:omap"]) {
if (!(objId in seenObjects)) {
seenObjects[objId] = 0;
}
}
}
return OcelGraphs.transformArrayToDictArray(Object.keys(ret));
}
static objectCobirthGraph(ocel) {
let ret = {};
let events = ocel["ocel:events"];
let objects = ocel["ocel:objects"];
let evIds = Object.keys(events);
let seenObjects = {};
for (let evId of evIds) {
let eve = events[evId];
for (let objId of eve["ocel:omap"]) {
if (!(objId in seenObjects)) {
for (let objId2 of eve["ocel:omap"]) {
if (!(objId2 in seenObjects)) {
if (objId != objId2) {
ret[[objId, objId2]] = 0;
}
}
}
}
}
for (let objId of eve["ocel:omap"]) {
if (!(objId in seenObjects)) {
seenObjects[objId] = 0;
}
}
}
return OcelGraphs.transformArrayToDictArray(Object.keys(ret));
}
static objectCodeathGraph(ocel) {
let ret = {};
let events = ocel["ocel:events"];
let objects = ocel["ocel:objects"];
let evIds = Object.keys(events).reverse();
let seenObjects = {};
for (let evId of evIds) {
let eve = events[evId];
for (let objId of eve["ocel:omap"]) {
if (!(objId in seenObjects)) {
for (let objId2 of eve["ocel:omap"]) {
if (!(objId2 in seenObjects)) {
if (objId != objId2) {
ret[[objId, objId2]] = 0;
}
}
}
}
}
for (let objId of eve["ocel:omap"]) {
if (!(objId in seenObjects)) {
seenObjects[objId] = 0;
}
}
}
return OcelGraphs.transformArrayToDictArray(Object.keys(ret));
}
static objectInheritanceGraph(ocel) {
let ret = {};
let events = ocel["ocel:events"];
let objects = ocel["ocel:objects"];
let evIds = Object.keys(events).reverse();
let lastEventLifecycle = {};
for (let evId of evIds) {
let eve = events[evId];
for (let objId of eve["ocel:omap"]) {
if (!(objId in lastEventLifecycle)) {
lastEventLifecycle[objId] = evId;
}
}
}
evIds = evIds.reverse();
let seenObjects = {};
for (let evId of evIds) {
let eve = events[evId];
for (let objId of eve["ocel:omap"]) {
if (objId in seenObjects) {
if (objId in lastEventLifecycle && lastEventLifecycle[objId] == evId) {
for (let objId2 of eve["ocel:omap"]) {
if (objId != objId2) {
if (!(objId2 in seenObjects)) {
ret[[objId, objId2]] = 0;
}
}
}
}
}
}
for (let objId of eve["ocel:omap"]) {
seenObjects[objId] = 0;
}
}
return OcelGraphs.transformArrayToDictArray(Object.keys(ret));
}
static graphFindInterrupts(ocel) {
let objInteractionGraph = OcelGraphs.objectInteractionGraph(ocel);
let objects = ocel["ocel:objects"];
let objTypes = {};
for (let objId in objects) {
let objType = objects[objId]["ocel:type"];
objTypes[objId] = objType;
}
let lifecycleObj = OcelObjectFeatures.getObjectsLifecycle(ocel);
let lifecycleStartEnd = {};
for (let objId in lifecycleObj) {
if (lifecycleObj[objId].length > 0) {
lifecycleStartEnd[objId] = [lifecycleObj[objId][0]["ocel:timestamp"].getTime()/1000.0, lifecycleObj[objId][lifecycleObj[objId].length-1]["ocel:timestamp"].getTime()/1000.0];
}
}
let interrupts = {};
for (let objId in objInteractionGraph) {
if (objId in lifecycleStartEnd) {
let lifse = lifecycleStartEnd[objId];
for (let objId2 of objInteractionGraph[objId]) {
if (objId2 in lifecycleStartEnd) {
if (objTypes[objId2] != objTypes[objId]) {
let lifse2 = lifecycleStartEnd[objId2];
if (lifse[0] > lifse2[0] && lifse[1] < lifse2[1]) {
let lif = lifecycleObj[objId];
let lif2 = lifecycleObj[objId2];
let isOk = true;
let i = 0;
while (i < lif2.length) {
let currTime = lif2[i]["ocel:timestamp"].getTime()/1000.0;
if (currTime > lifse[0] && currTime < lifse[1]) {
if (!(lif.includes(lif2[i]))) {
isOk = false;
break;
}
}
i++;
}
if (isOk) {
if (!(objId in interrupts)) {
interrupts[objId] = [];
}
interrupts[objId].push(objId2);
}
}
}
}
}
}
}
return interrupts;
}
static graphFindLocks(ocel) {
let objInteractionGraph = OcelGraphs.objectInteractionGraph(ocel);
let objects = ocel["ocel:objects"];
let objTypes = {};
for (let objId in objects) {
let objType = objects[objId]["ocel:type"];
objTypes[objId] = objType;
}
let lifecycleObj = OcelObjectFeatures.getObjectsLifecycle(ocel);
let lifecycleStartEnd = {};
for (let objId in lifecycleObj) {
if (lifecycleObj[objId].length > 0) {
lifecycleStartEnd[objId] = [lifecycleObj[objId][0]["ocel:timestamp"].getTime()/1000.0, lifecycleObj[objId][lifecycleObj[objId].length-1]["ocel:timestamp"].getTime()/1000.0];
}
}
let interactionDivided = {};
for (let objId in objInteractionGraph) {
interactionDivided[objId] = {};
for (let objId2 of objInteractionGraph[objId]) {
let objType = objTypes[objId2];
if (!(objType in interactionDivided[objId])) {
interactionDivided[objId][objType] = [];
}
interactionDivided[objId][objType].push(objId2);
}
}
let locks = {};
for (let objId in interactionDivided) {
if (objId in lifecycleStartEnd) {
let lifse = lifecycleStartEnd[objId];
let currObjType = objTypes[objId];
for (let objType in interactionDivided[objId]) {
if (objType != currObjType) {
if (interactionDivided[objId][objType].length == 1) {
let objId2 = interactionDivided[objId][objType][0];
let otherInteractions = interactionDivided[objId2][currObjType];
let otherInteractionsLifStartEnd = [];
for (let objId3 of otherInteractions) {
if (objId3 != objId) {
if (objId3 in lifecycleStartEnd) {
otherInteractionsLifStartEnd.push(lifecycleStartEnd[objId3]);
}
}
}
let isOk = true;
if (otherInteractionsLifStartEnd.length == 0) {
isOk = false;
}
let i = 0;
while (i < otherInteractionsLifStartEnd.length) {
let lifse2 = otherInteractionsLifStartEnd[i];
if (!(lifse2[i][1] < lifse[i][0] || lifse2[i][0] > lifse[i][1])) {
isOk = false;
break;
}
i++;
}
if (isOk) {
if (!(objId in locks)) {
locks[objId] = [];
}
locks[objId].push(objId2);
}
}
}
}
}
}
return locks;
}
static graphFindParents(ocel) {
let objInteractionGraph = OcelGraphs.objectInteractionGraph(ocel);
let objects = ocel["ocel:objects"];
let objTypes = {};
for (let objId in objects) {
let objType = objects[objId]["ocel:type"];
objTypes[objId] = objType;
}
let lifecycleObj = OcelObjectFeatures.getObjectsLifecycle(ocel);
let lifecycleStartEnd = {};
for (let objId in lifecycleObj) {
if (lifecycleObj[objId].length > 0) {
lifecycleStartEnd[objId] = [lifecycleObj[objId][0]["ocel:timestamp"].getTime()/1000.0, lifecycleObj[objId][lifecycleObj[objId].length-1]["ocel:timestamp"].getTime()/1000.0];
}
}
let interactionDivided = {};
for (let objId in objInteractionGraph) {
interactionDivided[objId] = {};
for (let objId2 of objInteractionGraph[objId]) {
let objType = objTypes[objId2];
if (!(objType in interactionDivided[objId])) {
interactionDivided[objId][objType] = [];
}
interactionDivided[objId][objType].push(objId2);
}
}
let parents = {};
for (let objId in interactionDivided) {
let currType = objTypes[objId];
for (let objType in interactionDivided[objId]) {
if (objType != currType) {
if (interactionDivided[objId][objType].length == 1) {
let objId2 = interactionDivided[objId][objType][0];
if (objId in lifecycleStartEnd && objId2 in lifecycleStartEnd) {
let lif = lifecycleStartEnd[objId];
let lif2 = lifecycleStartEnd[objId2];
if (lif[0] >= lif2[0] && lif[1] <= lif2[1]) {
parents[objId] = objId2;
}
}
}
}
}
}
return parents;
}
static graphFindChildren(ocel) {
let parents = OcelGraphs.graphFindParents(ocel);
let children = {};
for (let child in parents) {
let par = parents[child];
if (!(par in children)) {
children[par] = [];
}
children[par].push(child);
}
return children;
}
static transformArrayToDictArray(arr) {
let dl = {};
let i = 0;
while (i < arr.length) {
let spli = arr[i].split(",");
if (!(spli[0] in dl)) {
dl[spli[0]] = [];
}
dl[spli[0]].push(spli[1]);
i++;
}
return dl;
}
static expandGraph(graph0) {
let graph = {};
for (let k in graph0) {
graph[k] = {};
for (let k2 of graph0[k]) {
graph[k][k2] = 0;
}
}
let toVisit = {};
let invGraph = {};
for (let k in graph) {
if (!(k in invGraph)) {
invGraph[k] = [];
}
for (let k2 in graph[k]) {
if (!(k2 in invGraph)) {
invGraph[k2] = {};
}
invGraph[k2][k] = 0;
}
}
for (let k in graph) {
toVisit[k] = 0;
}
while (true) {
let newToVisit = {};
for (let k2 in toVisit) {
for (let k in invGraph[k2]) {
let newGraph = Object.assign({}, graph[k]);
for (let k3 in graph[k2]) {
newGraph[k3] = 0;
}
if (Object.keys(newGraph).length > Object.keys(graph[k]).length) {
graph[k] = newGraph;
newToVisit[k] = 0;
}
}
}
if (Object.keys(newToVisit).length == 0) {
break;
}
toVisit = newToVisit;
}
for (let k in graph) {
graph[k] = Object.keys(graph[k]);
}
return graph;
}
static connectedComponents(graph) {
let allNodes = {};
for (let k in graph) {
allNodes[k] = 0;
for (let k2 of graph[k]) {
allNodes[k2] = 0;
}
}
let count = 0;
for (let k in allNodes) {
allNodes[k] = count;
count = count + 1;
}
let changed = true;
while (changed) {
changed = false;
for (let k in graph) {
for (let k2 of graph[k]) {
let v1 = allNodes[k];
let v2 = allNodes[k2];
if (v1 != v2) {
changed = true;
let v3 = Math.min(v1, v2);
allNodes[k] = v3;
allNodes[k2] = v3;
}
}
}
}
let nodesGrouping = {};
for (let k in allNodes) {
let v = allNodes[k];
if (!(v in nodesGrouping)) {
nodesGrouping[v] = [];
}
nodesGrouping[v].push(k);
}
return Object.values(nodesGrouping);
}
}
try {
module.exports = {OcelGraphs: OcelGraphs};
global.OcelGraphs = OcelGraphs;
}
catch (err) {
// not in node
//console.log(err);
}