Presentation is loading. Please wait.

Presentation is loading. Please wait.

Efficient implementations of Alignment-based algorithms

Similar presentations


Presentation on theme: "Efficient implementations of Alignment-based algorithms"— Presentation transcript:

1 Efficient implementations of Alignment-based algorithms
Efficient storage! Efficient CPU use! Implementation effort? Efficient implementations of Alignment-based algorithms B.F. van Dongen

2 Introduction: Alignments
Alignments are used for conformance checking Alignments are computed over a trace and a model: A trace is a (partial) order of activities A model is a labeled Petri net or a labeled Process Tree, labeled with activities An alignment explains exactly where deviations occur: A synchronous move mean that an activity is in the log and a corresponding transition was enabled in the model A log move means that no corresponding activity is found in the model A model move means that no corresponding activity appeared in the log

3 Introduction: Computing Alignments
To compute alignments, an A-star algorithm is used A-star is an efficient algorithm for finding the shortest path in a graph: Initialize PriorityQueue q While (head(q) is not target t) VisitedNode n = head(q) For each edge in the graph from node(n) to m If m was considered before, or is in the queue with lower cost, continue If m is in the queue with higher cost, update and reposition it If m is new, compute an estimate for the remaining distance to t V = new VisitedNode(m) set n a predecessor for v add v to the priority queue Return head(q)

4 Important realizations
This allows for caching of the estimate The remaining distance from node m to the target node t should be independent of the path from the initial node to m The estimate for the remaining distance has to be an underestimate, preferably a very good underestimate Tradeoff between CPU time and quality of the estimate can be made

5 Essential elements Node
Necessary to store efficiently Node combination of a marking, parikh vector and estimate Visited Node The node, the predecessor and the distance Edge move on model move on log move synchronously Considered nodes lookup node visits add node visits Priority queue insert node visits update node visits inspect/remove head Estimation function tradeoff between CPU and quality Necessary to store efficiently Necessary to compute fast Necessary to store efficiently and have fast operations Necessary to store efficiently and have fast operations Necessary to cache efficiently and compute fast

6 Java: pitfalls Java collections framework:
Easy to use, nicely typed code, but: Very generic and often too generic Hopelessly inefficient w.r.t. memory PriorityQueue<T> : Add, Poll: O(log(n)) Remove, Contains: O(n) Peek: O(1) Map<K,V> is unsuitable for multisets (marking, parikh vector) as each value is an Integer, requiring about 384 bits instead of just 32

7 Necessary to store efficiently
A Closer Look: Nodes A node is a combination of a multiset of places, a multiset of activities and an estimate Assume a total order on the places and a total order on the activities Assume at most 256 tokens in a place, and at most 256 occurrences of the same activity in one trace Assume the estimate to be an integer (4 bytes) A Node becomes an array of bytes: p1 p2 p3 p4 p5 p6 a b c Estimate 1 3 21 5 2 4

8 A Closer Look: Lists of nodes
Necessary to store efficiently A Closer Look: Lists of nodes List<byte[]> should not be used here! A list of nodes is an array of bytes, where the first byte of a node n is stored at index n*13 (in our example) Add: O(1) Remove: O(n) Lookup: O(n) Update: O(n) p1 p2 p3 p4 p5 p6 a b c Estimate 1 3 21 5 2 4 11 -2 10 9

9 A Closer Look: Hashsets of nodes
Necessary to store efficiently A Closer Look: Hashsets of nodes A hashset of nodes requires an array of bytes for the nodes, a strong hash operation and an equality function In the storage, we add a hashmap, from node to nodeID Add: O(1+k/n) Remove: Lookup: O(≈1) p1 p2 p3 p4 p5 p6 a b c Estimate 1 3 21 5 2 4 11 -2 10 9 13 39 26

10 Implementations: Collections vs. Own
CPU Efficient Memory Efficient The Node objects are stored in a List<Node> The index is stored in a TObjectIntMap<NodeID> Uses much more memory The Node objects are stored in a byte array using compressed storage Requires compressor and a decompressor

11 Memory use storing 224 objects of 28 bytes (448 MB)
CPU Efficient Memory Efficient Wasted space: 64 MB Free space: MB (74,898 objects)

12 Compressing byte arrays
Necessary to store efficiently Compressing byte arrays Markings and parikh vectors consist mainly of 0’s, 1’s and 2’s We represent 0,1, and 2 by two bits and >2 by 2 bits and a byte for the actual value Compression-factor: 1.75, but compression takes time! p1 p2 p3 p4 a b c 1 2 21 4 byte 1 byte 2 byte 3 byte 4 (0,1,2,3) 21 (1,2,4,0) 4

13 A Closer Look: VisitedNode
Necessary to store efficiently A Closer Look: VisitedNode A node visit is simply an object containing: A pointer to the corresponding node (the NodeID) An object-pointer to the predecessor A bitmask for the executed events in the trace (necessary to allow for partially ordered traces) and optionally (The moves made to reach the state) (The estimate of the remaining cost)

14 Necessary to compute fast
A Closer Look: Edges An edge is essentially: the execution of a transition in a model moving forward by one activity in the trace both simultaneously For Petri nets: consider each transition given the marking and check all connected places for a transition O(T*P) For Process trees: consider all nodes and check if they are enabled in the marking O(N)

15 A Closer Look: Considered Nodes
Necessary to store efficiently and have fast operations A Closer Look: Considered Nodes HashSet<Node> : Add: O(1) Contains: O(1+k/n) However, the java collections hashset would require pointers to the actual nodes, which do not exist... Node visits are identified by the ID of the node, i.e. we use a TLongHashSet from the GNU Trove libraries Storing longs instead of pointers requires the same space, but Node visits can be removed from memory

16 A Closer Look: PriorityQueue
Necessary to store efficiently and have fast operations A Closer Look: PriorityQueue PriorityQueue<T> : Add, Poll: O(log(n)) Remove, Contains: O(n) Peek: O(1) Update: O(n+log(n)) In A-star the priority queue is constantly searched. The object searched for is uniquely identified by a long (the node ID) Elements of the queue need constant updating If a node visit is queued and the node is reached again with lower cost

17 A Closer Look: PriorityQueue
Necessary to store efficiently and have fast operations A Closer Look: PriorityQueue Solution: - A balanced binary heap for the queue - A TLongIntMap mapping nodeID’s to locations in the heap FastLookupPriorityQueue : Add, Poll, Remove : O(log(n)+k/n) Contains: O(1) Peek: O(1) Update: O(log(n)) Two implementations: Breadth-first: second order sorting on least cost so far Depth-first second order sorting on most cost so far

18 Complexity w/ Java Collections
O(log(n)) Initialize PriorityQueue q While (head(q) is not target t) VisitedNode n = head(q) For each edge in the graph from node(n) to m If m was considered before, continue If m is in the queue with lower cost, continue If m is in the queue with higher cost, update and reposition it If m is new, compute an estimate for the remaining distance to t V = new VisitedNode(m) set n a predecessor for v add v to the priority queue Return head(q) O(1) O(n) O(n+log(n)) Expensive? O(log(n))

19 Complexity w/ Own Collections
O(log(n)+k/n) Initialize PriorityQueue q While (head(q) is not target t) VisitedNode n = head(q) For each edge in the graph from node(n) to m If m was considered before, continue If m is in the queue with lower cost, continue If m is in the queue with higher cost, update and reposition it If m is new, compute an estimate for the remaining distance to t V = new VisitedNode(m) set n a predecessor for v add v to the priority queue Return head(q) O(1) O(1) O(log(n)) Expensive? O(log(n)+k/n)

20 A Closer Look: Estimation
Necessary to compute fast A Closer Look: Estimation Stupid estimation: 0 (fast!) Smarter estimation: size of parikh vector (fast!) Both for process trees and Petri nets, we can use an estimation function based on Linear Programming Form is the same: Minimize c.x Where A.x = r c and A are the same for all traces r depends on the current node

21 A Closer Look: Estimation
Necessary to compute fast A Closer Look: Estimation If we store the vector x, we can derive one solution from the other, since x represents the various moves. if xi>=1 and we execute move i, then c.x–c.1i is optimal and the x–1i is a new optimal solution for the problem Minimize c.x Where A.x = r-A.1i Otherwise, if we execute move i, then c.x–c.1i is a lower bound for c.x So, we get the problem: Minimize c.x Where A.x = r c.x >= v

22 A Closer Look: Estimation
Necessary to compute fast A Closer Look: Estimation Technically, the vector x is an integer vector, since you cannot do half a modelmove or half a synchronous move Hence, our LP (polynomial complexity) is an ILP (exponential complexity) Fortunately, the LP provides a lower bound on the ILP (and we need an underestimate!) For Petri nets: we use ILP as it’s more precise For Process Trees: we use LP since we need the speed

23 Implementations: Estimator versions
Petri nets Process Trees Dijkstra (estimator 0) Naive (estimator parikh) ILP (estimator using ILP) Naive (estimator parikh) LP (estimator using LP) Hybrid ILP (estimator using ILP for at most 1 second before reverting to LP)

24 Some performance results
179 random process trees of 16.7 nodes on average 120 short traces over 6 activities

25 Conclusion Fast, memory efficient implementations can be essential Memory efficiency comes at a cost of code readability There’s negligible performance overhead for memory efficiency A-star efficiency required good estimation functions, but Good estimation functions can be expensive There’s always a tradeoff between CPU time, memory consumption and implementation effort

26 Strong Hash functions There are many ways to hash an array of bytes
Collision test on 33,554,432 semi-random arrays. Expecting 130,731 collisions. Algorithm Time Collisions JAVA31 12.08 130,721 Bernstein 12.23 130,428 MurMur3 12.46 131,519 Jenkings 23.06 131,031 FNV1 14.10 130,695 FNV1a 14.01 130,606 OAT 16.97 130,546 Incremental 9.41 238,423


Download ppt "Efficient implementations of Alignment-based algorithms"

Similar presentations


Ads by Google