Skip to content

Commit 05407b4

Browse files
committed
Alpha Precision Calculator, Unrestricted
1 parent e0a1b02 commit 05407b4

14 files changed

+1055
-0
lines changed

src/main/java/qut/pm/spm/Measure.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public enum Measure {
77
LOG_EVENT_COUNT("Log Events"), LOG_TRACE_COUNT("Log Traces"),
88
MODEL_ENTITY_COUNT("Entities"), MODEL_EDGE_COUNT("Edges"),
99
NORMALIZED_PETRI_NET_EDGE_SIMPLICITY,
10+
ALPHA_PRECISION_UNRESTRICTED("alpha-precision UR"), // Depaire et al 2022
1011
EARTH_MOVERS_LIGHT_COVERAGE("tEMSC 0.8"), // Leemans 2019
1112
EARTH_MOVERS_SIMILARITY,
1213
ENTROPY_PRECISION("S_precision"),
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package qut.pm.spm;
2+
3+
public class NumUtils {
4+
5+
public static final double EPSILON = 0.001;
6+
7+
public static boolean nearEquals(double d1, double d2, double epsilon) {
8+
return Math.abs(d1-d2) < epsilon;
9+
}
10+
11+
public static boolean nearEquals(double d1, double d2) {
12+
return nearEquals(d1,d2,EPSILON);
13+
}
14+
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package qut.pm.spm;
2+
3+
public class SPMConfigException extends RuntimeException {
4+
5+
/**
6+
*
7+
*/
8+
private static final long serialVersionUID = -7582562352978631933L;
9+
10+
public SPMConfigException(String message) {
11+
super(message);
12+
}
13+
14+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package qut.pm.spm;
2+
3+
import java.util.HashMap;
4+
import java.util.List;
5+
import java.util.Map;
6+
import java.util.Set;
7+
8+
/**
9+
* Allows R+ valued frequencies. This makes it possible to model scaled play-out logs with non-natural
10+
* frequencies.
11+
*
12+
* @author burkeat
13+
*
14+
*/
15+
public class TraceFreq{
16+
private Map<List<String>,Double> traceFreq = new HashMap<>();
17+
private double traceTotal = 0;
18+
19+
public Map<List<String>, Double> getTraceFreq() {
20+
return traceFreq;
21+
}
22+
23+
public double getTraceTotal() {
24+
return traceTotal;
25+
}
26+
27+
public double getFreq(List<String> trace) {
28+
Double result = traceFreq.get(trace);
29+
if (result == null) {
30+
return 0;
31+
}
32+
return result;
33+
}
34+
35+
public void incTraceFreq(List<String> trace) {
36+
double freq = getFreq(trace);
37+
traceFreq.put(trace,freq+1);
38+
traceTotal += 1;
39+
}
40+
41+
public void incTraceFreq(List<String> trace, double plusFreq) {
42+
double freq = getFreq(trace);
43+
traceFreq.put(trace,freq+plusFreq);
44+
traceTotal += plusFreq;
45+
}
46+
47+
public void putFreq(List<String> trace, double freq) {
48+
double oldFreq = getFreq(trace);
49+
traceFreq.put(trace,freq);
50+
traceTotal += freq - oldFreq;
51+
}
52+
53+
public void forceTraceTotal(double traceTotal) {
54+
this.traceTotal = traceTotal;
55+
}
56+
57+
public double getInternalTraceTotal() {
58+
double sum = 0;
59+
for ( List<String> key : traceFreq.keySet() ) {
60+
sum += traceFreq.get(key);
61+
}
62+
return sum;
63+
}
64+
65+
public void scaleBy(double factor) {
66+
traceTotal = traceTotal* factor;
67+
for ( List<String> key : traceFreq.keySet() ) {
68+
traceFreq.put( key, traceFreq.get(key)*factor );
69+
}
70+
}
71+
72+
public Set<List<String>> keySet() {
73+
return traceFreq.keySet();
74+
}
75+
76+
public String format() {
77+
return "TraceFreq [traceFreq=" + traceFreq + "]";
78+
}
79+
80+
public String toString() {
81+
return format();
82+
}
83+
84+
85+
86+
@Override
87+
public int hashCode() {
88+
final int prime = 31;
89+
int result = 1;
90+
result = prime * result + ((traceFreq == null) ? 0 : traceFreq.hashCode());
91+
long temp;
92+
temp = Double.doubleToLongBits(traceTotal);
93+
result = prime * result + (int) (temp ^ (temp >>> 32));
94+
return result;
95+
}
96+
97+
@Override
98+
public boolean equals(Object obj) {
99+
if (this == obj)
100+
return true;
101+
if (obj == null)
102+
return false;
103+
if (getClass() != obj.getClass())
104+
return false;
105+
TraceFreq other = (TraceFreq) obj;
106+
if (traceFreq == null) {
107+
if (other.traceFreq != null)
108+
return false;
109+
} else if (!traceFreq.equals(other.traceFreq))
110+
return false;
111+
if (Double.doubleToLongBits(traceTotal) != Double.doubleToLongBits(other.traceTotal))
112+
return false;
113+
return true;
114+
}
115+
116+
117+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package qut.pm.spm;
2+
3+
import java.util.LinkedList;
4+
5+
import org.deckfour.xes.classification.XEventClassifier;
6+
import org.deckfour.xes.model.XEvent;
7+
import org.deckfour.xes.model.XLog;
8+
import org.deckfour.xes.model.XTrace;
9+
10+
public class TraceFreqGenerator {
11+
12+
public TraceFreq calculateForLog(XLog log, XEventClassifier classifier) {
13+
TraceFreq result = new TraceFreq();
14+
for (XTrace trace: log) {
15+
LinkedList<String> newTrace = new LinkedList<String>();
16+
for (XEvent event: trace) {
17+
String classId = classifier.getClassIdentity(event);
18+
newTrace.add(classId);
19+
}
20+
result.incTraceFreq(newTrace);
21+
}
22+
return result;
23+
}
24+
25+
26+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package qut.pm.spm.conformance;
2+
3+
import java.util.List;
4+
import java.util.Map;
5+
6+
import qut.pm.spm.TraceFreq;
7+
8+
public class AlphaPrecisionCalculation {
9+
10+
public double calculatePrecision(TraceFreq tfLog, TraceFreq tfModel, int logTotalEvents,
11+
double alphaSig,int numberActivities, int maxTraceLength)
12+
{
13+
double supportSize = calculateSystemSupportSize(numberActivities,maxTraceLength );
14+
Map<List<String>, Double> tfl = tfLog.getTraceFreq();
15+
double sumFreq = 0.0;
16+
for (List<String> trace: tfl.keySet()) {
17+
double probEstimate = (1+tfl.get(trace))/(supportSize + logTotalEvents);
18+
if (probEstimate > alphaSig)
19+
sumFreq += tfModel.getFreq(trace);
20+
}
21+
return sumFreq/tfModel.getTraceTotal();
22+
}
23+
24+
public double calculateSystemSupportSize(int numberActivities, int maxTraceLength) {
25+
double result = 0;
26+
for (int i=1; i<maxTraceLength; i++) {
27+
result += Math.pow(numberActivities,i);
28+
}
29+
return result;
30+
}
31+
32+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package qut.pm.spm.conformance;
2+
3+
import org.apache.logging.log4j.LogManager;
4+
import org.apache.logging.log4j.Logger;
5+
import org.deckfour.xes.classification.XEventClasses;
6+
import org.deckfour.xes.classification.XEventClassifier;
7+
import org.deckfour.xes.info.XLogInfo;
8+
import org.deckfour.xes.model.XLog;
9+
import org.deckfour.xes.model.XTrace;
10+
import org.processmining.framework.plugin.PluginContext;
11+
12+
import qut.pm.spm.AcceptingStochasticNet;
13+
import qut.pm.spm.Measure;
14+
import qut.pm.spm.SPNQualityCalculator;
15+
import qut.pm.spm.TaskStats;
16+
import qut.pm.spm.TraceFreq;
17+
import qut.pm.spm.TraceFreqGenerator;
18+
import qut.pm.spm.playout.PlayoutGenerator;
19+
import qut.pm.spm.playout.StochasticPlayoutGenerator;
20+
21+
public class AlphaPrecisionUnrestrictedCalculator implements SPNQualityCalculator {
22+
23+
24+
private static final int PLAYOUT_LOG_SIZE = 1000;
25+
private static final int MAX_TRACE_LENGTH = 100;
26+
private static final double ALPHA_SIGNIFICANCE = 0.0;
27+
private static Logger LOGGER = LogManager.getLogger();
28+
29+
private TraceFreqGenerator traceFreqGen = new TraceFreqGenerator();
30+
private PlayoutGenerator playout
31+
= new StochasticPlayoutGenerator(MAX_TRACE_LENGTH,PLAYOUT_LOG_SIZE);
32+
private AlphaPrecisionCalculation alphaCalc = new AlphaPrecisionCalculation();
33+
34+
@Override
35+
public String getReadableId() {
36+
return "Alpha Precision Unrestricted alpha-sig " + ALPHA_SIGNIFICANCE;
37+
}
38+
39+
@Override
40+
public void calculate(PluginContext context, AcceptingStochasticNet net, XLog log,
41+
XEventClassifier classifier, TaskStats stats) throws Exception
42+
{
43+
LOGGER.info("Computing " + getReadableId() );
44+
LOGGER.debug("Initial marking {}",net.getInitialMarking());
45+
double result = calculateAlphaPrecision(net,log,ALPHA_SIGNIFICANCE,classifier);
46+
stats.setMeasure(Measure.ALPHA_PRECISION_UNRESTRICTED, result);
47+
}
48+
49+
private double calculateAlphaPrecision(AcceptingStochasticNet net, XLog log,
50+
double alphaSig, XEventClassifier classifier)
51+
{
52+
int size = calculateLogLanguageSize(log,classifier);
53+
int maxTraceLength = calculateMaxTraceLength(log);
54+
TraceFreq tfLog = traceFreqGen.calculateForLog(log,classifier);
55+
TraceFreq tfModel = playout.buildPlayoutTraceFreq(net);
56+
return alphaCalc.calculatePrecision(tfLog, tfModel,
57+
log.getInfo(classifier).getNumberOfEvents(), alphaSig, size, maxTraceLength);
58+
}
59+
60+
61+
62+
private int calculateMaxTraceLength(XLog log) {
63+
int max = 0;
64+
for( XTrace trace: log) {
65+
if (trace.size() > max)
66+
max = trace.size();
67+
}
68+
return max;
69+
}
70+
71+
72+
private int calculateLogLanguageSize(XLog log, XEventClassifier classifier) {
73+
XLogInfo logInfo = log.getInfo(classifier);
74+
XEventClasses ec = logInfo.getEventClasses();
75+
return ec.size();
76+
}
77+
78+
79+
80+
}

0 commit comments

Comments
 (0)