├── .gitignore
├── DOCS.md
├── Dockerfile
├── LICENSE
├── README.THIRD_PARTY.md
├── README.md
├── browser_packaging.py
├── dist
└── pm4js_latest.js
├── examples
├── html
│ ├── celonis_dfg_showing.html
│ ├── celonis_embedded_dfg_alignments.html
│ ├── celonis_embedded_mvp_showing.html
│ ├── celonis_embedded_process_tree.html
│ ├── celonis_mvp_showing.html
│ ├── csv_exporting.html
│ ├── csv_importing.html
│ ├── petri_importing.html
│ ├── petri_playground.html
│ ├── process_tree_conversion.html
│ ├── process_tree_importing.html
│ ├── process_tree_playground.html
│ ├── token_based_replay.html
│ ├── xes_exporting.html
│ ├── xes_general_statistics.html
│ ├── xes_general_statistics_with_upload.html
│ └── xes_importing.html
├── input_data
│ ├── 10_orders.xes
│ ├── 11_tickets.xes
│ ├── a32f0n00.bpmn
│ ├── example_log.csv
│ ├── example_log.jsonocel
│ ├── example_log.xmlocel
│ ├── newocel.csv
│ ├── newocel.jsonocel
│ ├── ocel20_example.jsonocel
│ ├── ocel20_example.sqlite
│ ├── ocel20_example.xmlocel
│ ├── receipt.bpmn
│ ├── receipt.csv
│ ├── receipt.pnml
│ ├── receipt.ptml
│ ├── receipt.xes
│ ├── receipt_imf_prom.pnml
│ ├── reviewing.xes
│ ├── roadtraffic100traces.xes
│ ├── running-example.bpmn
│ ├── running-example.csv
│ ├── running-example.dfg
│ ├── running-example.pnml
│ ├── running-example.ptml
│ ├── running-example.xes
│ ├── running-example_unchanged.csv
│ └── sepsis.bpmn
└── node
│ ├── csv_exporting.js
│ ├── csv_importing.js
│ ├── interval_tree.js
│ ├── petri_importing.js
│ ├── petri_playground.js
│ ├── process_tree_conversion.js
│ ├── process_tree_importing.js
│ ├── process_tree_playground.js
│ ├── token_based_replay.js
│ ├── xes_exporting.js
│ ├── xes_general_statistics.js
│ └── xes_importing.js
├── init.js
├── interface
├── components
│ ├── algo
│ │ ├── log_end_activities_filter.js
│ │ ├── log_log_merging.js
│ │ └── log_sampling.js
│ └── visualization
│ │ ├── dfg_graphviz.js
│ │ ├── generalization_tbr.js
│ │ ├── plotly_activities.js
│ │ ├── pnml_graphviz.js
│ │ ├── ptml_graphviz.js
│ │ ├── simplicity_apn.js
│ │ └── tbr_tokens.js
├── js
│ ├── algorithm.js
│ ├── exporting.js
│ ├── importing.js
│ ├── main.js
│ ├── plotly-2.1.0.min.js
│ ├── visualization.js
│ ├── viz.js
│ └── wizard.js
├── pm4js.css
└── pm4js.html
├── package-lock.json
├── package.json
├── pm4js
├── algo
│ ├── conformance
│ │ ├── alignments
│ │ │ ├── dfg
│ │ │ │ └── algorithm.js
│ │ │ ├── heapq.js
│ │ │ └── petri_net
│ │ │ │ └── algorithm.js
│ │ ├── log_skeleton
│ │ │ └── algorithm.js
│ │ ├── temporal_profile
│ │ │ └── algorithm.js
│ │ └── tokenreplay
│ │ │ └── algorithm.js
│ ├── discovery
│ │ ├── dfg
│ │ │ └── algorithm.js
│ │ ├── flower
│ │ │ └── algorithm.js
│ │ ├── inductive
│ │ │ └── algorithm.js
│ │ ├── log_skeleton
│ │ │ └── algorithm.js
│ │ └── temporal_profile
│ │ │ └── algorithm.js
│ ├── evaluation
│ │ └── petri_net
│ │ │ ├── fitness
│ │ │ ├── alignments.js
│ │ │ └── tbr.js
│ │ │ ├── generalization
│ │ │ └── tbr_result.js
│ │ │ ├── precision
│ │ │ └── tbr.js
│ │ │ └── simplicity
│ │ │ └── arc_degree.js
│ ├── filtering
│ │ ├── log
│ │ │ ├── general.js
│ │ │ └── ltl.js
│ │ └── ocel
│ │ │ └── general.js
│ ├── organizational
│ │ └── network_analysis
│ │ │ └── algorithm.js
│ ├── simulation
│ │ └── playout
│ │ │ ├── dfg
│ │ │ ├── algorithm.js
│ │ │ └── performance.js
│ │ │ └── petri_net
│ │ │ └── algorithm.js
│ └── transformation
│ │ ├── case_features.js
│ │ ├── interval_tree.js
│ │ ├── log_links.js
│ │ ├── ocel_conn_comp.js
│ │ ├── ocel_event_features.js
│ │ ├── ocel_graphs.js
│ │ ├── ocel_interval_tree.js
│ │ ├── ocel_links.js
│ │ ├── ocel_object_features.js
│ │ ├── ocel_propagation.js
│ │ └── ocel_segments.js
├── objects
│ ├── bpmn
│ │ ├── bpmn_graph.js
│ │ ├── exporter
│ │ │ └── bpmn_exporter.js
│ │ ├── importer
│ │ │ └── bpmn_importer.js
│ │ └── layouting
│ │ │ └── dagre.js
│ ├── conversion
│ │ ├── bpmn
│ │ │ └── to_petri_net.js
│ │ ├── process_tree
│ │ │ └── to_petri_net.js
│ │ └── wf_net
│ │ │ └── to_bpmn.js
│ ├── dfg
│ │ ├── exporter
│ │ │ └── exporter.js
│ │ ├── frequency
│ │ │ └── obj.js
│ │ ├── importer
│ │ │ └── importer.js
│ │ ├── performance
│ │ │ └── obj.js
│ │ └── util
│ │ │ ├── maximize.js
│ │ │ └── sliders.js
│ ├── log
│ │ ├── exporter
│ │ │ ├── csv
│ │ │ │ └── exporter.js
│ │ │ └── xes
│ │ │ │ └── exporter.js
│ │ ├── importer
│ │ │ ├── csv
│ │ │ │ └── importer.js
│ │ │ └── xes
│ │ │ │ └── importer.js
│ │ ├── log.js
│ │ └── util
│ │ │ ├── log_to_stream.js
│ │ │ └── prefixes.js
│ ├── ocel
│ │ ├── exporter
│ │ │ ├── csv
│ │ │ │ └── exporter.js
│ │ │ ├── json2
│ │ │ │ └── exporter.js
│ │ │ ├── jsonocel
│ │ │ │ └── exporter.js
│ │ │ ├── sqlite
│ │ │ │ └── exporter.js
│ │ │ ├── xml2
│ │ │ │ └── exporter.js
│ │ │ └── xmlocel
│ │ │ │ └── exporter.js
│ │ ├── importer
│ │ │ ├── csv
│ │ │ │ └── importer.js
│ │ │ ├── json2
│ │ │ │ └── importer.js
│ │ │ ├── jsonocel
│ │ │ │ └── importer.js
│ │ │ ├── sqlite
│ │ │ │ └── importer.js
│ │ │ ├── xml2
│ │ │ │ └── importer.js
│ │ │ └── xmlocel
│ │ │ │ └── importer.js
│ │ └── util
│ │ │ ├── flattening.js
│ │ │ ├── ocel20_fixer.js
│ │ │ ├── parent_children.js
│ │ │ └── to_celonis.js
│ ├── petri_net
│ │ ├── exporter
│ │ │ └── exporter.js
│ │ ├── importer
│ │ │ └── importer.js
│ │ ├── petri_net.js
│ │ └── util
│ │ │ ├── reachable_visible_transitions.js
│ │ │ └── reduction.js
│ ├── process_tree
│ │ ├── exporter
│ │ │ └── exporter.js
│ │ ├── importer
│ │ │ └── importer.js
│ │ └── process_tree.js
│ └── skeleton
│ │ └── log_skeleton.js
├── pm4js.js
├── statistics
│ ├── log
│ │ └── general.js
│ └── ocel
│ │ └── general.js
├── utils
│ ├── browser
│ │ ├── download.js
│ │ └── jquery.min.js
│ ├── celonis
│ │ ├── celonis.js
│ │ ├── celonis_1d_wrapper.js
│ │ ├── celonis_nd_wrapper.js
│ │ ├── celonis_proxy.php
│ │ ├── celonis_proxy.py
│ │ ├── celonis_proxy_post.php
│ │ └── celonis_proxy_put.php
│ ├── generic
│ │ ├── business_hours.js
│ │ ├── dates.js
│ │ ├── humanize-duration.js
│ │ ├── intervaltree.js
│ │ ├── numeric.js
│ │ └── stats-utils.js
│ ├── ml
│ │ ├── dt_utils.js
│ │ └── rules.js
│ ├── random_variables
│ │ ├── exp_mod_gaussian.js
│ │ ├── expon.js
│ │ ├── fitter.js
│ │ ├── gamma.js
│ │ ├── lognormal.js
│ │ ├── normal.js
│ │ └── uniform.js
│ └── stream
│ │ └── stream_attr_wrapper.js
└── visualization
│ ├── dfg
│ ├── alignments.js
│ ├── frequency.js
│ └── performance.js
│ ├── network_analysis
│ └── graphviz.js
│ ├── ocel
│ ├── ocel_obj_relations.js
│ └── ocel_obj_relations2.js
│ ├── petri_net
│ ├── frequency_graphviz.js
│ └── vanilla_graphviz.js
│ └── process_tree
│ └── vanilla_graphviz.js
├── simple_example.html
└── tests
├── bpmn.test.js
├── csv_importing.test.js
├── dfg.test.js
├── feature_extraction.test.js
├── inductive_miner.test.js
├── log_filtering.test.js
├── log_skeleton.test.js
├── log_statistics.test.js
├── petri_evaluation.test.js
├── petri_replay.test.js
├── random_variables.test.js
├── visualization.test.js
└── xes_importing.test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | playground.js
3 | prova*.js
4 |
5 | *temp_output*
6 | # Logs
7 | logs
8 | *.log
9 | npm-debug.log*
10 | yarn-debug.log*
11 | yarn-error.log*
12 | lerna-debug.log*
13 |
14 | # Diagnostic reports (https://nodejs.org/api/report.html)
15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
16 |
17 | # Runtime data
18 | pids
19 | *.pid
20 | *.seed
21 | *.pid.lock
22 |
23 | # Directory for instrumented libs generated by jscoverage/JSCover
24 | lib-cov
25 |
26 | # Coverage directory used by tools like istanbul
27 | coverage
28 | *.lcov
29 |
30 | # nyc test coverage
31 | .nyc_output
32 |
33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
34 | .grunt
35 |
36 | # Bower dependency directory (https://bower.io/)
37 | bower_components
38 |
39 | # node-waf configuration
40 | .lock-wscript
41 |
42 | # Compiled binary addons (https://nodejs.org/api/addons.html)
43 | build/Release
44 |
45 | # Dependency directories
46 | node_modules/
47 | jspm_packages/
48 |
49 | # TypeScript v1 declaration files
50 | typings/
51 |
52 | # TypeScript cache
53 | *.tsbuildinfo
54 |
55 | # Optional npm cache directory
56 | .npm
57 |
58 | # Optional eslint cache
59 | .eslintcache
60 |
61 | # Microbundle cache
62 | .rpt2_cache/
63 | .rts2_cache_cjs/
64 | .rts2_cache_es/
65 | .rts2_cache_umd/
66 |
67 | # Optional REPL history
68 | .node_repl_history
69 |
70 | # Output of 'npm pack'
71 | *.tgz
72 |
73 | # Yarn Integrity file
74 | .yarn-integrity
75 |
76 | # dotenv environment variables file
77 | .env
78 | .env.test
79 |
80 | # parcel-bundler cache (https://parceljs.org/)
81 | .cache
82 |
83 | # Next.js build output
84 | .next
85 |
86 | # Nuxt.js build / generate output
87 | .nuxt
88 |
89 | # Gatsby files
90 | .cache/
91 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
92 | # https://nextjs.org/blog/next-9-1#public-directory-support
93 | # public
94 |
95 | # vuepress build output
96 | .vuepress/dist
97 |
98 | # Serverless directories
99 | .serverless/
100 |
101 | # FuseBox cache
102 | .fusebox/
103 |
104 | # DynamoDB Local files
105 | .dynamodb/
106 |
107 | # TernJS port file
108 | .tern-port
109 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:16
2 |
3 | WORKDIR /app
4 |
5 | COPY . .
6 |
7 | RUN npm install
8 |
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2021 Alessandro Berti
2 |
3 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4 |
5 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
6 |
7 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8 |
9 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10 |
11 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------------
/README.THIRD_PARTY.md:
--------------------------------------------------------------------------------
1 | # PM4JS Third Party Dependencies
2 |
3 | PM4JS depends on third party libraries to implement some functionality. This document describes which libraries
4 | PM4JS depends upon. This is a best effort attempt to describe the library's dependencies, it is subject to change as libraries are added/removed.
5 |
6 | Common dependencies (Javascript library and Node package)
7 |
8 | | Name | URL | License | Version |
9 | | --------------------------- | ------------------------------------------------------------ | --------------------------- | ------------------- |
10 | | [heapq.js](pm4js/algo/conformance/heapq.js) | https://stackoverflow.com/questions/42919469/efficient-way-to-implement-priority-queue-in-javascript | [CC BY-SA 2.5](https://creativecommons.org/licenses/by-sa/2.5/) | |
11 | | [HumanizeDuration.js](pm4js/utils/generic/humanize-duration.js) | https://github.com/EvanHahn/HumanizeDuration.js | [The Unlicense](https://github.com/EvanHahn/HumanizeDuration.js/blob/main/LICENSE.txt) | 3.27.0 |
12 | | [intervaltree.js](pm4js/utils/generic/intervaltree.js) | https://github.com/pineapplemachine/interval-tree-type-js | [ZLIB/LIBPNG](https://opensource.org/licenses/Zlib) | 1.0.1 |
13 | | [numeric.js](pm4js/utils/generic/numeric.js) | https://github.com/sloisel/numeric | [MIT](https://opensource.org/licenses/MIT) | 1.2.6 |
14 |
15 | Other dependencies of the Node package:
16 |
17 | | Name | URL | License | Version |
18 | | --------------------------- | ------------------------------------------------------------ | --------------------------- | ------------------- |
19 | | jsdom | https://www.npmjs.com/package/jsdom | [MIT](https://opensource.org/licenses/MIT) | 16.6.0 |
20 | | xmldom | https://www.npmjs.com/package/xmldom | [MIT](https://opensource.org/licenses/MIT) | 0.6.0 |
21 | | xmlserializer | https://www.npmjs.com/package/xmlserializer | [MIT](https://opensource.org/licenses/MIT) | 0.6.1 |
22 | | jest | https://www.npmjs.com/package/jest | [MIT](https://opensource.org/licenses/MIT) | 27.1.1 |
23 |
--------------------------------------------------------------------------------
/browser_packaging.py:
--------------------------------------------------------------------------------
1 | F = open("init.js", "r")
2 | content = F.readlines()
3 | F.close()
4 | F = open("dist/pm4js_latest.js", "w")
5 | for line in content:
6 | if "require" in line:
7 | package = line.split("require('")[1].split("'")[0]
8 | package_content = open(package, "r", errors='ignore').read()
9 | F.write(package_content)
10 | F.write("\n\n")
11 | F.close()
12 |
--------------------------------------------------------------------------------
/dist/pm4js_latest.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pm4js/pm4js-core/44d8afea4e737edb5712d0a4d7905868d43ff3fd/dist/pm4js_latest.js
--------------------------------------------------------------------------------
/examples/html/celonis_dfg_showing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
22 |
23 |
--------------------------------------------------------------------------------
/examples/html/celonis_embedded_dfg_alignments.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
23 |
24 |
--------------------------------------------------------------------------------
/examples/html/celonis_embedded_mvp_showing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
20 |
21 |
--------------------------------------------------------------------------------
/examples/html/celonis_embedded_process_tree.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/html/celonis_mvp_showing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
22 |
23 |
--------------------------------------------------------------------------------
/examples/html/csv_exporting.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/examples/html/csv_importing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
28 |
29 |
--------------------------------------------------------------------------------
/examples/html/petri_importing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/examples/html/petri_playground.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
29 |
30 |
--------------------------------------------------------------------------------
/examples/html/process_tree_conversion.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
20 |
21 |
--------------------------------------------------------------------------------
/examples/html/process_tree_importing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
19 |
20 |
--------------------------------------------------------------------------------
/examples/html/process_tree_playground.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
22 |
23 |
--------------------------------------------------------------------------------
/examples/html/token_based_replay.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Consumed tokens:
8 | Produced tokens:
9 | Missing tokens:
10 | Remaining tokens:
11 | Fit traces:
12 | Log fitness:
13 |
29 |
30 |
--------------------------------------------------------------------------------
/examples/html/xes_exporting.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/examples/html/xes_importing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
28 |
29 |
--------------------------------------------------------------------------------
/examples/input_data/example_log.csv:
--------------------------------------------------------------------------------
1 | ocel:eid,ocel:timestamp,ocel:activity,ocel:type:element,ocel:type:order,ocel:type:delivery
2 | e1,1980-01-01,Create Order,"['i4', 'i1', 'i3', 'i2']",['o1'],
3 | e2,1980-01-02,Confirm Order,,['o1'],
4 | e3,1980-01-03,Item out of Stock,['i3'],,
5 | e4,1980-01-04,Create Delivery,"['i2', 'i1']",,['d1']
6 | e5,1980-01-05,Item back in Stock,['i3'],,
7 | e6,1980-01-08,Delivery Failed,,,['d1']
8 | e7,1980-01-09,Retry Delivery,,,['d1']
9 | e8,1980-01-10,Delivery Successful,,,['d1']
10 | e9,1980-01-11,Invoice Sent,,['o1'],
11 | e10,1980-01-12,Pay Order,,['o1'],
12 | e11,1981-01-01,Create Order,"['i6', 'i5']",['o2'],
13 | e12,1981-01-02,Remove Item,['i5'],,
14 | e13,1981-01-03,Cancel Order,,['o2'],
15 | e14,1981-01-04,Create Order,"['i8', 'i7']",['o3'],
16 | e15,1981-01-05,Add Item to Order,['i9'],['o3'],
17 | e16,1981-01-06,Create Delivery,"['i3', 'i4', 'i7']",,['d2']
18 | e17,1981-01-07,Delivery Successful,,,['d2']
19 | e18,1981-01-08,Create Delivery,"['i8', 'i9']",,['d3']
20 | e19,1981-01-09,Delivery Successful,,,['d3']
21 | e20,1981-01-10,Invoice Sent,,['o3'],
22 | e21,1981-01-11,Payment Reminder,,['o3'],
23 | e22,1981-01-11,Payment Reminder,,['o3'],
24 | e23,1981-01-12,Send for Credit Collection,,['o3'],
25 |
--------------------------------------------------------------------------------
/examples/input_data/newocel.csv:
--------------------------------------------------------------------------------
1 | ocel:eid,ocel:activity,ocel:timestamp,ocel:type:order,ocel:type:item,ocel:type:line,ocel:type:goodsissue,ocel:type:delivery,ocel:type:invoice,ocel:type:payment
2 | e1,Create Purchase Order,1970-01-01 01:00:00,"['o1']","['i1','i2','i3']","[]","[]","[]","[]","[]"
3 | e2,Produce Item,1970-01-01 02:00:00,"['o1']","['i1']","['L1']","[]","[]","[]","[]"
4 | e3,Item Issue,1970-01-01 03:00:00,"['o1']","['i1']","['L1']","['gi1']","[]","[]","[]"
5 | e4,Replace Item,1970-01-01 04:00:00,"['o1']","['i1']","['L1']","['gi1']","[]","[]","[]"
6 | e5,Produce Item,1970-01-01 05:00:00,"['o1']","['i2']","['L1']","[]","[]","[]","[]"
7 | e6,Produce Item,1970-01-01 06:00:00,"['o1']","['i3']","[]","[]","[]","[]","[]"
8 | e7,Collect Items,1970-01-01 07:00:00,"['o1']","['i1','i2','i3']","[]","[]","[]","[]","[]"
9 | e8,Start Delivery,1970-01-01 08:00:00,"['o1']","[]","[]","[]","['d1']","[]","[]"
10 | e9,Send Invoice,1970-01-01 09:00:00,"['o1']","[]","[]","[]","[]","['r1']","[]"
11 | e10,Delivery Successful,1970-01-01 10:00:00,"[]","[]","[]","[]","['d1']","[]","[]"
12 | e11,Revert Invoice,1970-01-01 11:00:00,"[]","[]","[]","[]","[]","['r1','r2']","[]"
13 | e12,Send Invoice,1970-01-01 11:00:00,"[]","[]","[]","[]","[]","['r2']","[]"
14 | e13,Create Purchase Order,1970-01-01 12:00:00,"['o2']","['i4','i5']","[]","[]","[]","[]","[]"
15 | e14,Produce Item,1970-01-01 13:00:00,"['o2']","['i4']","['L1']","[]","[]","[]","[]"
16 | e15,Produce Item,1970-01-01 14:00:00,"['o2']","['i5']","['L1']","[]","[]","[]","[]"
17 | e16,Collect Items,1970-01-01 15:00:00,"['o2']","['i4','i5']","[]","[]","[]","[]","[]"
18 | e17,Start Delivery,1970-01-01 16:00:00,"['o2']","[]","[]","[]","['d2']","[]","[]"
19 | e18,Delivery Successful,1970-01-01 17:00:00,"[]","[]","[]","[]","['d2']","[]","[]"
20 | e19,Send Invoice,1970-01-01 18:00:00,"['o2']","[]","[]","[]","[]","['r3']","[]"
21 | e20,Payment,1970-01-01 19:00:00,"[]","[]","[]","[]","[]","['r3']","['pay1']"
22 |
--------------------------------------------------------------------------------
/examples/input_data/newocel.jsonocel:
--------------------------------------------------------------------------------
1 | {"ocel:events":{"e1":{"ocel:omap":["o1","i1","i2","i3"],"ocel:vmap":{},"ocel:activity":"Create Purchase Order","ocel:timestamp":"1970-01-01T00:00:00.000Z"},"e2":{"ocel:omap":["o1","i1","L1"],"ocel:vmap":{},"ocel:activity":"Produce Item","ocel:timestamp":"1970-01-01T01:00:00.000Z"},"e3":{"ocel:omap":["o1","i1","L1","gi1"],"ocel:vmap":{},"ocel:activity":"Item Issue","ocel:timestamp":"1970-01-01T02:00:00.000Z"},"e4":{"ocel:omap":["o1","i1","L1","gi1"],"ocel:vmap":{},"ocel:activity":"Replace Item","ocel:timestamp":"1970-01-01T03:00:00.000Z"},"e5":{"ocel:omap":["o1","i2","L1"],"ocel:vmap":{},"ocel:activity":"Produce Item","ocel:timestamp":"1970-01-01T04:00:00.000Z"},"e6":{"ocel:omap":["o1","i3"],"ocel:vmap":{},"ocel:activity":"Produce Item","ocel:timestamp":"1970-01-01T05:00:00.000Z"},"e7":{"ocel:omap":["o1","i1","i2","i3"],"ocel:vmap":{},"ocel:activity":"Collect Items","ocel:timestamp":"1970-01-01T06:00:00.000Z"},"e8":{"ocel:omap":["o1","d1"],"ocel:vmap":{},"ocel:activity":"Start Delivery","ocel:timestamp":"1970-01-01T07:00:00.000Z"},"e9":{"ocel:omap":["o1","r1"],"ocel:vmap":{},"ocel:activity":"Send Invoice","ocel:timestamp":"1970-01-01T08:00:00.000Z"},"e10":{"ocel:omap":["d1"],"ocel:vmap":{},"ocel:activity":"Delivery Successful","ocel:timestamp":"1970-01-01T09:00:00.000Z"},"e11":{"ocel:omap":["r1","r2"],"ocel:vmap":{},"ocel:activity":"Revert Invoice","ocel:timestamp":"1970-01-01T10:00:00.000Z"},"e12":{"ocel:omap":["r2"],"ocel:vmap":{},"ocel:activity":"Send Invoice","ocel:timestamp":"1970-01-01T10:00:00.000Z"},"e13":{"ocel:omap":["o2","i4","i5"],"ocel:vmap":{},"ocel:activity":"Create Purchase Order","ocel:timestamp":"1970-01-01T11:00:00.000Z"},"e14":{"ocel:omap":["o2","i4","L1"],"ocel:vmap":{},"ocel:activity":"Produce Item","ocel:timestamp":"1970-01-01T12:00:00.000Z"},"e15":{"ocel:omap":["o2","i5","L1"],"ocel:vmap":{},"ocel:activity":"Produce Item","ocel:timestamp":"1970-01-01T13:00:00.000Z"},"e16":{"ocel:omap":["o2","i4","i5"],"ocel:vmap":{},"ocel:activity":"Collect Items","ocel:timestamp":"1970-01-01T14:00:00.000Z"},"e17":{"ocel:omap":["o2","d2"],"ocel:vmap":{},"ocel:activity":"Start Delivery","ocel:timestamp":"1970-01-01T15:00:00.000Z"},"e18":{"ocel:omap":["d2"],"ocel:vmap":{},"ocel:activity":"Delivery Successful","ocel:timestamp":"1970-01-01T16:00:00.000Z"},"e19":{"ocel:omap":["o2","r3"],"ocel:vmap":{},"ocel:activity":"Send Invoice","ocel:timestamp":"1970-01-01T17:00:00.000Z"},"e20":{"ocel:omap":["r3","pay1"],"ocel:vmap":{},"ocel:activity":"Payment","ocel:timestamp":"1970-01-01T18:00:00.000Z"}},"ocel:objects":{"o1":{"ocel:type":"ocel:type:order","ocel:ovmap":{}},"i1":{"ocel:type":"ocel:type:item","ocel:ovmap":{}},"i2":{"ocel:type":"ocel:type:item","ocel:ovmap":{}},"i3":{"ocel:type":"ocel:type:item","ocel:ovmap":{}},"L1":{"ocel:type":"ocel:type:line","ocel:ovmap":{}},"gi1":{"ocel:type":"ocel:type:goodsissue","ocel:ovmap":{}},"d1":{"ocel:type":"ocel:type:delivery","ocel:ovmap":{}},"r1":{"ocel:type":"ocel:type:invoice","ocel:ovmap":{}},"r2":{"ocel:type":"ocel:type:invoice","ocel:ovmap":{}},"o2":{"ocel:type":"ocel:type:order","ocel:ovmap":{}},"i4":{"ocel:type":"ocel:type:item","ocel:ovmap":{}},"i5":{"ocel:type":"ocel:type:item","ocel:ovmap":{}},"d2":{"ocel:type":"ocel:type:delivery","ocel:ovmap":{}},"r3":{"ocel:type":"ocel:type:invoice","ocel:ovmap":{}},"pay1":{"ocel:type":"ocel:type:payment","ocel:ovmap":{}}},"ocel:global-event":{"ocel:activity":"__INVALID__"},"ocel:global-object":{"ocel:activity":"__INVALID__"},"ocel:global-log":{"ocel:version":"1.0","ocel:ordering":"timestamp","ocel:attribute-names":[],"ocel:object-types":["ocel:type:order","ocel:type:item","ocel:type:line","ocel:type:goodsissue","ocel:type:delivery","ocel:type:invoice","ocel:type:payment"]}}
--------------------------------------------------------------------------------
/examples/input_data/ocel20_example.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pm4js/pm4js-core/44d8afea4e737edb5712d0a4d7905868d43ff3fd/examples/input_data/ocel20_example.sqlite
--------------------------------------------------------------------------------
/examples/input_data/running-example.dfg:
--------------------------------------------------------------------------------
1 | 8
2 | reinitiate request
3 | examine casually
4 | check ticket
5 | register request
6 | reject request
7 | pay compensation
8 | decide
9 | examine thoroughly
10 | 1
11 | 3x6
12 | 2
13 | 5x3
14 | 4x3
15 | 3>1x3
16 | 1>2x4
17 | 2>6x6
18 | 6>0x3
19 | 0>7x1
20 | 7>2x2
21 | 6>5x3
22 | 3>2x2
23 | 2>1x2
24 | 1>6x2
25 | 3>7x1
26 | 6>4x3
27 | 0>2x1
28 | 0>1x1
29 | 2>7x1
30 | 7>6x1
31 |
--------------------------------------------------------------------------------
/examples/input_data/running-example.ptml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/examples/input_data/running-example_unchanged.csv:
--------------------------------------------------------------------------------
1 | case_id;activity;timestamp;costs;resource
2 | 3;register request;2010-12-30 14:32:00+01:00;50;Pete
3 | 3;examine casually;2010-12-30 15:06:00+01:00;400;Mike
4 | 3;check ticket;2010-12-30 16:34:00+01:00;100;Ellen
5 | 3;decide;2011-01-06 09:18:00+01:00;200;Sara
6 | 3;reinitiate request;2011-01-06 12:18:00+01:00;200;Sara
7 | 3;examine thoroughly;2011-01-06 13:06:00+01:00;400;Sean
8 | 3;check ticket;2011-01-08 11:43:00+01:00;100;Pete
9 | 3;decide;2011-01-09 09:55:00+01:00;200;Sara
10 | 3;pay compensation;2011-01-15 10:45:00+01:00;200;Ellen
11 | 2;register request;2010-12-30 11:32:00+01:00;50;Mike
12 | 2;check ticket;2010-12-30 12:12:00+01:00;100;Mike
13 | 2;examine casually;2010-12-30 14:16:00+01:00;400;Sean
14 | 2;decide;2011-01-05 11:22:00+01:00;200;Sara
15 | 2;pay compensation;2011-01-08 12:05:00+01:00;200;Ellen
16 | 1;register request;2010-12-30 11:02:00+01:00;50;Pete
17 | 1;examine thoroughly;2010-12-31 10:06:00+01:00;400;Sue
18 | 1;check ticket;2011-01-05 15:12:00+01:00;100;Mike
19 | 1;decide;2011-01-06 11:18:00+01:00;200;Sara
20 | 1;reject request;2011-01-07 14:24:00+01:00;200;Pete
21 | 6;register request;2011-01-06 15:02:00+01:00;50;Mike
22 | 6;examine casually;2011-01-06 16:06:00+01:00;400;Ellen
23 | 6;check ticket;2011-01-07 16:22:00+01:00;100;Mike
24 | 6;decide;2011-01-07 16:52:00+01:00;200;Sara
25 | 6;pay compensation;2011-01-16 11:47:00+01:00;200;Mike
26 | 5;register request;2011-01-06 09:02:00+01:00;50;Ellen
27 | 5;examine casually;2011-01-07 10:16:00+01:00;400;Mike
28 | 5;check ticket;2011-01-08 11:22:00+01:00;100;Pete
29 | 5;decide;2011-01-10 13:28:00+01:00;200;Sara
30 | 5;reinitiate request;2011-01-11 16:18:00+01:00;200;Sara
31 | 5;check ticket;2011-01-14 14:33:00+01:00;100;Ellen
32 | 5;examine casually;2011-01-16 15:50:00+01:00;400;Mike
33 | 5;decide;2011-01-19 11:18:00+01:00;200;Sara
34 | 5;reinitiate request;2011-01-20 12:48:00+01:00;200;Sara
35 | 5;examine casually;2011-01-21 09:06:00+01:00;400;Sue
36 | 5;check ticket;2011-01-21 11:34:00+01:00;100;Pete
37 | 5;decide;2011-01-23 13:12:00+01:00;200;Sara
38 | 5;reject request;2011-01-24 14:56:00+01:00;200;Mike
39 | 4;register request;2011-01-06 15:02:00+01:00;50;Pete
40 | 4;check ticket;2011-01-07 12:06:00+01:00;100;Mike
41 | 4;examine thoroughly;2011-01-08 14:43:00+01:00;400;Sean
42 | 4;decide;2011-01-09 12:02:00+01:00;200;Sara
43 | 4;reject request;2011-01-12 15:44:00+01:00;200;Ellen
44 |
--------------------------------------------------------------------------------
/examples/node/csv_exporting.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | require('../../init.js');
3 | fs.readFile('../input_data/running-example.xes', {encoding: 'utf-8'}, (err, data) => {
4 | var eventLog = XesImporter.apply(data);
5 | let txtStri = CsvExporter.apply(eventLog);
6 | fs.writeFile('temp_output_csv_exporting.csv', txtStri, function (err) {
7 |
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/examples/node/csv_importing.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | require('../../init.js');
3 | fs.readFile('../input_data/running-example.csv', {encoding: 'utf-8'}, (err, data) => {
4 | var eventLog = CsvImporter.apply(data, sep=',', quotechar='"');
5 | for (let trace of eventLog.traces) {
6 | console.log("case "+trace.attributes["concept:name"].value);
7 | for (let eve of trace.events) {
8 | console.log("\tevent (activity: "+eve.attributes["concept:name"].value+"; timestamp: "+eve.attributes["time:timestamp"].value);
9 | }
10 | }
11 | });
12 |
--------------------------------------------------------------------------------
/examples/node/interval_tree.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | require('../../init.js');
3 |
4 | fs.readFile('../input_data/receipt.xes', {encoding: 'utf-8'}, (err, data) => {
5 | let log = XesImporter.apply(data);
6 | let tree = IntervalTreeBuilder.apply(log);
7 | // query the interval tree at regular points and see how many 'intervals'
8 | // intersect in the given point.
9 | let i = 0;
10 | let summ = 0;
11 | while (i < 50) {
12 | let thisPoint = tree.mintime + i/50 * (tree.maxtime - tree.mintime);
13 | let contained = tree.queryPoint(thisPoint);
14 | let count = 0;
15 | for (let p of contained) {
16 | count++;
17 | summ++;
18 | }
19 | console.log(thisPoint+" "+count);
20 | i++;
21 | }
22 | });
--------------------------------------------------------------------------------
/examples/node/petri_importing.js:
--------------------------------------------------------------------------------
1 | require('../../init.js');
2 | var fs = require('fs');
3 |
4 | fs.readFile('../input_data/running-example.pnml', {encoding: 'utf-8'}, (err, data) => {
5 | let acceptingPetriNet = PnmlImporter.apply(data);
6 | console.log(acceptingPetriNet);
7 | let gv = PetriNetVanillaVisualizer.apply(acceptingPetriNet);
8 | console.log(gv);
9 | });
10 |
--------------------------------------------------------------------------------
/examples/node/petri_playground.js:
--------------------------------------------------------------------------------
1 | require('../../init.js');
2 |
3 | let petriNet = new PetriNet();
4 | let source = petriNet.addPlace('source');
5 | let sink = petriNet.addPlace('sink');
6 | let A = petriNet.addTransition('A', 'A');
7 | let B = petriNet.addTransition('B', 'B');
8 | let C = petriNet.addTransition('C', 'C');
9 | petriNet.addArcFromTo(source, A);
10 | petriNet.addArcFromTo(A, sink);
11 | petriNet.addArcFromTo(sink, C);
12 | let im = new Marking(petriNet);
13 | im.setTokens(source, 1);
14 | let fm = new Marking(petriNet);
15 | fm.setTokens(sink, 1);
16 | let acceptingPetriNet = new AcceptingPetriNet(petriNet, im, fm);
17 | let gv = PetriNetVanillaVisualizer.apply(acceptingPetriNet);
18 | console.log(gv);
19 |
--------------------------------------------------------------------------------
/examples/node/process_tree_conversion.js:
--------------------------------------------------------------------------------
1 | require('../../init.js');
2 | var fs = require('fs');
3 |
4 | fs.readFile('../input_data/running-example.ptml', {encoding: 'utf-8'}, (err, data) => {
5 | let processTree = PtmlImporter.apply(data);
6 | console.log(processTree);
7 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
8 | let gv = PetriNetVanillaVisualizer.apply(acceptingPetriNet);
9 | console.log(gv);
10 | });
11 |
--------------------------------------------------------------------------------
/examples/node/process_tree_importing.js:
--------------------------------------------------------------------------------
1 | require('../../init.js');
2 | var fs = require('fs');
3 |
4 | fs.readFile('../input_data/running-example.ptml', {encoding: 'utf-8'}, (err, data) => {
5 | let processTree = PtmlImporter.apply(data);
6 | console.log(processTree);
7 | let gv = ProcessTreeVanillaVisualizer.apply(processTree);
8 | console.log(gv);
9 | });
10 |
--------------------------------------------------------------------------------
/examples/node/process_tree_playground.js:
--------------------------------------------------------------------------------
1 | require('../../init.js');
2 |
3 | let root = new ProcessTree(null, ProcessTreeOperator.SEQUENCE, null);
4 | let child1 = new ProcessTree(root, ProcessTreeOperator.EXCLUSIVE, null);
5 | let child2 = new ProcessTree(root, null, 'label of the visibile leaf');
6 | let child3 = new ProcessTree(root, null, null);
7 | root.children.push(child1);
8 | root.children.push(child2);
9 | root.children.push(child3);
10 | let gv = ProcessTreeVanillaVisualizer.apply(root);
11 | console.log(gv);
12 |
--------------------------------------------------------------------------------
/examples/node/token_based_replay.js:
--------------------------------------------------------------------------------
1 | require('../../init.js');
2 | var fs = require('fs');
3 |
4 | fs.readFile('../input_data/receipt.xes', {encoding: 'utf-8'}, (err, data) => {
5 | let eventLog = XesImporter.apply(data);
6 | fs.readFile('../input_data/receipt_imf_prom.pnml', {encoding: 'utf-8'}, (err2, data2) => {
7 | let acceptingPetriNet = PnmlImporter.apply(data2);
8 | let replayResult = TokenBasedReplay.apply(eventLog, acceptingPetriNet);
9 | console.log("consumed tokens: "+replayResult["totalConsumed"]);
10 | console.log("produced tokens: "+replayResult["totalProduced"]);
11 | console.log("missing tokens: "+replayResult["totalMissing"]);
12 | console.log("remaining tokens: "+replayResult["totalRemaining"]);
13 | console.log("fit traces: "+replayResult["fitTraces"]+"/"+replayResult["totalTraces"]);
14 | console.log("log fitness: "+replayResult["logFitness"]);
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/examples/node/xes_exporting.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | require('../../init.js');
3 |
4 | fs.readFile('../input_data/running-example.xes', {encoding: 'utf-8'}, (err, data) => {
5 | var eventLog = XesImporter.apply(data);
6 | let xmlStri = XesExporter.apply(eventLog);
7 | fs.writeFile('temp_output_xes_exporting.xes', xmlStri, function (err) {
8 |
9 | });
10 | });
--------------------------------------------------------------------------------
/examples/node/xes_general_statistics.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | require('../../init.js');
3 |
4 | fs.readFile('../input_data/receipt.xes', {encoding: 'utf-8'}, (err, data) => {
5 | var eventLog = XesImporter.apply(data);
6 | console.log("start activities = ");
7 | console.log(GeneralLogStatistics.getStartActivities(eventLog));
8 | console.log("end activites = ");
9 | console.log(GeneralLogStatistics.getEndActivities(eventLog));
10 | console.log("activities = ");
11 | console.log(GeneralLogStatistics.getAttributeValues(eventLog, "concept:name"));
12 | console.log("variants = ");
13 | console.log(GeneralLogStatistics.getVariants(eventLog));
14 | console.log("attributes at the trace level = ");
15 | console.log(GeneralLogStatistics.getCaseAttributesList(eventLog));
16 | console.log("attributes at the event level = ");
17 | console.log(GeneralLogStatistics.getEventAttributesList(eventLog));
18 | });
--------------------------------------------------------------------------------
/examples/node/xes_importing.js:
--------------------------------------------------------------------------------
1 | var fs = require('fs');
2 | require('../../init.js');
3 |
4 | fs.readFile('../input_data/running-example.xes', {encoding: 'utf-8'}, (err, data) => {
5 | var eventLog = XesImporter.apply(data);
6 | for (let trace of eventLog.traces) {
7 | console.log("case "+trace.attributes["concept:name"].value);
8 | for (let eve of trace.events) {
9 | console.log("\tevent (activity: "+eve.attributes["concept:name"].value+"; timestamp: "+eve.attributes["time:timestamp"].value);
10 | }
11 | }
12 | });
--------------------------------------------------------------------------------
/interface/components/algo/log_end_activities_filter.js:
--------------------------------------------------------------------------------
1 | class LogEndActivitiesFilter {
2 | static apply(log) {
3 | let endActivities = GeneralLogStatistics.getEndActivities(log, "concept:name");
4 | document.getElementById("wizardTitle").innerHTML = "Filter End Activities";
5 | let container = document.getElementById("wizardContent");
6 | container.innerHTML = "";
7 | let explanation = document.createElement("div");
8 | explanation.innerHTML = "Please select the allowed end activities";
9 | container.appendChild(explanation);
10 | let selection = document.createElement("select");
11 | selection.setAttribute("id", "endActivitiesFilterSelect");
12 | selection.setAttribute("multiple", "");
13 | container.appendChild(selection);
14 | for (let act in endActivities) {
15 | let count = endActivities[act];
16 | let opt = document.createElement("option");
17 | opt.value = act;
18 | opt.innerHTML = act+" ("+count+")";
19 | opt.selected = true;
20 | selection.appendChild(opt);
21 | }
22 | wizardCallback = function() { LogEndActivitiesFilter.applyFilterAfterSelection(log); };
23 | $('#wizardPopup').show();
24 | }
25 |
26 | static applyFilterAfterSelection(log) {
27 | let selectedEndActivities = [];
28 | for (let opt of document.getElementById("endActivitiesFilterSelect").childNodes) {
29 | console.log(opt);
30 | if (opt.selected) {
31 | selectedEndActivities.push(opt.value);
32 | }
33 | }
34 | let newLog = new EventLog();
35 | for (let trace of log.traces) {
36 | if (trace.events.length > 0) {
37 | let evs = trace.events;
38 | if (selectedEndActivities.includes(evs[evs.length-1].attributes["concept:name"].value)) {
39 | newLog.traces.push(trace);
40 | }
41 | }
42 | }
43 | Pm4JS.registerObject(newLog, "Filtered Log ("+newLog.traces.length+" cases)");
44 | return newLog;
45 | }
46 | }
47 |
48 | Pm4JS.registerAlgorithm("LogEndActivitiesFilter", "apply", ["EventLog"], "EventLog", "Filter by End Activities", "Alessandro Berti");
49 |
--------------------------------------------------------------------------------
/interface/components/algo/log_log_merging.js:
--------------------------------------------------------------------------------
1 | class LogMerging {
2 | static apply(log1, log2) {
3 | let newEventLog = new EventLog();
4 | for (let trace of log1.traces) {
5 | newEventLog.traces.push(trace);
6 | }
7 | for (let trace of log2.traces) {
8 | newEventLog.traces.push(trace);
9 | }
10 | Pm4JS.registerObject(newEventLog, "Merged Log ("+newEventLog.traces.length+" cases)");
11 | return newEventLog;
12 | }
13 | }
14 |
15 | Pm4JS.registerAlgorithm("LogMerging", "apply", ["EventLog", "EventLog"], "EventLog", "Merge Event Logs", "Alessandro Berti");
16 |
--------------------------------------------------------------------------------
/interface/components/algo/log_sampling.js:
--------------------------------------------------------------------------------
1 | class LogSamplingWithInputBox {
2 | static getRandomSubarray(arr, size) {
3 | var shuffled = arr.slice(0), i = arr.length, temp, index;
4 | while (i--) {
5 | index = Math.floor((i + 1) * Math.random());
6 | temp = shuffled[index];
7 | shuffled[index] = shuffled[i];
8 | shuffled[i] = temp;
9 | }
10 | return shuffled.slice(0, size);
11 | }
12 |
13 | static apply(log) {
14 | let numTraces = parseInt(prompt("Insert the number of cases to sample"));
15 | let caseIdxs = [];
16 | for (let traceIdx in log.traces) {
17 | caseIdxs.push(traceIdx);
18 | }
19 | let caseIdxsSubarray = LogSamplingWithInputBox.getRandomSubarray(caseIdxs, numTraces);
20 | let newLog = new EventLog();
21 | for (let idx of caseIdxsSubarray) {
22 | newLog.traces.push(log.traces[idx]);
23 | }
24 | Pm4JS.registerObject(newLog, "Sampled Log ("+numTraces+" cases)");
25 | return newLog;
26 | }
27 | }
28 |
29 | Pm4JS.registerAlgorithm("LogSamplingWithInputBox", "apply", ["EventLog"], "EventLog", "Sample Event Log (JS prompt)", "Alessandro Berti");
30 |
--------------------------------------------------------------------------------
/interface/components/visualization/dfg_graphviz.js:
--------------------------------------------------------------------------------
1 | class DfgGraphvizComponent {
2 | static showFrequencyDfg(frequencyDfg, component) {
3 | let gv = FrequencyDfgGraphvizVisualizer.apply(frequencyDfg);
4 | let svgXml = Viz(gv, { format: "svg"});
5 | document.getElementById(component).innerHTML = svgXml;
6 | }
7 |
8 | static showPerformanceDfg(performanceDfg, component) {
9 | let gv = PerformanceDfgGraphvizVisualizer.apply(performanceDfg);
10 | let svgXml = Viz(gv, { format: "svg"});
11 | document.getElementById(component).innerHTML = svgXml;
12 | }
13 | }
14 |
15 | Pm4JS.registerVisualizer("DfgGraphvizComponent", "showFrequencyDfg", "FrequencyDfg", "Show Frequency DFG (Graphviz)", "Alessandro Berti");
16 | Pm4JS.registerVisualizer("DfgGraphvizComponent", "showPerformanceDfg", "PerformanceDfg", "Show Performance DFG (Graphviz)", "Alessandro Berti");
17 |
--------------------------------------------------------------------------------
/interface/components/visualization/generalization_tbr.js:
--------------------------------------------------------------------------------
1 | class GeneralizationTbrVisualization {
2 | static apply(generalizationResult, component0) {
3 | let component = document.getElementById(component0);
4 | let generalizationSpan = document.createElement("span");
5 | generalizationSpan.innerHTML = "Generalization value: ";
6 | let generalizationValue = document.createElement("span");
7 | generalizationValue.innerHTML = generalizationResult.value;
8 | component.appendChild(generalizationSpan);
9 | component.appendChild(generalizationValue);
10 | }
11 | }
12 |
13 | Pm4JS.registerVisualizer("GeneralizationTbrVisualization", "apply", "GeneralizationTbrResults", "Show the Generalization", "Alessandro Berti");
14 |
--------------------------------------------------------------------------------
/interface/components/visualization/plotly_activities.js:
--------------------------------------------------------------------------------
1 | class PlotlyActivities {
2 | static plotBarChar(event_log, component) {
3 | let xy = GeneralLogStatistics.getAttributeValues(event_log, "concept:name");
4 | let x = [];
5 | let y = [];
6 | for (let act in xy) {
7 | x.push(act);
8 | y.push(xy[act]);
9 | }
10 | var data = [{x: x, y: y, type: 'bar'}];
11 | var layout = {title: "Events per Activity", width: 1000, height: 400};
12 | Plotly.newPlot(component, data, layout);
13 | }
14 |
15 | static plotBarCharEndActivities(event_log, component) {
16 | let xy = GeneralLogStatistics.getEndActivities(event_log, "concept:name");
17 | let x = [];
18 | let y = [];
19 | for (let act in xy) {
20 | x.push(act);
21 | y.push(xy[act]);
22 | }
23 | var data = [{x: x, y: y, type: 'bar'}];
24 | var layout = {title: "End Activities (n. cases)", width: 1000, height: 400};
25 | Plotly.newPlot(component, data, layout);
26 | }
27 |
28 | static plotBarCharStartActivities(event_log, component) {
29 | let xy = GeneralLogStatistics.getStartActivities(event_log, "concept:name");
30 | let x = [];
31 | let y = [];
32 | for (let act in xy) {
33 | x.push(act);
34 | y.push(xy[act]);
35 | }
36 | var data = [{x: x, y: y, type: 'bar'}];
37 | var layout = {title: "Start Activities (n. cases)", width: 1000, height: 400};
38 | Plotly.newPlot(component, data, layout);
39 | }
40 | }
41 |
42 | Pm4JS.registerVisualizer("PlotlyActivities", "plotBarChar", "EventLog", "Plot Events per Activity", "Alessandro Berti");
43 | Pm4JS.registerVisualizer("PlotlyActivities", "plotBarCharEndActivities", "EventLog", "Plot End Activities", "Alessandro Berti");
44 | Pm4JS.registerVisualizer("PlotlyActivities", "plotBarCharStartActivities", "EventLog", "Plot Start Activities", "Alessandro Berti");
45 |
--------------------------------------------------------------------------------
/interface/components/visualization/pnml_graphviz.js:
--------------------------------------------------------------------------------
1 | class PnmlGraphvizVanilla {
2 | static applyVanilla(acceptingPetriNet, component) {
3 | let gv = PetriNetVanillaVisualizer.apply(acceptingPetriNet);
4 | let svgXml = Viz(gv, { format: "svg"});
5 | document.getElementById(component).innerHTML = svgXml;
6 | }
7 |
8 | static applyFrequency(tbrResults, component) {
9 | let gv = PetriNetFrequencyVisualizer.apply(tbrResults.acceptingPetriNet, tbrResults);
10 | let svgXml = Viz(gv, { format: "svg"});
11 | document.getElementById(component).innerHTML = svgXml;
12 | }
13 | }
14 |
15 | Pm4JS.registerVisualizer("PnmlGraphvizVanilla", "applyVanilla", "AcceptingPetriNet", "Show Accepting Petri Net (Graphviz; vanilla)", "Alessandro Berti");
16 | Pm4JS.registerVisualizer("PnmlGraphvizVanilla", "applyFrequency", "TokenBasedReplayResult", "Show Accepting Petri net decorated with TBR results", "Alessandro Berti");
17 |
--------------------------------------------------------------------------------
/interface/components/visualization/ptml_graphviz.js:
--------------------------------------------------------------------------------
1 | class PtmlGraphvizVanilla {
2 | static applyVanilla(processTree, component) {
3 | let gv = ProcessTreeVanillaVisualizer.apply(processTree);
4 | let svgXml = Viz(gv, { format: "svg"});
5 | document.getElementById(component).innerHTML = svgXml;
6 | }
7 | }
8 |
9 | Pm4JS.registerVisualizer("PtmlGraphvizVanilla", "applyVanilla", "ProcessTree", "Visualize Process Tree", "Alessandro Berti");
10 |
--------------------------------------------------------------------------------
/interface/components/visualization/simplicity_apn.js:
--------------------------------------------------------------------------------
1 | class SimplicityVisualization {
2 | static apply(simplicityResult, component0) {
3 | let component = document.getElementById(component0);
4 | let simplicitySpan = document.createElement("span");
5 | simplicitySpan.innerHTML = "Simplicity value: ";
6 | let simplicityValue = document.createElement("span");
7 | simplicityValue.innerHTML = simplicityResult.value;
8 | component.appendChild(simplicitySpan);
9 | component.appendChild(simplicityValue);
10 | }
11 | }
12 |
13 | Pm4JS.registerVisualizer("SimplicityVisualization", "apply", "SimplicityArcDegreeResults", "Show the Simplicity (Arc Degree)", "Alessandro Berti");
14 |
--------------------------------------------------------------------------------
/interface/components/visualization/tbr_tokens.js:
--------------------------------------------------------------------------------
1 | class TbrTokensVisualization {
2 | static apply(tbrResult, component0) {
3 | let component = document.getElementById(component0);
4 | let consumedTokensP = document.createElement("p");
5 | let consumedTokensD = document.createElement("span");
6 | consumedTokensD.innerHTML = "Consumed tokens: ";
7 | let consumedTokens = document.createElement("span");
8 | consumedTokens.innerHTML = tbrResult["totalConsumed"];
9 | consumedTokensP.appendChild(consumedTokensD);
10 | consumedTokensP.appendChild(consumedTokens);
11 | let producedTokensP = document.createElement("p");
12 | let producedTokensD = document.createElement("span");
13 | producedTokensD.innerHTML = "Produced tokens: ";
14 | let producedTokens = document.createElement("span");
15 | producedTokens.innerHTML = tbrResult["totalProduced"];
16 | producedTokensP.appendChild(producedTokensD);
17 | producedTokensP.appendChild(producedTokens);
18 | let missingTokensP = document.createElement("p");
19 | let missingTokensD = document.createElement("span");
20 | missingTokensD.innerHTML = "Missing tokens: ";
21 | let missingTokens = document.createElement("span");
22 | missingTokens.innerHTML = tbrResult["totalMissing"];
23 | missingTokensP.appendChild(missingTokensD);
24 | missingTokensP.appendChild(missingTokens);
25 | let remainingTokensP = document.createElement("p");
26 | let remainingTokensD = document.createElement("span");
27 | remainingTokensD.innerHTML = "Remaining tokens: ";
28 | let remainingTokens = document.createElement("span");
29 | remainingTokens.innerHTML = tbrResult["totalRemaining"];
30 | remainingTokensP.appendChild(remainingTokensD);
31 | remainingTokensP.appendChild(remainingTokens);
32 | let fitTracesP = document.createElement("p");
33 | let fitTracesD = document.createElement("span");
34 | fitTracesD.innerHTML = "Fit traces: ";
35 | let fitTraces = document.createElement("span");
36 | fitTraces.innerHTML = tbrResult["fitTraces"]+"/"+tbrResult["totalTraces"];
37 | fitTracesP.appendChild(fitTracesD);
38 | fitTracesP.appendChild(fitTraces);
39 | let logFitnessP = document.createElement("p");
40 | let logFitnessD = document.createElement("span");
41 | logFitnessD.innerHTML = "Log fitness: ";
42 | let logFitness = document.createElement("span");
43 | logFitness.innerHTML = tbrResult["logFitness"];
44 | logFitnessP.appendChild(logFitnessD);
45 | logFitnessP.appendChild(logFitness);
46 | component.appendChild(consumedTokensP);
47 | component.appendChild(producedTokensP);
48 | component.appendChild(missingTokensP);
49 | component.appendChild(remainingTokensP);
50 | component.appendChild(fitTracesP);
51 | component.appendChild(logFitnessP);
52 | }
53 | }
54 |
55 | Pm4JS.registerVisualizer("TbrTokensVisualization", "apply", "TokenBasedReplayResult", "Show Fitness and Tokens from the Replay", "Alessandro Berti");
56 |
--------------------------------------------------------------------------------
/interface/js/algorithm.js:
--------------------------------------------------------------------------------
1 | function applyAlgorithm() {
2 | selectedObjects = null;
3 | selectedObjects = [];
4 | for (let objIdx of levelsSelected["0"]) {
5 | selectedObjects.push(Pm4JS.objects[objIdx]);
6 | }
7 | let availableAlgorithms = getAvailableAlgorithms();
8 | operation = "algorithm";
9 | document.getElementById("level1Title").innerHTML = "Select the algorithm among the available ones
";
10 | populateLevel(document.getElementById("availableMethods"), 1, availableAlgorithms);
11 | $('#pm4jsAlgoPopup').show();
12 | }
13 |
14 | function getAvailableAlgorithms() {
15 | let selectedObjectsTypes = [];
16 | for (let obj of selectedObjects) {
17 | selectedObjectsTypes.push(obj["object"].constructor.name);
18 | }
19 | let availableAlgorithms = [];
20 | for (let algo of Pm4JS.algorithms) {
21 | if (algo["inputs"].toString() == selectedObjectsTypes.toString()) {
22 | availableAlgorithms.push(algo);
23 | }
24 | }
25 | return availableAlgorithms;
26 | }
27 |
28 | function level1ApplyAlgorithm() {
29 | try {
30 | let availableAlgorithms = getAvailableAlgorithms();
31 | let selectedMethod = availableAlgorithms[levelsSelected["1"][0]];
32 | let args = '...args';
33 | let intArgsStri = "";
34 | let i = 0;
35 | while (i < selectedObjects.length) {
36 | intArgsStri += "x["+i+"]";
37 | if (i < selectedObjects.length-1) {
38 | intArgsStri += ",";
39 | }
40 | i++;
41 | }
42 | let body = 'let [x]= args; return '+selectedMethod['className']+"."+selectedMethod['methodName']+'('+intArgsStri+')';
43 | myFunc = new Function(args, body);
44 | let selectedObjectsObjs = [];
45 | for (let obj of selectedObjects) {
46 | selectedObjectsObjs.push(obj["object"]);
47 | }
48 | myFunc(selectedObjectsObjs);
49 | }
50 | catch (err) {
51 | alert("Algorithm failed");
52 | console.log(err);
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/interface/js/exporting.js:
--------------------------------------------------------------------------------
1 | function startExportingObj(ev, obj) {
2 | objectToConsider = obj;
3 | operation = "exporting";
4 | document.getElementById("level1Title").innerHTML = "Select the exporter among the available ones
";
5 | populateLevel(document.getElementById("availableMethods"), 1, getAvailableExporters(obj));
6 | $('#pm4jsAlgoPopup').show();
7 | ev.preventDefault();
8 | }
9 |
10 | function getAvailableExporters(obj) {
11 | let ret = [];
12 | for (let method of Pm4JS.exporters) {
13 | if (method["exportedObjType"] == obj["object"].constructor.name) {
14 | ret.push(method);
15 | }
16 | }
17 | return ret;
18 | }
19 |
20 | function level1ApplyExporting() {
21 | try {
22 | let selectedObject = objectToConsider;
23 | let availableMethods = getAvailableExporters(selectedObject);
24 | let selectedMethod = availableMethods[levelsSelected["1"][0]];
25 | let args = '...args';
26 | let body = 'let [a]= args; return '+selectedMethod['className']+"."+selectedMethod['methodName']+'(a)';
27 | myFunc = new Function(args, body);
28 | let expString = myFunc(selectedObject["object"]);
29 | DownloadUtility.download(expString, "prova."+selectedMethod['extension'], selectedMethod['mimeType']);
30 | }
31 | catch (err) {
32 | alert("Export failed");
33 | console.log(err);
34 | }
35 | }
--------------------------------------------------------------------------------
/interface/js/importing.js:
--------------------------------------------------------------------------------
1 | function handleFileSelect(evt) {
2 | var files = evt.target.files; // FileList object
3 | // use the 1st file from the list
4 | f = files[0];
5 | var reader = new FileReader();
6 | reader.onload = function(e) {
7 | inputContent = e.target.result;
8 | extension = f.name.split('.').pop();
9 | operation = "importing";
10 | document.getElementById("level1Title").innerHTML = "Select the importer among the available ones
";
11 | populateLevel(document.getElementById("availableMethods"), 1, getAvailableImportersGivenExtension(extension));
12 | document.getElementById("uploadHidden").value = "";
13 | $('#pm4jsAlgoPopup').show();
14 | }
15 | reader.readAsText(f);
16 | }
17 |
18 | function getAvailableImportersGivenExtension(extension) {
19 | let ret = [];
20 | for (let method of Pm4JS.importers) {
21 | if (method["extensions"].includes(extension)) {
22 | ret.push(method);
23 | }
24 | }
25 | return ret;
26 | }
27 |
28 | function level1ApplyImporting() {
29 | let availableMethods = getAvailableImportersGivenExtension(extension);
30 | let selectedMethod = availableMethods[levelsSelected["1"][0]];
31 | try {
32 | let args = '...args';
33 | let body = 'let [a] = args;return '+selectedMethod['className']+"."+selectedMethod['methodName']+'(a)';
34 | myFunc = new Function(args, body);
35 | myFunc(inputContent);
36 | }
37 | catch (err) {
38 | alert("Import failed");
39 | console.log(err);
40 | }
41 | }
42 |
43 | document.getElementById('uploadHidden').addEventListener('change', handleFileSelect, false);
44 |
--------------------------------------------------------------------------------
/interface/js/visualization.js:
--------------------------------------------------------------------------------
1 | function startVisualizingObj(ev, obj) {
2 | objectToConsider = obj;
3 | operation = "visualising";
4 | document.getElementById("level1Title").innerHTML = "Select the visualizer among the available ones
";
5 | populateLevel(document.getElementById("availableMethods"), 1, getAvailableVisualizers(obj));
6 | $('#pm4jsAlgoPopup').show();
7 | ev.preventDefault();
8 | }
9 |
10 | function getAvailableVisualizers(obj) {
11 | let ret = [];
12 | for (let method of Pm4JS.visualizers) {
13 | if (method["input"] == obj["object"].constructor.name) {
14 | ret.push(method);
15 | }
16 | }
17 | return ret;
18 | }
19 |
20 | function level1ApplyVisualization() {
21 | try {
22 | let selectedObject = objectToConsider;
23 | let availableMethods = getAvailableVisualizers(selectedObject);
24 | let selectedMethod = availableMethods[levelsSelected["1"][0]];
25 | let args = '...args';
26 | let body = 'let [a,b]= args; return '+selectedMethod['className']+"."+selectedMethod['methodName']+'(a, b)';
27 | myFunc = new Function(args, body);
28 | document.getElementById("visualizationContent").innerHTML = "";
29 | myFunc(selectedObject["object"], "visualizationContent");
30 | $('#visualizationPopup').show();
31 | }
32 | catch (err) {
33 | alert("Visualization failed");
34 | console.log(err);
35 | }
36 | }
37 |
38 | $('#visualizationPopupClose').click(function(){
39 | $('#visualizationPopup').hide();
40 | });
41 |
--------------------------------------------------------------------------------
/interface/js/wizard.js:
--------------------------------------------------------------------------------
1 | function wizardApply() {
2 | wizardCallback();
3 | $('#wizardPopup').hide();
4 | }
5 |
6 | function wizardCancel() {
7 | $('#wizardPopup').hide();
8 | }
9 |
10 | $('#pm4jsWizardPopupClose').click(function(){
11 | $('#wizardPopup').hide();
12 | });
13 |
--------------------------------------------------------------------------------
/interface/pm4js.css:
--------------------------------------------------------------------------------
1 | #pm4jsAppHeader {
2 | width: 100%;
3 | height: 10%;
4 | background-color: black;
5 | color: white;
6 | }
7 |
8 | #importingButton {
9 | float: right;
10 | }
11 |
12 | #applyAlgorithmButton {
13 | float: right;
14 | }
15 |
16 | #pm4jsAppObjList {
17 | width: 100%;
18 | height: 85%;
19 | overflow-y: scroll;
20 | }
21 |
22 | #pm4jsAppFooter {
23 | width: 100%;
24 | height: 5%;
25 | background-color: darkgray;
26 | }
27 |
28 |
29 | .methodDiv {
30 | height: 100px;
31 | }
32 |
33 | .methodDiv_unselected {
34 | background-color: yellow;
35 | }
36 |
37 | .methodDiv_selected {
38 | background-color: green;
39 | }
40 |
41 | .hover_bkgr_fricc{
42 | background:rgba(0,0,0,.4);
43 | cursor:pointer;
44 | display:none;
45 | height:100%;
46 | position:fixed;
47 | text-align:center;
48 | top:0;
49 | width:100%;
50 | z-index:10000;
51 | }
52 | .hover_bkgr_fricc .helper{
53 | display:inline-block;
54 | height:100%;
55 | vertical-align:middle;
56 | }
57 | .hover_bkgr_fricc > div {
58 | background-color: #fff;
59 | box-shadow: 10px 10px 60px #555;
60 | display: inline-block;
61 | height: 70%;
62 | max-width: 1500px;
63 | min-height: 100px;
64 | vertical-align: middle;
65 | width: 80%;
66 | position: relative;
67 | border-radius: 8px;
68 | padding: 15px 5%;
69 | }
70 | .popupCloseButton {
71 | background-color: #fff;
72 | border: 3px solid #999;
73 | border-radius: 50px;
74 | cursor: pointer;
75 | display: inline-block;
76 | font-family: arial;
77 | font-weight: bold;
78 | position: absolute;
79 | top: -20px;
80 | right: -20px;
81 | font-size: 25px;
82 | line-height: 30px;
83 | width: 30px;
84 | height: 30px;
85 | text-align: center;
86 | }
87 | .popupCloseButton:hover {
88 | background-color: #ccc;
89 | }
90 | .trigger_popup_fricc {
91 | cursor: pointer;
92 | font-size: 20px;
93 | margin: 20px;
94 | display: inline-block;
95 | font-weight: bold;
96 | }
97 |
--------------------------------------------------------------------------------
/interface/pm4js.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
36 |
47 |
58 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "pm4js",
3 | "version": "0.0.39",
4 | "description": "Process Mining for Javascript",
5 | "main": "init.js",
6 | "directories": {
7 | "example": "examples"
8 | },
9 | "dependencies": {
10 | "retus": "^1.1.2",
11 | "xmldom": "^0.6.0",
12 | "xmlserializer": "^0.6.1",
13 | "sql.js": "^1.8.0"
14 | },
15 | "devDependencies": {
16 | "jest": "^27.1.1"
17 | },
18 | "scripts": {
19 | "test": "jest"
20 | },
21 | "repository": {
22 | "type": "git",
23 | "url": "git+https://github.com/pm4js/pm4js-core.git"
24 | },
25 | "keywords": [
26 | "process",
27 | "mining",
28 | "javascript",
29 | "pm4js"
30 | ],
31 | "author": "Alessandro Berti",
32 | "license": "BSD-3-Clause",
33 | "bugs": {
34 | "url": "https://github.com/pm4js/pm4js-core/issues"
35 | },
36 | "homepage": "https://github.com/pm4js/pm4js-core#readme"
37 | }
38 |
--------------------------------------------------------------------------------
/pm4js/algo/conformance/alignments/heapq.js:
--------------------------------------------------------------------------------
1 | const heapqTop = 0;
2 | const heapqParent = i => ((i + 1) >>> 1) - 1;
3 | const heapqLeft = i => (i << 1) + 1;
4 | const heapqRight = i => (i + 1) << 1;
5 |
6 | class PriorityQueue {
7 | constructor(comparator = (a, b) => a > b) {
8 | this._heap = [];
9 | this._comparator = comparator;
10 | }
11 | size() {
12 | return this._heap.length;
13 | }
14 | isEmpty() {
15 | return this.size() == 0;
16 | }
17 | peek() {
18 | return this._heap[heapqTop];
19 | }
20 | push(...values) {
21 | values.forEach(value => {
22 | this._heap.push(value);
23 | this._siftUp();
24 | });
25 | return this.size();
26 | }
27 | pop() {
28 | const poppedValue = this.peek();
29 | const bottom = this.size() - 1;
30 | if (bottom > heapqTop) {
31 | this._swap(heapqTop, bottom);
32 | }
33 | this._heap.pop();
34 | this._siftDown();
35 | return poppedValue;
36 | }
37 | replace(value) {
38 | const replacedValue = this.peek();
39 | this._heap[heapqTop] = value;
40 | this._siftDown();
41 | return replacedValue;
42 | }
43 | _greater(i, j) {
44 | return this._comparator(this._heap[i], this._heap[j]);
45 | }
46 | _swap(i, j) {
47 | [this._heap[i], this._heap[j]] = [this._heap[j], this._heap[i]];
48 | }
49 | _siftUp() {
50 | let node = this.size() - 1;
51 | while (node > heapqTop && this._greater(node, heapqParent(node))) {
52 | this._swap(node, heapqParent(node));
53 | node = heapqParent(node);
54 | }
55 | }
56 | _siftDown() {
57 | let node = heapqTop;
58 | while (
59 | (heapqLeft(node) < this.size() && this._greater(heapqLeft(node), node)) ||
60 | (heapqRight(node) < this.size() && this._greater(heapqRight(node), node))
61 | ) {
62 | let maxChild = (heapqRight(node) < this.size() && this._greater(heapqRight(node), heapqLeft(node))) ? heapqRight(node) : heapqLeft(node);
63 | this._swap(node, maxChild);
64 | node = maxChild;
65 | }
66 | }
67 | }
68 |
69 | try {
70 | module.exports = {PriorityQueue: PriorityQueue};
71 | global.PriorityQueue = PriorityQueue;
72 | }
73 | catch (err) {
74 | // not in Node
75 | //console.log(err);
76 | }
77 |
--------------------------------------------------------------------------------
/pm4js/algo/conformance/temporal_profile/algorithm.js:
--------------------------------------------------------------------------------
1 | class TemporalProfileConformanceResults {
2 | constructor(results) {
3 | this.results = results;
4 | }
5 | }
6 |
7 | class TemporalProfileConformance {
8 | static getAnalysis(eventLog, temporalProfile, activityKey="concept:name", timestampKey="time:timestamp", startTimestampKey="time:timestamp") {
9 | let confResults = [];
10 | for (let trace of eventLog.traces) {
11 | confResults.push([])
12 | let i = 0;
13 | while (i < trace.events.length - 1) {
14 | let act_i = trace.events[i].attributes[activityKey].value;
15 | let j = i + 1;
16 | while (j < trace.events.length) {
17 | let act_j = trace.events[j].attributes[activityKey].value;
18 | let ts1 = trace.events[i].attributes[timestampKey].value;
19 | let ts2 = trace.events[j].attributes[startTimestampKey].value;
20 | let diff = 0;
21 | if (BusinessHours.ENABLED) {
22 | diff = BusinessHours.apply(ts1, ts2);
23 | }
24 | else {
25 | ts1 = ts1.getTime();
26 | ts2 = ts2.getTime();
27 | diff = (ts2 - ts1)/1000;
28 | }
29 | let cou = [act_i, act_j];
30 | if (cou in temporalProfile.temporalProfile) {
31 | let avg = temporalProfile.temporalProfile[cou][0];
32 | let stdev = temporalProfile.temporalProfile[cou][1] + 0.0000001;
33 | let k = Math.abs(avg - diff) / stdev;
34 | confResults[confResults.length - 1].push([act_i, act_j, diff, k]);
35 | }
36 | j++;
37 | }
38 | i++;
39 | }
40 | }
41 | return confResults;
42 | }
43 |
44 | static apply(eventLog, temporalProfile, zeta, activityKey="concept:name", timestampKey="time:timestamp", startTimestampKey="time:timestamp", addObject=false) {
45 | let analysis = TemporalProfileConformance.getAnalysis(eventLog, temporalProfile, activityKey, timestampKey, startTimestampKey);
46 | let result = [];
47 | for (let trace of analysis) {
48 | result.push([]);
49 | for (let cou of trace) {
50 | if (cou[cou.length - 1] > zeta) {
51 | result[result.length - 1].push(cou);
52 | }
53 | }
54 | }
55 | return new TemporalProfileConformanceResults(result);
56 | }
57 | }
58 |
59 | try {
60 | module.exports = {TemporalProfileConformance: TemporalProfileConformance};
61 | global.TemporalProfileConformance = TemporalProfileConformance;
62 | }
63 | catch (err) {
64 | // not in Node.JS
65 | }
66 |
--------------------------------------------------------------------------------
/pm4js/algo/discovery/flower/algorithm.js:
--------------------------------------------------------------------------------
1 | class FlowerMiner {
2 | static apply(eventLog, activityKey="concept:name") {
3 | let activities = GeneralLogStatistics.getAttributeValues(eventLog, activityKey);
4 | let loop = new ProcessTree(null, ProcessTreeOperator.LOOP, null);
5 | let xor = new ProcessTree(loop, ProcessTreeOperator.EXCLUSIVE, null);
6 | let redo = new ProcessTree(loop, null, null);
7 | loop.children.push(xor);
8 | loop.children.push(redo);
9 | for (let act in activities) {
10 | let actNode = new ProcessTree(xor, null, act);
11 | xor.children.push(actNode);
12 | }
13 | Pm4JS.registerObject(loop, "Process Tree (Flower Miner)");
14 | return loop;
15 | }
16 | }
17 |
18 | try {
19 | module.exports = {FlowerMiner: FlowerMiner};
20 | global.FlowerMiner = FlowerMiner;
21 | }
22 | catch (err) {
23 | // not in Node
24 | //console.log(err);
25 | }
26 |
27 | Pm4JS.registerAlgorithm("FlowerMiner", "apply", ["EventLog"], "ProcessTree", "Mine a Process Tree using the Flower Miner", "Alessandro Berti");
28 |
--------------------------------------------------------------------------------
/pm4js/algo/discovery/temporal_profile/algorithm.js:
--------------------------------------------------------------------------------
1 | class TemporalProfile {
2 | constructor(temporalProfile) {
3 | this.temporalProfile = temporalProfile;
4 | }
5 | }
6 |
7 | class TemporalProfileDiscovery {
8 | static getAvg(vect) {
9 | if (vect.length > 0) {
10 | let sum = 0.0;
11 | for (let el of vect) {
12 | sum += el;
13 | }
14 | return sum / vect.length;
15 | }
16 | return 0;
17 | }
18 |
19 | static getStdev(vect, avg) {
20 | if (vect.length > 0) {
21 | let sum = 0.0;
22 | for (let el of vect) {
23 | sum += (el - avg)*(el - avg);
24 | }
25 | return Math.sqrt(sum / vect.length);
26 | }
27 | return 0;
28 | }
29 |
30 | static apply(eventLog, activityKey="concept:name", timestampKey="time:timestamp", startTimestampKey="time:timestamp", addObject=false) {
31 | let actCouplesTimes = {};
32 | let temporalProfile = {};
33 | for (let trace of eventLog.traces) {
34 | let i = 0;
35 | while (i < trace.events.length - 1) {
36 | let act_i = trace.events[i].attributes[activityKey].value;
37 | let j = i + 1;
38 | while (j < trace.events.length) {
39 | let act_j = trace.events[j].attributes[activityKey].value;
40 | let ts1 = trace.events[i].attributes[timestampKey].value;
41 | let ts2 = trace.events[j].attributes[startTimestampKey].value;
42 | let diff = 0;
43 | if (BusinessHours.ENABLED) {
44 | diff = BusinessHours.apply(ts1, ts2);
45 | }
46 | else {
47 | ts1 = ts1.getTime();
48 | ts2 = ts2.getTime();
49 | diff = (ts2 - ts1)/1000;
50 | }
51 | if (!([act_i, act_j] in actCouplesTimes)) {
52 | actCouplesTimes[[act_i, act_j]] = [];
53 | }
54 | actCouplesTimes[[act_i, act_j]].push(diff);
55 | j++;
56 | }
57 | i++;
58 | }
59 | }
60 | for (let cou in actCouplesTimes) {
61 | let vect = actCouplesTimes[cou]
62 | let avg = TemporalProfileDiscovery.getAvg(vect);
63 | let stdev = TemporalProfileDiscovery.getStdev(vect, avg);
64 | temporalProfile[cou] = [avg, stdev];
65 | }
66 | return new TemporalProfile(temporalProfile);
67 | }
68 | }
69 |
70 | try {
71 | module.exports = {TemporalProfileDiscovery: TemporalProfileDiscovery};
72 | global.TemporalProfileDiscovery = TemporalProfileDiscovery;
73 | }
74 | catch (err) {
75 | // not in Node.JS
76 | }
--------------------------------------------------------------------------------
/pm4js/algo/evaluation/petri_net/fitness/alignments.js:
--------------------------------------------------------------------------------
1 | class AlignmentsFitness {
2 | static apply(eventLog, acceptingPetriNet, activityKey="concept:name") {
3 | return PetriNetAlignments.apply(eventLog, acceptingPetriNet, activityKey);
4 | }
5 |
6 | static evaluate(alignResults) {
7 | return alignResults;
8 | }
9 | }
10 |
11 | try {
12 | module.exports = {AlignmentsFitness: AlignmentsFitness};
13 | global.AlignmentsFitness = AlignmentsFitness;
14 | }
15 | catch (err) {
16 | // not in Node
17 | //console.log(err);
18 | }
19 |
--------------------------------------------------------------------------------
/pm4js/algo/evaluation/petri_net/fitness/tbr.js:
--------------------------------------------------------------------------------
1 | class TbrFitness {
2 | static apply(eventLog, acceptingPetriNet, activityKey="concept:name") {
3 | return TokenBasedReplay.apply(eventLog, acceptingPetriNet, activityKey);
4 | }
5 |
6 | static evaluate(tbrResults) {
7 | return tbrResults;
8 | }
9 | }
10 |
11 | try {
12 | module.exports = {TbrFitness: TbrFitness};
13 | global.TbrFitness = TbrFitness;
14 | }
15 | catch (err) {
16 | // not in Node
17 | //console.log(err);
18 | }
19 |
--------------------------------------------------------------------------------
/pm4js/algo/evaluation/petri_net/generalization/tbr_result.js:
--------------------------------------------------------------------------------
1 | class GeneralizationTbrResults {
2 | constructor(value) {
3 | this.value = value;
4 | }
5 | }
6 |
7 | class GeneralizationTbr {
8 | static apply(log, acceptingPetriNet, activityKey="concept:name") {
9 | return GeneralizationTbr.evaluate(TokenBasedReplay.apply(log, acceptingPetriNet, activityKey));
10 | }
11 |
12 | static evaluate(tbrResults) {
13 | let invSqOccSum = 0.0
14 | for (let trans in tbrResults.transExecutions) {
15 | let thisTerm = 1.0 / Math.sqrt(Math.max(tbrResults.transExecutions[trans], 1));
16 | invSqOccSum += thisTerm;
17 | }
18 | let ret = new GeneralizationTbrResults(1.0 - invSqOccSum/(Object.keys(tbrResults.transExecutions).length));
19 | Pm4JS.registerObject(ret, "Generalization Results");
20 | return ret;
21 | }
22 | }
23 |
24 | try {
25 | module.exports = {GeneralizationTbr: GeneralizationTbr, GeneralizationTbrResults: GeneralizationTbrResults};
26 | global.GeneralizationTbr = GeneralizationTbr;
27 | global.GeneralizationTbrResults = GeneralizationTbrResults;
28 | }
29 | catch (err) {
30 | // not in Node
31 | //console.log(err);
32 | }
33 |
34 | Pm4JS.registerAlgorithm("GeneralizationTbr", "evaluate", ["TokenBasedReplayResult"], "GeneralizationTbrResults", "Calculate Generalization", "Alessandro Berti");
35 |
--------------------------------------------------------------------------------
/pm4js/algo/evaluation/petri_net/precision/tbr.js:
--------------------------------------------------------------------------------
1 | class ETConformanceResult {
2 | constructor(activatedTransitions, escapingEdges, precision) {
3 | this.activatedTransitions = activatedTransitions;
4 | this.escapingEdges = escapingEdges;
5 | this.precision = precision;
6 | }
7 | }
8 |
9 | class ETConformance {
10 | static apply(eventLog, acceptingPetriNet, activityKey="concept:name") {
11 | let prefixes = EventLogPrefixes.apply(eventLog, activityKey);
12 | let prefixesKeys = Object.keys(prefixes);
13 | let ret = TokenBasedReplay.applyListListAct(prefixesKeys, acceptingPetriNet, false, true);
14 | let i = 0;
15 | let sum_at = 0;
16 | let sum_ee = 0;
17 | let logTransitions = Object.keys(GeneralLogStatistics.getStartActivities(eventLog, activityKey));
18 | let activatedTransitions = PetriNetReachableVisibleTransitions.apply(acceptingPetriNet.net, acceptingPetriNet.im);
19 | let escapingEdges = [];
20 | for (let at of activatedTransitions) {
21 | if (!(logTransitions.includes(at))) {
22 | escapingEdges.push(at);
23 | }
24 | }
25 | sum_at += activatedTransitions.length * eventLog.traces.length;
26 | sum_ee += escapingEdges.length * eventLog.traces.length;
27 | i = 0;
28 | while (i < prefixesKeys.length) {
29 | if (ret[i].isFit) {
30 | let activatedTransitions = PetriNetReachableVisibleTransitions.apply(acceptingPetriNet.net, ret[i]);
31 | let prefix = prefixesKeys[i];
32 | let logTransitions = Object.keys(prefixes[prefix]);
33 | let sumPrefix = 0;
34 | for (let transition of logTransitions) {
35 | sumPrefix += prefixes[prefix][transition];
36 | }
37 | let escapingEdges = [];
38 | for (let at of activatedTransitions) {
39 | if (!(logTransitions.includes(at))) {
40 | escapingEdges.push(at);
41 | }
42 | }
43 | sum_at += activatedTransitions.length * sumPrefix;
44 | sum_ee += escapingEdges.length * sumPrefix;
45 | }
46 | i++;
47 | }
48 | let precision = 1.0;
49 | if (sum_at > 0) {
50 | precision = 1.0 - (sum_ee / (0.0 + sum_at));
51 | }
52 | let finalResult = new ETConformanceResult(sum_at, sum_ee, precision);
53 | Pm4JS.registerObject(finalResult, "ETConformance Precision Results");
54 | return finalResult;
55 | }
56 | }
57 |
58 | try {
59 | module.exports = {ETConformance: ETConformance, ETConformanceResult: ETConformanceResult};
60 | global.ETConformance = ETConformance;
61 | global.ETConformanceResult = ETConformanceResult;
62 | }
63 | catch (err) {
64 | // not in Node
65 | //console.log(err);
66 | }
67 |
68 | Pm4JS.registerAlgorithm("ETConformance", "apply", ["EventLog", "AcceptingPetriNet"], "ETConformanceResult", "Calculate Precision (ETConformance based on TBR)", "Alessandro Berti");
69 |
--------------------------------------------------------------------------------
/pm4js/algo/evaluation/petri_net/simplicity/arc_degree.js:
--------------------------------------------------------------------------------
1 | class SimplicityArcDegreeResults {
2 | constructor(value) {
3 | this.value = value;
4 | }
5 | }
6 |
7 | class SimplicityArcDegree {
8 | static apply(acceptingPetriNet, k=0) {
9 | return SimplicityArcDegree.evaluate(acceptingPetriNet, k);
10 | }
11 |
12 | static evaluate(acceptingPetriNet, k=0) {
13 | let summ = 0.0;
14 | let count = 0;
15 | for (let placeId in acceptingPetriNet.net.places) {
16 | let place = acceptingPetriNet.net.places[placeId];
17 | summ += Object.keys(place.inArcs).length;
18 | summ += Object.keys(place.outArcs).length;
19 | count += 2;
20 | }
21 | for (let transId in acceptingPetriNet.net.transitions) {
22 | let trans = acceptingPetriNet.net.transitions[transId];
23 | summ += Object.keys(trans.inArcs).length;
24 | summ += Object.keys(trans.outArcs).length;
25 | count += 2;
26 | }
27 | let meanDegree = 0;
28 | if (count > 0) {
29 | meanDegree = summ / count;
30 | }
31 | let simplicity = 1.0 / (1.0 + Math.max(meanDegree - k, 0));
32 | let ret = new SimplicityArcDegreeResults(simplicity);
33 | Pm4JS.registerObject(ret, "Simplicity Results");
34 | return ret;
35 | }
36 | }
37 |
38 | try {
39 | module.exports = {SimplicityArcDegree: SimplicityArcDegree, SimplicityArcDegreeResults: SimplicityArcDegreeResults};
40 | global.SimplicityArcDegree = SimplicityArcDegree;
41 | global.SimplicityArcDegreeResults = SimplicityArcDegreeResults;
42 | }
43 | catch (err) {
44 | // not in Node
45 | //console.log(err);
46 | }
47 |
48 | Pm4JS.registerAlgorithm("SimplicityArcDegree", "evaluate", ["AcceptingPetriNet"], "SimplicityArcDegreeResults", "Calculate Simplicity (Arc Degree)", "Alessandro Berti");
49 |
--------------------------------------------------------------------------------
/pm4js/algo/organizational/network_analysis/algorithm.js:
--------------------------------------------------------------------------------
1 | class NetworkAnalysisResult {
2 | constructor(nodes, multiEdges) {
3 | this.nodes = nodes;
4 | this.multiEdges = multiEdges;
5 | }
6 | }
7 |
8 | class NetworkAnalysis {
9 | static apply(links, sourceNodeAgg, targetNodeAgg, edgeAgg, source=true) {
10 | let nodes = {};
11 | let multiEdges = {};
12 | for (let el of links) {
13 | let se = el[0];
14 | let te = el[1];
15 | let sn = StreamAttrWrapper.accessAttribute(se, sourceNodeAgg);
16 | let tn = StreamAttrWrapper.accessAttribute(te, targetNodeAgg);
17 | let eg = null;
18 | if (source) {
19 | eg = StreamAttrWrapper.accessAttribute(se, edgeAgg);
20 | }
21 | else {
22 | eg = StreamAttrWrapper.accessAttribute(te, edgeAgg);
23 | }
24 |
25 | if (sn != null && tn != null && eg != null) {
26 | eg = [sn, tn, eg];
27 |
28 | let st = StreamAttrWrapper.defaultTimestamp(se).getTime();
29 | let tt = StreamAttrWrapper.defaultTimestamp(te).getTime();
30 | let diff = (tt - st) / 1000.0;
31 |
32 | if (!(sn in nodes)) {
33 | nodes[sn] = {"IN": 0, "OUT": 0};
34 | }
35 | if (!(tn in nodes)) {
36 | nodes[tn] = {"IN": 0, "OUT": 0};
37 | }
38 | if (!(eg in multiEdges)) {
39 | multiEdges[eg] = {"count": 0, "timeDiff": []};
40 | }
41 | nodes[sn]["OUT"] += 1;
42 | nodes[tn]["IN"] += 1;
43 | multiEdges[eg]["count"] += 1;
44 | multiEdges[eg]["timeDiff"].push(diff);
45 | }
46 | }
47 | return new NetworkAnalysisResult(nodes, multiEdges);
48 | }
49 | }
50 |
51 | try {
52 | module.exports = {NetworkAnalysis: NetworkAnalysis};
53 | global.NetworkAnalysis = NetworkAnalysis;
54 | }
55 | catch (err) {
56 | // not in node
57 | //console.log(err);
58 | }
59 |
--------------------------------------------------------------------------------
/pm4js/algo/simulation/playout/dfg/algorithm.js:
--------------------------------------------------------------------------------
1 | class DfgPlayout {
2 | static apply(freqDfg, numDesideredTraces=1000, activityKey="concept:name", timestampKey="time:timestamp") {
3 | let vect = freqDfg.getArtificialDfg();
4 | let outgoing = {};
5 | for (let act in vect[0]) {
6 | outgoing[act] = {};
7 | }
8 | for (let edge0 in vect[1]) {
9 | let edge = edge0.split(",");
10 | outgoing[edge[0]][edge[1]] = -Math.log(vect[1][edge0] / (0.0 + vect[0][edge[0]]));
11 | }
12 | let comparator = function(a,b) {
13 | return a[1] < b[1];
14 | };
15 | let queue = new PriorityQueue(comparator);
16 | let start = [["▶"], 0];
17 | queue.push(start);
18 | let count = 0;
19 | let minTimestamp = 10000000;
20 | let eventLog = new EventLog();
21 | while (true) {
22 | if (count >= numDesideredTraces) {
23 | break;
24 | }
25 | let el = queue.pop();
26 | let activities = el[0];
27 | let lastActivity = activities[activities.length-1];
28 | if (lastActivity == "■") {
29 | let prob = Math.exp(-el[1]);
30 | let trace = new Trace();
31 | trace.attributes["@@prob"] = new Attribute(prob);
32 | trace.attributes["concept:name"] = new Attribute(""+count);
33 | eventLog.traces.push(trace);
34 | let i = 1;
35 | while (i < activities.length - 1) {
36 | let newEve = new Event();
37 | trace.events.push(newEve);
38 | newEve.attributes[activityKey] = new Attribute(activities[i]);
39 | newEve.attributes[timestampKey] = new Attribute(new Date((minTimestamp + count)*1000));
40 | i++;
41 | }
42 | count++;
43 | }
44 | for (let act in outgoing[lastActivity]) {
45 | let newActivities = activities.slice();
46 | newActivities.push(act);
47 | queue.push([newActivities, el[1] + outgoing[lastActivity][act]]);
48 | }
49 | }
50 | Pm4JS.registerObject(eventLog, "Simulated Event log (from DFG)");
51 | return eventLog;
52 | }
53 | }
54 |
55 | try {
56 | module.exports = {DfgPlayout: DfgPlayout};
57 | global.DfgPlayout = DfgPlayout;
58 | }
59 | catch (err) {
60 | // not in Node
61 | //console.log(err);
62 | }
63 |
64 | Pm4JS.registerAlgorithm("DfgPlayout", "apply", ["FrequencyDfg"], "EventLog", "Perform Playout on a DFG", "Alessandro Berti");
65 | Pm4JS.registerAlgorithm("DfgPlayout", "apply", ["PerformanceDfg"], "EventLog", "Perform Playout on a DFG", "Alessandro Berti");
66 |
--------------------------------------------------------------------------------
/pm4js/algo/simulation/playout/dfg/performance.js:
--------------------------------------------------------------------------------
1 | class PerformanceDfgSimulation {
2 | static choiceFromProbDct(dct) {
3 | let choices = [];
4 | let prob = [];
5 | let cumprob = 0.0;
6 | for (let k in dct) {
7 | choices.push(k);
8 | cumprob += dct[k];
9 | prob.push(cumprob);
10 | }
11 | let rr = Math.random();
12 | let i = 0;
13 | while (i < choices.length) {
14 | if (prob[i] > rr) {
15 | return choices[i];
16 | }
17 | i++;
18 | }
19 | }
20 |
21 | static apply(performanceDfg, numDesideredTraces=1000, activityKey="concept:name", timestampKey="time:timestamp", caseArrivalRate=1) {
22 | let artificialDfg = performanceDfg.getArtificialDfg();
23 | let outgoing = {};
24 | for (let path0 in artificialDfg[1]) {
25 | let path = path0.split(",");
26 | if (!(path[0] in outgoing)) {
27 | outgoing[path[0]] = {};
28 | }
29 | outgoing[path[0]][path[1]] = artificialDfg[1][path0] / artificialDfg[0][path[0]];
30 | }
31 | let eventLog = new EventLog();
32 | let timestamp = 10000000;
33 | let i = 0;
34 | while (i < numDesideredTraces) {
35 | timestamp += 1;
36 | let currTraceTimestampTrace = 0 + timestamp;
37 | let trace = new Trace();
38 | eventLog.traces.push(trace);
39 | let currActivity = "▶";
40 | while (currActivity != "■") {
41 | let nextActivity = PerformanceDfgSimulation.choiceFromProbDct(outgoing[currActivity]);
42 | if (currActivity != "▶" && nextActivity != "■") {
43 | let path = [currActivity, nextActivity];
44 | let pathPerformance = performanceDfg.pathsPerformance[path];
45 | if (pathPerformance > 0) {
46 | let exp = new ExponentialRandomVariable(1.0 / pathPerformance);
47 | currTraceTimestampTrace += exp.getValue();
48 | }
49 | }
50 | if (nextActivity != "■") {
51 | let eve = new Event();
52 | eve.attributes[activityKey] = new Attribute(nextActivity);
53 | eve.attributes[timestampKey] = new Attribute(new Date(currTraceTimestampTrace*1000));
54 | trace.events.push(eve);
55 | }
56 | currActivity = nextActivity;
57 | }
58 | i++;
59 | }
60 | Pm4JS.registerObject(eventLog, "Simulated Event log (performance simulation from DFG)");
61 | return eventLog;
62 | }
63 | }
64 |
65 | try {
66 | module.exports = {PerformanceDfgSimulation: PerformanceDfgSimulation};
67 | global.PerformanceDfgSimulation = PerformanceDfgSimulation;
68 | }
69 | catch (err) {
70 | // not in Node
71 | }
72 |
73 | Pm4JS.registerAlgorithm("PerformanceDfgSimulation", "apply", ["PerformanceDfg"], "EventLog", "Perform Playout on a Performance DFG (performance simulation)", "Alessandro Berti");
74 |
--------------------------------------------------------------------------------
/pm4js/algo/simulation/playout/petri_net/algorithm.js:
--------------------------------------------------------------------------------
1 | class PetriNetPlayout {
2 | static apply(acceptingPetriNet, numDesideredTraces=1000, activityKey="concept:name", timestampKey="time:timestamp") {
3 | let petriNet = acceptingPetriNet.net;
4 | let initialMarking = acceptingPetriNet.im;
5 | let finalMarking = acceptingPetriNet.fm;
6 | let count = 0;
7 | let minTimestamp = 10000000;
8 | let eventLog = new EventLog();
9 | while (true) {
10 | if (count >= numDesideredTraces) {
11 | break;
12 | }
13 | let trace = new Trace();
14 | let marking = initialMarking.copy();
15 | while (!(finalMarking.equals(marking))) {
16 | let enabledTransitions = marking.getEnabledTransitions();
17 | let pickedTransition = enabledTransitions[Math.floor(Math.random() * enabledTransitions.length)];
18 | if (pickedTransition.label != null) {
19 | let eve = new Event();
20 | eve.attributes[activityKey] = new Attribute(pickedTransition.label);
21 | eve.attributes[timestampKey] = new Attribute(new Date(minTimestamp*1000));
22 | trace.events.push(eve);
23 | }
24 | marking = marking.execute(pickedTransition);
25 | minTimestamp++;
26 | }
27 | eventLog.traces.push(trace);
28 | count++;
29 | }
30 | Pm4JS.registerObject(eventLog, "Simulated Event log (from Petri net)");
31 | return eventLog;
32 | }
33 | }
34 |
35 | try {
36 | global.PetriNetPlayout = PetriNetPlayout;
37 | module.exports = {PetriNetPlayout: PetriNetPlayout};
38 | }
39 | catch (err) {
40 | // not in Node
41 | //console.log(err);
42 | }
43 |
44 | Pm4JS.registerAlgorithm("PetriNetPlayout", "apply", ["AcceptingPetriNet"], "EventLog", "Perform Playout on a Petri net", "Alessandro Berti");
45 |
--------------------------------------------------------------------------------
/pm4js/algo/transformation/ocel_conn_comp.js:
--------------------------------------------------------------------------------
1 | class OcelConnectedComponents {
2 | static findConnCompEvIds(ocel) {
3 | let evRelGraph = OcelGraphs.eventsRelationGraph(ocel);
4 | let connComp = {};
5 | let count = 0;
6 | for (let evId in ocel["ocel:events"]) {
7 | connComp[evId] = count;
8 | count++;
9 | }
10 | let cont = true;
11 | while (cont) {
12 | cont = false;
13 | for (let evId in evRelGraph) {
14 | for (let evId2 in evRelGraph[evId]) {
15 | if (connComp[evId] != connComp[evId2]) {
16 | let cc = Math.min(connComp[evId], connComp[evId2]);
17 | connComp[evId] = cc;
18 | connComp[evId2] = cc;
19 | cont = true;
20 | }
21 | }
22 | }
23 | }
24 | let connComp1 = {};
25 | for (let evId in connComp) {
26 | let cc = connComp[evId];
27 | if (!(cc in connComp1)) {
28 | connComp1[cc] = [];
29 | }
30 | connComp1[cc].push(evId);
31 | }
32 | return connComp1;
33 | }
34 |
35 |
36 | }
37 |
38 | try {
39 | module.exports = {OcelConnectedComponents: OcelConnectedComponents};
40 | global.OcelConnectedComponents = OcelConnectedComponents;
41 | }
42 | catch (err) {
43 | // not in node
44 | //console.log(err);
45 | }
--------------------------------------------------------------------------------
/pm4js/algo/transformation/ocel_interval_tree.js:
--------------------------------------------------------------------------------
1 | class OcelIntervalTree {
2 | static buildIntervalTreeDictioPerObject(ocel, objects, objLifecycle) {
3 | if (objects == null) {
4 | objects = Object.keys(ocel["ocel:objects"]);
5 | }
6 | if (objLifecycle == null) {
7 | objLifecycle = OcelIntervalTree.getObjectsLifecycle(ocel);
8 | }
9 | let dictio = {};
10 |
11 | for (let objId of objects) {
12 | let lif = objLifecycle[objId];
13 | if (lif.length > 0) {
14 | let tree = new IntervalTree();
15 | for (let eve of lif) {
16 | let evTimest = eve["ocel:timestamp"].getTime() / 1000.0;
17 | tree.insert(evTimest-0.00001, evTimest+0.00001, eve);
18 | }
19 | let mintime = null;
20 | for (let n of tree.ascending()) {
21 | mintime = n.low;
22 | break;
23 | }
24 | let maxtime = null;
25 | for (let n of tree.descending()) {
26 | maxtime = n.high;
27 | break;
28 | }
29 | tree.mintime = mintime;
30 | tree.maxtime = maxtime;
31 |
32 | dictio[objId] = tree;
33 | }
34 | }
35 |
36 | return dictio;
37 | }
38 |
39 | static buildEventTimestampIntervalTree(ocel) {
40 | let events = ocel["ocel:events"];
41 | let tree = new IntervalTree();
42 | for (let evId in events) {
43 | let eve = events[evId];
44 | let evTimest = eve["ocel:timestamp"].getTime() / 1000.0;
45 | tree.insert(evTimest-0.00001, evTimest+0.00001, eve);
46 | }
47 | let mintime = null;
48 | for (let n of tree.ascending()) {
49 | mintime = n.low;
50 | break;
51 | }
52 | let maxtime = null;
53 | for (let n of tree.descending()) {
54 | maxtime = n.high;
55 | break;
56 | }
57 | tree.mintime = mintime;
58 | tree.maxtime = maxtime;
59 | return tree;
60 | }
61 |
62 | static getObjectsLifecycle(ocel) {
63 | let lif = {};
64 | let objects = ocel["ocel:objects"];
65 | for (let objId in objects) {
66 | lif[objId] = [];
67 | }
68 | let events = ocel["ocel:events"];
69 | for (let evId in events) {
70 | let eve = {... events[evId]};
71 | eve["ocel:eid"] = evId;
72 |
73 | for (let objId of eve["ocel:omap"]) {
74 | lif[objId].push(eve);
75 | }
76 | }
77 | return lif;
78 | }
79 |
80 | static buildObjectLifecycleTimestampIntervalTree(ocel) {
81 | let objects = ocel["ocel:objects"];
82 | let objLifecycle = OcelIntervalTree.getObjectsLifecycle(ocel);
83 | let tree = new IntervalTree();
84 | for (let objId in objects) {
85 | let obj = objects[objId];
86 | let lif = objLifecycle[objId];
87 | if (lif.length > 0) {
88 | let st = lif[0]["ocel:timestamp"].getTime() / 1000.0;
89 | let et = lif[lif.length - 1]["ocel:timestamp"].getTime() / 1000.0;
90 | if (et > st) {
91 | tree.insert(st-0.00001, et+0.00001, [obj, lif]);
92 | }
93 | }
94 | }
95 | let mintime = null;
96 | for (let n of tree.ascending()) {
97 | mintime = n.low;
98 | break;
99 | }
100 | let maxtime = null;
101 | for (let n of tree.descending()) {
102 | maxtime = n.high;
103 | break;
104 | }
105 | tree.mintime = mintime;
106 | tree.maxtime = maxtime;
107 | return tree;
108 | }
109 | }
110 |
111 | try {
112 | module.exports = {OcelIntervalTree: OcelIntervalTree};
113 | global.OcelIntervalTree = OcelIntervalTree;
114 | }
115 | catch (err) {
116 | // not in node
117 | //console.log(err);
118 | }
--------------------------------------------------------------------------------
/pm4js/algo/transformation/ocel_propagation.js:
--------------------------------------------------------------------------------
1 | class OcelAttributePropagation {
2 | static propagateObjectAttributes(ocel0, referenceObjectType) {
3 | let ocel = OcelSegments.cloneOcel(ocel0);
4 |
5 | let objectInteractionGraph = OcelGraphs.objectInteractionGraph(ocel);
6 | let objectsPerType = OcelSegments.collectObjectsPerType(ocel);
7 |
8 | for (let objId of objectsPerType[referenceObjectType]) {
9 | let object = ocel["ocel:objects"][objId];
10 | let objAttrs = object["ocel:ovmap"];
11 |
12 | let allValues = {};
13 |
14 | if (objId in objectInteractionGraph) {
15 | for (let otherObjectId of objectInteractionGraph[objId]) {
16 | let otherObj = ocel["ocel:objects"][otherObjectId];
17 |
18 | for (let attr in otherObj["ocel:ovmap"]) {
19 | if (!(attr in objAttrs)) {
20 | if (!(attr in allValues)) {
21 | allValues[attr] = [];
22 | }
23 | allValues[attr].push(otherObj["ocel:ovmap"][attr]);
24 | }
25 | }
26 | }
27 | }
28 |
29 | for (let attr in allValues) {
30 | let values = allValues[attr];
31 |
32 | let allStrings = true;
33 | let allNumbers = true;
34 |
35 | for (let val of values) {
36 | if (typeof val != 'string') {
37 | allStrings = false;
38 | }
39 | if (typeof val != 'number') {
40 | allNumbers = false;
41 | }
42 | if (!(allStrings || allNumbers)) {
43 | break;
44 | }
45 | }
46 |
47 | if (allStrings) {
48 | ocel["ocel:objects"][objId]["ocel:ovmap"]["PROP_"+attr+"_FIRST"] = values[0];
49 | }
50 | else if (allNumbers) {
51 | ocel["ocel:objects"][objId]["ocel:ovmap"]["PROP_"+attr+"_MIN"] = Math.min(...values);
52 | ocel["ocel:objects"][objId]["ocel:ovmap"]["PROP_"+attr+"_MAX"] = Math.max(...values);
53 | }
54 | }
55 | }
56 |
57 | return ocel;
58 | }
59 | }
60 |
61 | try {
62 | module.exports = {OcelAttributePropagation: OcelAttributePropagation};
63 | global.OcelAttributePropagation = OcelAttributePropagation;
64 | }
65 | catch (err) {
66 | // not in node
67 | //console.log(err);
68 | }
69 |
--------------------------------------------------------------------------------
/pm4js/objects/bpmn/layouting/dagre.js:
--------------------------------------------------------------------------------
1 | class DagreBPMNLayouting {
2 | static apply(bpmnGraph, nodesep=null, edgesep=null, ranksep=null, targetSvg="svg", targetInner="g", d3Obj=null, dagreD3Obj=null) {
3 | // works only in browser
4 | // works only with Dagre/D3
5 | if (d3Obj == null) {
6 | d3Obj = d3;
7 | }
8 | if (dagreD3Obj == null) {
9 | dagreD3Obj = dagreD3;
10 | }
11 | let ordered = bpmnGraph.getOrderedNodesAndEdges();
12 |
13 | var g = new dagreD3Obj.graphlib.Graph().setGraph({});
14 |
15 | for (let nodeId of ordered["nodesId"]) {
16 | let node = bpmnGraph.nodes[nodeId];
17 | g.setNode(node.id, {"label": node.name});
18 | }
19 |
20 | for (let edge of ordered["edgesId"]) {
21 | g.setEdge(edge[0], edge[1], {})
22 | }
23 |
24 | g.graph().rankDir = 'LR';
25 | if (nodesep != null) {
26 | g.graph().nodesep = nodesep;
27 | }
28 | if (edgesep != null) {
29 | g.graph().edgesep = edgesep;
30 | }
31 | if (ranksep != null) {
32 | g.graph().ranksep = ranksep;
33 | }
34 |
35 | let render = new dagreD3Obj.render();
36 |
37 | let svg = d3Obj.select(targetSvg);
38 | let inner = svg.append(targetInner);
39 | render(inner, g);
40 |
41 | for (let nodeId in g._nodes) {
42 | let node = g._nodes[nodeId];
43 | let elemStr = node.elem.innerHTML;
44 | let width = parseInt(elemStr.split('width=\"')[1].split('\"')[0]);
45 | let height = parseInt(elemStr.split('height=\"')[1].split('\"')[0]);
46 | bpmnGraph.nodes[nodeId].bounds = {"x": node.x - width/2, "y": node.y - height/2, "width": width, "height": height};
47 | }
48 |
49 |
50 | for (let edgeId in g._edgeLabels) {
51 | let graphEdgeObj = g._edgeObjs[edgeId];
52 | graphEdgeObj = [graphEdgeObj.v, graphEdgeObj.w];
53 | let graphEdge = g._edgeLabels[edgeId];
54 | let edge = g._edgeLabels[edgeId];
55 | bpmnGraph.edges[ordered["invMap"][graphEdgeObj]].waypoints = null;
56 | bpmnGraph.edges[ordered["invMap"][graphEdgeObj]].waypoints = [];
57 | for (let p of edge.points) {
58 | bpmnGraph.edges[ordered["invMap"][graphEdgeObj]].waypoints.push([p["x"], p["y"]]);
59 | }
60 | }
61 |
62 | return bpmnGraph;
63 | }
64 | }
65 |
66 | try {
67 | module.exports = {DagreBPMNLayouting: DagreBPMNLayouting};
68 | global.DagreBPMNLayouting = DagreBPMNLayouting;
69 | }
70 | catch (err) {
71 | // not in Node
72 | //console.log(err);
73 | }
74 |
--------------------------------------------------------------------------------
/pm4js/objects/dfg/exporter/exporter.js:
--------------------------------------------------------------------------------
1 | class FrequencyDfgExporter {
2 | static apply(frequencyDfg) {
3 | let ret = [];
4 | let activities = Object.keys(frequencyDfg.activities);
5 | ret.push(activities.length);
6 | for (let act in frequencyDfg.activities) {
7 | ret.push(act);
8 | }
9 | ret.push(Object.keys(frequencyDfg.startActivities).length);
10 | for (let act in frequencyDfg.startActivities) {
11 | ret.push(activities.indexOf(act)+"x"+frequencyDfg.startActivities[act]);
12 | }
13 | ret.push(Object.keys(frequencyDfg.endActivities).length);
14 | for (let act in frequencyDfg.endActivities) {
15 | ret.push(activities.indexOf(act)+"x"+frequencyDfg.endActivities[act]);
16 | }
17 | for (let path0 in frequencyDfg.pathsFrequency) {
18 | let path = path0.split(",");
19 | ret.push(activities.indexOf(path[0])+">"+activities.indexOf(path[1])+"x"+frequencyDfg.pathsFrequency[path0]);
20 | }
21 | return ret.join("\n");
22 | }
23 | }
24 |
25 | try {
26 | global.FrequencyDfgExporter = FrequencyDfgExporter;
27 | module.exports = {FrequencyDfgExporter: FrequencyDfgExporter};
28 | }
29 | catch (err) {
30 | // not in node
31 | //console.log(err);
32 | }
33 |
34 | Pm4JS.registerExporter("FrequencyDfgExporter", "apply", "FrequencyDfg", "dfg", "text/plain", "DFG Exporter (.dfg)", "Alessandro Berti");
35 | Pm4JS.registerExporter("FrequencyDfgExporter", "apply", "PerformanceDfg", "dfg", "text/plain", "DFG Exporter (.dfg)", "Alessandro Berti");
36 |
--------------------------------------------------------------------------------
/pm4js/objects/dfg/frequency/obj.js:
--------------------------------------------------------------------------------
1 | class FrequencyDfg {
2 | constructor(activities, startActivities, endActivities, pathsFrequency) {
3 | this.activities = activities;
4 | this.startActivities = startActivities;
5 | this.endActivities = endActivities;
6 | this.pathsFrequency = pathsFrequency;
7 | }
8 |
9 | getArtificialDfg() {
10 | let artificialActivities = {};
11 | let artificialDfg = {};
12 | Object.assign(artificialDfg, this.pathsFrequency);
13 | Object.assign(artificialActivities, this.activities);
14 | let sumSa = 0;
15 | for (let sa in this.startActivities) {
16 | artificialDfg[["▶", sa]] = this.startActivities[sa];
17 | sumSa += this.startActivities[sa];
18 | }
19 | for (let ea in this.endActivities) {
20 | artificialDfg[[ea, "■"]] = this.endActivities[ea];
21 | }
22 | artificialActivities["▶"] = sumSa;
23 | artificialActivities["■"] = sumSa;
24 | return [artificialActivities, artificialDfg];
25 | }
26 |
27 | unrollArtificialDfg(vect) {
28 | let artificialActivities = vect[0];
29 | let artificialDfg = vect[1];
30 | let newActivities = {};
31 | let newPathsFrequency = {};
32 | let newStartActivities = {};
33 | let newEndActivities = {};
34 | Object.assign(newActivities, artificialActivities);
35 | Object.assign(newPathsFrequency, artificialDfg);
36 | for (let el0 in artificialDfg) {
37 | let el = el0.split(",");
38 | if (el[0] == "▶") {
39 | newStartActivities[el[1]] = artificialDfg[el0];
40 | delete newPathsFrequency[el];
41 | }
42 | else if (el[1] == "■") {
43 | newEndActivities[el[0]] = artificialDfg[el0];
44 | delete newPathsFrequency[el];
45 | }
46 | }
47 | delete newActivities["▶"];
48 | delete newActivities["■"];
49 | return new FrequencyDfg(newActivities, newStartActivities, newEndActivities, newPathsFrequency);
50 | }
51 | }
52 |
53 | try {
54 | module.exports = {FrequencyDfg: FrequencyDfg};
55 | global.FrequencyDfg = FrequencyDfg;
56 | }
57 | catch (err) {
58 | // not in Node
59 | }
60 |
--------------------------------------------------------------------------------
/pm4js/objects/dfg/importer/importer.js:
--------------------------------------------------------------------------------
1 | class FrequencyDfgImporter {
2 | static apply(txtStri) {
3 | let stri = txtStri.split("\n");
4 | let i = 0;
5 | let numActivities = i + 1 + parseInt(stri[i]);
6 | i++;
7 | let activities = [];
8 | let activitiesIngoing = {};
9 | let startActivities = {};
10 | let endActivities = {};
11 | let pathsFrequency = {};
12 | while (i < numActivities) {
13 | activities.push(stri[i].trim());
14 | i++;
15 | }
16 | let numStartActivities = i + 1 + parseInt(stri[i]);
17 | i++;
18 | while (i < numStartActivities) {
19 | let stru = stri[i].trim().split("x");
20 | let act = activities[parseInt(stru[0])]
21 | startActivities[act] = parseInt(stru[1]);
22 | if (!(act in activitiesIngoing)) {
23 | activitiesIngoing[act] = 0;
24 | }
25 | activitiesIngoing[act] += parseInt(stru[1]);
26 | i++;
27 | }
28 | let numEndActivities = i + 1 + parseInt(stri[i]);
29 | i++;
30 | while (i < numEndActivities) {
31 | let stru = stri[i].trim().split("x");
32 | let act = activities[parseInt(stru[0])];
33 | endActivities[act] = parseInt(stru[1]);
34 | i++;
35 | }
36 | while (i < stri.length) {
37 | let stru = stri[i].trim();
38 | if (stru.length > 0) {
39 | let act1 = activities[parseInt(stru.split(">")[0])];
40 | let act2 = activities[parseInt(stru.split("x")[0].split(">")[1])];
41 | let count = parseInt(stru.split("x")[1]);
42 | if (!(act2 in activitiesIngoing)) {
43 | activitiesIngoing[act2] = 0;
44 | }
45 | activitiesIngoing[act2] += count;
46 | pathsFrequency[[act1, act2]] = count;
47 | }
48 | i++;
49 | }
50 | let ret = new FrequencyDfg(activitiesIngoing, startActivities, endActivities, pathsFrequency);
51 | Pm4JS.registerObject(ret, "Frequency DFG");
52 | return ret;
53 | }
54 | }
55 |
56 | try {
57 | global.FrequencyDfgImporter = FrequencyDfgImporter;
58 | module.exports = {FrequencyDfgImporter: FrequencyDfgImporter};
59 | }
60 | catch (err) {
61 | // not in Node
62 | //console.log(err);
63 | }
64 |
65 | Pm4JS.registerImporter("FrequencyDfgImporter", "apply", ["dfg"], "Frequency DFG Importer", "Alessandro Berti");
66 |
--------------------------------------------------------------------------------
/pm4js/objects/dfg/performance/obj.js:
--------------------------------------------------------------------------------
1 | class PerformanceDfg {
2 | constructor(activities, startActivities, endActivities, pathsFrequency, pathsPerformance, sojournTimes) {
3 | this.activities = activities;
4 | this.startActivities = startActivities;
5 | this.endActivities = endActivities;
6 | this.pathsFrequency = pathsFrequency;
7 | this.pathsPerformance = pathsPerformance;
8 | this.sojournTimes = sojournTimes;
9 | }
10 |
11 | getArtificialDfg() {
12 | let artificialActivities = {};
13 | let artificialDfg = {};
14 | Object.assign(artificialDfg, this.pathsFrequency);
15 | Object.assign(artificialActivities, this.activities);
16 | let sumSa = 0;
17 | for (let sa in this.startActivities) {
18 | artificialDfg[["▶", sa]] = this.startActivities[sa];
19 | sumSa += this.startActivities[sa];
20 | }
21 | for (let ea in this.endActivities) {
22 | artificialDfg[[ea, "■"]] = this.endActivities[ea];
23 | }
24 | artificialActivities["▶"] = sumSa;
25 | artificialActivities["■"] = sumSa;
26 | return [artificialActivities, artificialDfg];
27 | }
28 |
29 | unrollArtificialDfg(vect) {
30 | let artificialActivities = vect[0];
31 | let artificialDfg = vect[1];
32 | let newActivities = {};
33 | let newPathsFrequency = {};
34 | let newStartActivities = {};
35 | let newEndActivities = {};
36 | let newPathsPerformance = {};
37 | let newSojournTimes = {};
38 | Object.assign(newActivities, artificialActivities);
39 | Object.assign(newPathsFrequency, artificialDfg);
40 | for (let el0 in artificialDfg) {
41 | let el = el0.split(",");
42 | if (el[0] == "▶") {
43 | newStartActivities[el[1]] = artificialDfg[el0];
44 | delete newPathsFrequency[el];
45 | }
46 | else if (el[1] == "■") {
47 | newEndActivities[el[0]] = artificialDfg[el0];
48 | delete newPathsFrequency[el];
49 | }
50 | }
51 | delete newActivities["▶"];
52 | delete newActivities["■"];
53 | for (let act in this.sojournTimes) {
54 | if (act in newActivities) {
55 | newSojournTimes[act] = this.sojournTimes[act];
56 | }
57 | }
58 | for (let path in this.pathsPerformance) {
59 | if (path in newPathsFrequency) {
60 | newPathsPerformance[path] = this.pathsPerformance[path];
61 | }
62 | }
63 | return new PerformanceDfg(newActivities, newStartActivities, newEndActivities, newPathsFrequency, newPathsPerformance, newSojournTimes);
64 | }
65 | }
66 |
67 | try {
68 | module.exports = {PerformanceDfg: PerformanceDfg};
69 | global.PerformanceDfg = PerformanceDfg;
70 | }
71 | catch (err) {
72 | // not in Node
73 | }
74 |
--------------------------------------------------------------------------------
/pm4js/objects/log/exporter/csv/exporter.js:
--------------------------------------------------------------------------------
1 | class CsvExporter {
2 | static apply(eventLog, sep=CsvExporter.DEFAULT_SEPARATOR, quotechar=CsvExporter.DEFAULT_QUOTECHAR, casePrefix=CsvExporter.DEFAULT_CASE_PREFIX, newline=CsvExporter.DEFAULT_NEWLINE) {
3 | let caseAttributes = GeneralLogStatistics.getCaseAttributesList(eventLog);
4 | let eventAttributes0 = GeneralLogStatistics.getEventAttributesList(eventLog);
5 | let eventAttributes = [];
6 | for (let ea of eventAttributes0) {
7 | if (!(ea.startsWith(casePrefix))) {
8 | eventAttributes.push(ea);
9 | }
10 | }
11 | let ret = [];
12 | let header = "";
13 | for (let ca of caseAttributes) {
14 | header += casePrefix+ca+sep;
15 | }
16 | for (let ea of eventAttributes) {
17 | header += ea+sep;
18 | }
19 | header = header.slice(0, -1);
20 | ret.push(header);
21 | for (let trace of eventLog.traces) {
22 | let pref = "";
23 | for (let ca of caseAttributes) {
24 | let val = trace.attributes[ca];
25 | if (val != null) {
26 | val = val.value;
27 | if (typeof val == "string" && val.includes(sep)) {
28 | pref += quotechar+val+quotechar+sep;
29 | }
30 | else if (typeof val == "object") {
31 | //pref += val.toISOString()+sep;
32 | pref += DateUtils.formatDateString(val)+sep;
33 | }
34 | else {
35 | pref += val+sep;
36 | }
37 | }
38 | else {
39 | pref += sep;
40 | }
41 | }
42 | for (let eve of trace.events) {
43 | let eveStr = ""+pref;
44 | for (let ea of eventAttributes) {
45 | let val = eve.attributes[ea];
46 | if (val != null) {
47 | val = val.value;
48 | if (typeof val == "string" && val.includes(sep)) {
49 | eveStr += quotechar+val+quotechar+sep;
50 | }
51 | else if (typeof val == "object") {
52 | //eveStr += val.toISOString()+sep;
53 | eveStr += DateUtils.formatDateString(val)+sep;
54 | }
55 | else {
56 | eveStr += val+sep;
57 | }
58 | }
59 | else {
60 | eveStr += sep;
61 | }
62 | }
63 | eveStr = eveStr.slice(0, -1);
64 | ret.push(eveStr);
65 | }
66 | }
67 | ret = ret.join(newline);
68 | return ret;
69 | }
70 | }
71 |
72 | CsvExporter.DEFAULT_CASE_ID = "case:concept:name";
73 | CsvExporter.DEFAULT_ACTIVITY = "concept:name";
74 | CsvExporter.DEFAULT_TIMESTAMP = "time:timestamp";
75 | CsvExporter.DEFAULT_CASE_ID_AS_TRACE_ATTRIBUTE = "concept:name";
76 | CsvExporter.DEFAULT_CASE_PREFIX = "case:";
77 | CsvExporter.DEFAULT_SEPARATOR = ',';
78 | CsvExporter.DEFAULT_QUOTECHAR = '"';
79 | CsvExporter.DEFAULT_NEWLINE = '\n';
80 |
81 | try {
82 | module.exports = {CsvExporter: CsvExporter};
83 | global.CsvExporter = CsvExporter;
84 | }
85 | catch (err) {
86 | // not in node
87 | //console.log(err);
88 | }
89 |
90 | Pm4JS.registerExporter("CsvExporter", "apply", "EventLog", "csv", "text/csv", "CSV Exporter", "Alessandro Berti");
91 |
--------------------------------------------------------------------------------
/pm4js/objects/log/exporter/xes/exporter.js:
--------------------------------------------------------------------------------
1 | class XesExporter {
2 | static apply(eventLog) {
3 | let xmlDoc = document.createElement("log");
4 | XesExporter.exportXmlObjToDom(eventLog, xmlDoc);
5 | let serializer = null;
6 | try {
7 | serializer = new XMLSerializer();
8 | }
9 | catch (err) {
10 | serializer = require('xmlserializer');
11 | }
12 | const xmlStr = serializer.serializeToString(xmlDoc);
13 | return xmlStr;
14 | }
15 |
16 | static exportXmlObjToDom(obj, dom) {
17 | for (let att in obj.attributes) {
18 | let attValue = obj.attributes[att].value;
19 | let xmlTag = null;
20 | let value = null;
21 | if (typeof attValue == "string") {
22 | xmlTag = "string";
23 | value = attValue;
24 | }
25 | else if (typeof attValue == "object") {
26 | xmlTag = "date";
27 | value = attValue.toISOString();
28 | }
29 | else if (typeof attValue == "number") {
30 | xmlTag = "float";
31 | value = ""+attValue;
32 | }
33 |
34 | if (value != null) {
35 | let attr = document.createElement(xmlTag);
36 | dom.appendChild(attr);
37 | attr.setAttribute("key", att);
38 | attr.setAttribute("value", value);
39 | XesExporter.exportXmlObjToDom(obj.attributes[att], attr);
40 | }
41 | }
42 | if (obj.constructor.name == "EventLog") {
43 | for (let ext in obj.extensions) {
44 | let extValue = obj.extensions[ext];
45 | let xmlExtension = document.createElement("extension");
46 | dom.appendChild(xmlExtension);
47 | xmlExtension.setAttribute("name", ext);
48 | xmlExtension.setAttribute("prefix", extValue[0]);
49 | xmlExtension.setAttribute("uri", extValue[1]);
50 | }
51 | for (let scope in obj.globals) {
52 | let global = obj.globals[scope];
53 | let xmlGlobal = document.createElement("global");
54 | dom.appendChild(xmlGlobal);
55 | xmlGlobal.setAttribute("scope", scope);
56 | XesExporter.exportXmlObjToDom(global, xmlGlobal);
57 | }
58 | for (let classifier in obj.classifiers) {
59 | let xmlClassifier = document.createElement("classifier");
60 | dom.appendChild(xmlClassifier);
61 | xmlClassifier.setAttribute("name", classifier);
62 | xmlClassifier.setAttribute("keys", obj.classifiers[classifier]);
63 | }
64 | for (let trace of obj.traces) {
65 | let xmlTrace = document.createElement("trace");
66 | dom.appendChild(xmlTrace);
67 | XesExporter.exportXmlObjToDom(trace, xmlTrace);
68 | }
69 | }
70 | else if (obj.constructor.name == "Trace") {
71 | for (let eve of obj.events) {
72 | let xmlEvent = document.createElement("event");
73 | dom.appendChild(xmlEvent);
74 | XesExporter.exportXmlObjToDom(eve, xmlEvent);
75 | }
76 | }
77 | }
78 | }
79 |
80 | try {
81 | module.exports = {XesExporter: XesExporter};
82 | global.XesExporter = XesExporter;
83 | const jsdom = require("jsdom");
84 | const { JSDOM } = jsdom;
85 | global.dom = new JSDOM('');
86 | global.window = dom.window;
87 | global.document = dom.window.document;
88 | global.navigator = global.window.navigator;
89 | }
90 | catch (err) {
91 | // not in node
92 | //console.log(err);
93 | }
94 |
95 | Pm4JS.registerExporter("XesExporter", "apply", "EventLog", "xes", "text/xml", "XES Exporter", "Alessandro Berti");
--------------------------------------------------------------------------------
/pm4js/objects/log/importer/xes/importer.js:
--------------------------------------------------------------------------------
1 | class XesImporter {
2 | static apply(xmlString) {
3 | let parser = new DOMParser();
4 | var xmlDoc = parser.parseFromString(xmlString, "text/xml");
5 | let xmlLog = xmlDoc.getElementsByTagName("log")[0];
6 | let eventLog = new EventLog();
7 | XesImporter.parseXmlObj(xmlLog, eventLog);
8 | let desc = "Log imported from a XES file"
9 | if ("name" in eventLog.attributes) {
10 | desc = eventLog.attributes["name"];
11 | }
12 | Pm4JS.registerObject(eventLog, "Log imported from a XES file");
13 | return eventLog;
14 | }
15 |
16 | static parseXmlObj(xmlObj, target) {
17 | for (let childId in xmlObj.childNodes) {
18 | let child = xmlObj.childNodes[childId];
19 | if (child.tagName == "string") {
20 | let xmlAttr = new Attribute(child.getAttribute("value"));
21 | target.attributes[child.getAttribute("key")] = xmlAttr;
22 | XesImporter.parseXmlObj(child, xmlAttr);
23 | }
24 | else if (child.tagName == "date") {
25 | let xmlAttr = new Attribute(new Date(child.getAttribute("value")));
26 | target.attributes[child.getAttribute("key")] = xmlAttr;
27 | XesImporter.parseXmlObj(child, xmlAttr);
28 | }
29 | else if (child.tagName == "float") {
30 | let xmlAttr = new Attribute(parseFloat(child.getAttribute("value")));
31 | target.attributes[child.getAttribute("key")] = xmlAttr;
32 | XesImporter.parseXmlObj(child, xmlAttr);
33 | }
34 | else if (child.tagName == "event") {
35 | let eve = new Event();
36 | target.events.push(eve);
37 | XesImporter.parseXmlObj(child, eve);
38 | }
39 | else if (child.tagName == "trace") {
40 | let trace = new Trace();
41 | target.traces.push(trace);
42 | XesImporter.parseXmlObj(child, trace);
43 | }
44 | else if (child.tagName == "extension") {
45 | target.extensions[child.getAttribute("name")] = [child.getAttribute("prefix"), child.getAttribute("uri")];
46 | }
47 | else if (child.tagName == "global") {
48 | let targetObj = new LogGlobal();
49 | target.globals[child.getAttribute("scope")] = targetObj;
50 | XesImporter.parseXmlObj(child, targetObj);
51 | }
52 | else if (child.tagName == "classifier") {
53 | target.classifiers[child.getAttribute("name")] = child.getAttribute("keys");
54 | }
55 | }
56 | }
57 | }
58 |
59 | try {
60 | module.exports = {XesImporter: XesImporter};
61 | global.XesImporter = XesImporter;
62 | global.DOMParser = require('xmldom').DOMParser;
63 | }
64 | catch (err) {
65 | // not in node
66 | }
67 |
68 | Pm4JS.registerImporter("XesImporter", "apply", ["xes"], "XES Importer", "Alessandro Berti");
--------------------------------------------------------------------------------
/pm4js/objects/log/log.js:
--------------------------------------------------------------------------------
1 | class EventLog {
2 | constructor() {
3 | this.attributes = {};
4 | this.traces = [];
5 | this.extensions = {};
6 | this.globals = {};
7 | this.classifiers = {};
8 | }
9 | }
10 |
11 | class Trace {
12 | constructor() {
13 | this.attributes = {};
14 | this.events = [];
15 | }
16 | }
17 |
18 | class Event {
19 | constructor() {
20 | this.attributes = {};
21 | }
22 | }
23 |
24 | class LogGlobal {
25 | constructor() {
26 | this.attributes = {};
27 | }
28 | }
29 |
30 | class Attribute {
31 | constructor(value) {
32 | this.value = value;
33 | this.attributes = [];
34 | }
35 | }
36 |
37 |
38 | try {
39 | module.exports = {EventLog: EventLog, Trace: Trace, Event: Event, LogGlobal: LogGlobal, Attribute: Attribute};
40 | global.EventLog = EventLog;
41 | global.Trace = Trace;
42 | global.Event = Event;
43 | global.LogGlobal = LogGlobal;
44 | global.Attribute = Attribute;
45 | }
46 | catch (err) {
47 | // not in node
48 | }
--------------------------------------------------------------------------------
/pm4js/objects/log/util/log_to_stream.js:
--------------------------------------------------------------------------------
1 | class EventLogToStream {
2 | static shallowCopy(eve0) {
3 | let eve = new Event();
4 | for (let attr in eve0.attributes) {
5 | eve.attributes[attr] = eve0.attributes[attr];
6 | }
7 | return eve;
8 | }
9 |
10 | static apply(eventLog, sortingAttribute="time:timestamp", casePrefix="case:") {
11 | let stream = [];
12 | for (let trace of eventLog.traces) {
13 | for (let eve0 of trace.events) {
14 | let eve = EventLogToStream.shallowCopy(eve0);
15 | for (let traceAttr in trace.attributes) {
16 | let traceAttrValue = trace.attributes[traceAttr];
17 | eve.attributes[casePrefix+traceAttr] = traceAttrValue;
18 | }
19 | stream.push(eve);
20 | }
21 | }
22 | stream.sort((a, b) => { return a.attributes[sortingAttribute].value - b.attributes[sortingAttribute].value });
23 | return stream;
24 | }
25 | }
26 |
27 | try {
28 | module.exports = {EventLogToStream: EventLogToStream};
29 | global.EventLogToStream = EventLogToStream;
30 | }
31 | catch (err) {
32 | // not in node
33 | //console.log(err);
34 | }
35 |
--------------------------------------------------------------------------------
/pm4js/objects/log/util/prefixes.js:
--------------------------------------------------------------------------------
1 | class EventLogPrefixes {
2 | static apply(eventLog, activityKey="concept:name") {
3 | let prefixes = {};
4 | let i = 0;
5 | for (let trace of eventLog.traces) {
6 | i = 0;
7 | let actArray = [];
8 | while (i < trace.events.length - 1) {
9 | let act = trace.events[i].attributes[activityKey].value;
10 | let nextAct = trace.events[i+1].attributes[activityKey].value;
11 | actArray.push(act);
12 | if (!(actArray in prefixes)) {
13 | prefixes[actArray] = {};
14 | }
15 | if (!(nextAct in prefixes[actArray])) {
16 | prefixes[actArray][nextAct] = 0;
17 | }
18 | prefixes[actArray][nextAct] += 1;
19 | i++;
20 | }
21 | }
22 | return prefixes;
23 | }
24 | }
25 |
26 | try {
27 | module.exports = {EventLogPrefixes: EventLogPrefixes};
28 | global.EventLogPrefixes = EventLogPrefixes;
29 | }
30 | catch (err) {
31 | // not in node
32 | //console.log(err);
33 | }
34 |
--------------------------------------------------------------------------------
/pm4js/objects/ocel/exporter/csv/exporter.js:
--------------------------------------------------------------------------------
1 | class CsvOcelExporter {
2 | static apply(ocel, sep=CsvOcelExporter.DEFAULT_SEPARATOR, quotechar=CsvOcelExporter.DEFAULT_QUOTECHAR, newline=CsvOcelExporter.DEFAULT_NEWLINE) {
3 | let rows = [];
4 | let header = ["ocel:eid", "ocel:activity", "ocel:timestamp"];
5 | for (let objType of ocel["ocel:global-log"]["ocel:object-types"]) {
6 | let objType1 = objType.split("ocel:type:");
7 | objType1 = objType1[objType1.length - 1]
8 | header.push("ocel:type:"+objType1);
9 | }
10 | for (let attName of ocel["ocel:global-log"]["ocel:attribute-names"]) {
11 | header.push(attName);
12 | }
13 | rows.push(header.join(sep));
14 | for (let evId in ocel["ocel:events"]) {
15 | let eve = ocel["ocel:events"][evId];
16 | let row = [];
17 | row.push(evId);
18 | row.push(eve["ocel:activity"]);
19 | row.push(eve["ocel:timestamp"].toISOString());
20 | let omap = eve["ocel:omap"];
21 | let typeOmap = {};
22 | for (let objType of ocel["ocel:global-log"]["ocel:object-types"]) {
23 | typeOmap[objType] = [];
24 | }
25 | for (let obj of omap) {
26 | let objType = ocel["ocel:objects"][obj]["ocel:type"];
27 | typeOmap[objType].push(obj);
28 | }
29 | for (let objType of ocel["ocel:global-log"]["ocel:object-types"]) {
30 | if (typeOmap[objType].length > 0) {
31 | row.push(quotechar+"['"+typeOmap[objType].join("','")+"']"+quotechar);
32 | }
33 | else {
34 | row.push(" ");
35 | }
36 | }
37 | for (let attName of ocel["ocel:global-log"]["ocel:attribute-names"]) {
38 | if (attName in eve["ocel:vmap"]) {
39 | row.push(eve["ocel:vmap"][attName]);
40 | }
41 | else {
42 | row.push(" ");
43 | }
44 | }
45 | rows.push(row.join(sep));
46 | }
47 | return rows.join(newline);
48 | }
49 | }
50 |
51 | CsvOcelExporter.DEFAULT_SEPARATOR = ',';
52 | CsvOcelExporter.DEFAULT_QUOTECHAR = '"';
53 | CsvOcelExporter.DEFAULT_NEWLINE = '\n';
54 |
55 | try {
56 | module.exports = {CsvOcelExporter: CsvOcelExporter};
57 | global.CsvOcelExporter = CsvOcelExporter;
58 | }
59 | catch (err) {
60 | // not in node
61 | //console.log(err);
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/pm4js/objects/ocel/exporter/json2/exporter.js:
--------------------------------------------------------------------------------
1 | class JsonOcel2Exporter {
2 | static apply(ocel) {
3 | ocel = Ocel20FormatFixer.apply(ocel);
4 |
5 | let jsonObj = {};
6 | jsonObj["objectTypes"] = [];
7 | jsonObj["eventTypes"] = [];
8 | jsonObj["objects"] = [];
9 | jsonObj["events"] = [];
10 |
11 | for (let ot in ocel["ocel:objectTypes"]) {
12 | let attrs = ocel["ocel:objectTypes"][ot];
13 | let descr = {"name": ot, "attributes": []};
14 | for (let attr in attrs) {
15 | let attr_type = attrs[attr];
16 | descr["attributes"].push({"name": attr, "type": attr_type});
17 | }
18 | jsonObj["objectTypes"].push(descr);
19 | }
20 |
21 | for (let et in ocel["ocel:eventTypes"]) {
22 | let attrs = ocel["ocel:eventTypes"][et];
23 | let descr = {"name": et, "attributes": []};
24 | for (let attr in attrs) {
25 | let attr_type = attrs[attr];
26 | descr["attributes"].push({"name": attr, "type": attr_type});
27 | }
28 | jsonObj["eventTypes"].push(descr);
29 | }
30 |
31 | let objIdx = {};
32 | let i = 0;
33 | for (let objId in ocel["ocel:objects"]) {
34 | let obj = ocel["ocel:objects"][objId];
35 | let descr = {"id": objId, "type": obj["ocel:type"]};
36 |
37 | if ("ocel:ovmap" in obj) {
38 | if (Object.keys(obj["ocel:ovmap"]).length > 0) {
39 | descr["attributes"] = [];
40 | for (let k in obj["ocel:ovmap"]) {
41 | let v = obj["ocel:ovmap"][k];
42 | descr["attributes"].push({"name": k, "time": "1970-01-01T00:00:00Z", "value": v});
43 | }
44 | }
45 | }
46 |
47 | if ("ocel:o2o" in obj) {
48 | if (obj["ocel:o2o"].length > 0) {
49 | descr["relationships"] = [];
50 | for (let v of obj["ocel:o2o"]) {
51 | descr["relationships"].push({"objectId": v["ocel:oid"], "qualifier": v["ocel:qualifier"]});
52 | }
53 | }
54 | }
55 |
56 | jsonObj["objects"].push(descr);
57 | objIdx[objId] = i;
58 | i++;
59 | }
60 |
61 | let eveIdx = {};
62 | i = 0;
63 | for (let evId in ocel["ocel:events"]) {
64 | let eve = ocel["ocel:events"][evId];
65 | let descr = {"id": evId, "type": eve["ocel:activity"], "time": eve["ocel:timestamp"]};
66 |
67 | if ("ocel:vmap" in eve) {
68 | if (Object.keys(eve["ocel:vmap"]).length > 0) {
69 | descr["attributes"] = [];
70 | for (let k in eve["ocel:vmap"]) {
71 | let v = eve["ocel:vmap"][k];
72 | descr["attributes"].push({"name": k, "value": v});
73 | }
74 | }
75 | }
76 |
77 | if ("ocel:typedOmap" in eve) {
78 | if (eve["ocel:typedOmap"].length > 0) {
79 | descr["relationships"] = [];
80 | for (let v of eve["ocel:typedOmap"]) {
81 | descr["relationships"].push({"objectId": v["ocel:oid"], "qualifier": v["ocel:qualifier"]});
82 | }
83 | }
84 | }
85 | jsonObj["events"].push(descr);
86 | eveIdx[evId] = i;
87 | i++;
88 | }
89 |
90 | for (let change of ocel["ocel:objectChanges"]) {
91 | try {
92 | let oid = change["ocel:oid"];
93 | let obj = jsonObj["objects"][objIdx[oid]];
94 |
95 | obj["attributes"].push({"name": change["ocel:name"], "time": change["ocel:timestamp"], "value": change["ocel:value"]});
96 |
97 | jsonObj["objects"][objIdx[oid]] = obj;
98 | }
99 | catch (err) {
100 | }
101 | }
102 |
103 | return JSON.stringify(jsonObj);
104 | }
105 | }
106 |
107 | try {
108 | module.exports = {JsonOcel2Exporter: JsonOcel2Exporter};
109 | global.JsonOcel2Exporter = JsonOcel2Exporter;
110 | }
111 | catch (err) {
112 | // not in node
113 | //console.log(err);
114 | }
115 |
116 |
--------------------------------------------------------------------------------
/pm4js/objects/ocel/exporter/jsonocel/exporter.js:
--------------------------------------------------------------------------------
1 | class JsonOcelExporter {
2 | static apply(ocel) {
3 | return JsonOcelExporter.exportLog(ocel);
4 | }
5 |
6 | static exportLog(ocel) {
7 | ocel = Ocel20FormatFixer.apply(ocel);
8 | return JSON.stringify(ocel);
9 | }
10 | }
11 |
12 | try {
13 | module.exports = {JsonOcelExporter: JsonOcelExporter};
14 | global.JsonOcelExporter = JsonOcelExporter;
15 | }
16 | catch (err) {
17 | // not in node
18 | //console.log(err);
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/pm4js/objects/ocel/importer/csv/importer.js:
--------------------------------------------------------------------------------
1 | class CsvOcelImporter {
2 | static apply(txt, activityColumn, timestampColumn, objectTypes, attNames, evIdColumn=null, separators=null, sep=CsvOcelImporter.DEFAULT_SEPARATOR, quotechar=CsvOcelImporter.DEFAULT_QUOTECHAR) {
3 | if (separators == null) {
4 | separators = ["\"", "'"];
5 | }
6 | let arr = CsvImporter.parseCSV(txt, sep=sep, quotechar=quotechar);
7 | let ocel = {};
8 | ocel["ocel:events"] = {};
9 | ocel["ocel:objects"] = {};
10 | ocel["ocel:global-event"] = {"ocel:activity": "__INVALID__"};
11 | ocel["ocel:global-object"] = {"ocel:activity": "__INVALID__"};
12 | ocel["ocel:global-log"] = {"ocel:version": "1.0", "ocel:ordering": "timestamp", "ocel:attribute-names": attNames, "ocel:object-types": objectTypes};
13 | let i = 1;
14 | while (i < arr.length) {
15 | let eve = {"ocel:omap": [], "ocel:vmap": {}}
16 | let evId = null;
17 | if (evIdColumn == null) {
18 | evId = ""+i;
19 | }
20 | let j = 0;
21 | while (j < arr[0].length) {
22 | if (arr[0][j] == evIdColumn) {
23 | evId = arr[i][j];
24 | }
25 | if (arr[0][j] == activityColumn) {
26 | eve["ocel:activity"] = arr[i][j];
27 | }
28 | else if (arr[0][j] == timestampColumn) {
29 | eve["ocel:timestamp"] = new Date(arr[i][j]);
30 | }
31 | else if (objectTypes.includes(arr[0][j])) {
32 | if (arr[i][j].length >= 2) {
33 | let objArr0 = arr[i][j].substring(1, arr[i][j].length-1);
34 | let objArr = null;
35 | if (separators.length > 0) {
36 | objArr = [];
37 | let z = 0;
38 | let reading = false;
39 | let currRead = null;
40 | while (z < objArr0.length) {
41 | if (separators.includes(objArr0[z])) {
42 | if (reading) {
43 | objArr.push(currRead);
44 | }
45 | reading = !reading;
46 | currRead = null;
47 | currRead = "";
48 | }
49 | else if (reading) {
50 | currRead += objArr0[z];
51 | }
52 | z++;
53 | }
54 | }
55 | else {
56 | objArr = objArr0.split(",");
57 | if (objArr.length == 1 && objArr[0].length == 0) {
58 | objArr = [];
59 | }
60 | }
61 | for (let objId of objArr) {
62 | eve["ocel:omap"].push(objId);
63 | if (!(objId in ocel["ocel:objects"])) {
64 | ocel["ocel:objects"][objId] = {"ocel:type": arr[0][j], "ocel:ovmap": {}};
65 | }
66 | }
67 | }
68 | }
69 | else if (attNames.includes(arr[0][j])) {
70 | eve["ocel:vmap"][arr[0][j]] = arr[i][j];
71 | }
72 | j++;
73 | }
74 | ocel["ocel:events"][evId] = eve;
75 | i++;
76 | }
77 | return ocel;
78 | }
79 | }
80 |
81 |
82 | CsvOcelImporter.DEFAULT_SEPARATOR = ',';
83 | CsvOcelImporter.DEFAULT_QUOTECHAR = '"';
84 |
85 | try {
86 | module.exports = {CsvOcelImporter: CsvOcelImporter};
87 | global.CsvOcelImporter = CsvOcelImporter;
88 | }
89 | catch (err) {
90 | // not in node
91 | //console.log(err);
92 | }
93 |
--------------------------------------------------------------------------------
/pm4js/objects/ocel/importer/json2/importer.js:
--------------------------------------------------------------------------------
1 | class JsonOcel2Importer {
2 | static apply(jsonString) {
3 | let jsonObj = JSON.parse(jsonString);
4 |
5 | let legacyObj = {};
6 | legacyObj["ocel:events"] = {};
7 | legacyObj["ocel:objects"] = {};
8 | legacyObj["ocel:objectChanges"] = [];
9 | legacyObj["ocel:global-log"] = {};
10 | legacyObj["ocel:global-event"] = {};
11 | legacyObj["ocel:global-object"] = {};
12 |
13 | let objectTypes = {};
14 | let attributeNames = {};
15 |
16 |
17 | for (let eve of jsonObj["events"]) {
18 | let dct = {};
19 | dct["ocel:activity"] = eve["type"];
20 | dct["ocel:timestamp"] = new Date(eve["time"]);
21 | dct["ocel:vmap"] = {};
22 | if ("attributes" in eve) {
23 | if (eve["attributes"].length > 0) {
24 | for (let v of eve["attributes"]) {
25 | dct["ocel:vmap"][v["name"]] = v["value"];
26 |
27 | attributeNames[v["name"]] = 0;
28 | }
29 | }
30 | }
31 | dct["ocel:typedOmap"] = [];
32 | dct["ocel:omap"] = [];
33 | if ("relationships" in eve) {
34 | if (eve["relationships"].length > 0) {
35 | for (let v of eve["relationships"]) {
36 | dct["ocel:typedOmap"].push({"ocel:oid": v["objectId"], "ocel:qualifier": v["qualifier"]});
37 | if (!(dct["ocel:omap"].includes(v["objectId"]))) {
38 | dct["ocel:omap"].push(v["objectId"]);
39 | }
40 | }
41 | }
42 | }
43 | legacyObj["ocel:events"][eve["id"]] = dct;
44 | }
45 |
46 | for (let obj of jsonObj["objects"]) {
47 | let dct = {};
48 | dct["ocel:type"] = obj["type"];
49 |
50 | objectTypes[obj["type"]] = 0;
51 |
52 | dct["ocel:ovmap"] = {};
53 | if ("attributes" in obj) {
54 | if (obj["attributes"].length > 0) {
55 | for (let x of obj["attributes"]) {
56 | attributeNames[x["name"]] = 0;
57 |
58 | if (x["name"] in dct["ocel:ovmap"]) {
59 | legacyObj["ocel:objectChanges"].push({"ocel:oid": obj["id"], "ocel:type": obj["type"], "ocel:name": x["name"], "ocel:value": x["value"], "ocel:timestamp": new Date(x["time"])});
60 | }
61 | else {
62 | dct["ocel:ovmap"][x["name"]] = x["value"];
63 | }
64 | }
65 | }
66 | }
67 | dct["ocel:o2o"] = [];
68 | if ("relationships" in obj) {
69 | if (obj["relationships"].length > 0) {
70 | for (let x of obj["relationships"]) {
71 | dct["ocel:o2o"].push({"ocel:oid": x["objectId"], "ocel:qualifier": x["qualifier"]});
72 | }
73 | }
74 | }
75 | legacyObj["ocel:objects"][obj["id"]] = dct;
76 | }
77 |
78 | legacyObj["ocel:global-log"]["ocel:object-types"] = Object.keys(objectTypes);
79 | legacyObj["ocel:global-log"]["ocel:attribute-names"] = Object.keys(attributeNames);
80 |
81 | legacyObj = Ocel20FormatFixer.apply(legacyObj);
82 |
83 | return legacyObj;
84 | }
85 | }
86 |
87 | try {
88 | module.exports = {JsonOcel2Importer: JsonOcel2Importer};
89 | global.JsonOcel2Importer = JsonOcel2Importer;
90 | }
91 | catch (err) {
92 | // not in node
93 | //console.log(err);
94 | }
95 |
--------------------------------------------------------------------------------
/pm4js/objects/ocel/importer/jsonocel/importer.js:
--------------------------------------------------------------------------------
1 | class JsonOcelImporter {
2 | static apply(jsonString) {
3 | return JsonOcelImporter.importLog(jsonString);
4 | }
5 |
6 | static importLog(jsonString) {
7 | let ret = JSON.parse(jsonString);
8 | if ("ocel:objects" in ret) {
9 | // OCEL 1.0 specification
10 | for (let evId in ret["ocel:events"]) {
11 | ret["ocel:events"][evId]["ocel:timestamp"] = new Date(ret["ocel:events"][evId]["ocel:timestamp"]);
12 | }
13 | ret = Ocel20FormatFixer.apply(ret);
14 | return ret;
15 | }
16 | else {
17 | return JsonOcel2Importer.apply(jsonString);
18 | }
19 | }
20 | }
21 |
22 | try {
23 | module.exports = {JsonOcelImporter: JsonOcelImporter};
24 | global.JsonOcelImporter = JsonOcelImporter;
25 | }
26 | catch (err) {
27 | // not in node
28 | //console.log(err);
29 | }
30 |
--------------------------------------------------------------------------------
/pm4js/objects/ocel/util/flattening.js:
--------------------------------------------------------------------------------
1 | class OcelFlattening {
2 | static apply(ocel, objType, caseIdKey="concept:name", activityKey="concept:name", timestampKey="time:timestamp") {
3 | return OcelFlattening.flatten(ocel, objType, caseIdKey, activityKey, timestampKey);
4 | }
5 |
6 | static flatten(ocel, objType, caseIdKey="concept:name", activityKey="concept:name", timestampKey="time:timestamp") {
7 | let log = new EventLog();
8 | let objTraces = {};
9 | for (let eveId in ocel["ocel:events"]) {
10 | let eve = ocel["ocel:events"][eveId];
11 | for (let objId of eve["ocel:omap"]) {
12 | let obj = ocel["ocel:objects"][objId];
13 | if (obj["ocel:type"] == objType) {
14 | let trace = null;
15 | if (!(objId in objTraces)) {
16 | trace = new Trace();
17 | trace.attributes[caseIdKey] = new Attribute(objId);
18 | log.traces.push(trace);
19 | objTraces[objId] = trace;
20 | }
21 | else {
22 | trace = objTraces[objId];
23 | }
24 | let xesEve = new Event();
25 | trace.events.push(xesEve);
26 | xesEve.attributes[activityKey] = new Attribute(eve["ocel:activity"]);
27 | xesEve.attributes[timestampKey] = new Attribute(new Date(eve["ocel:timestamp"]));
28 | for (let attr in eve["ocel:vmap"]) {
29 | xesEve.attributes[attr] = new Attribute(eve["ocel:vmap"][attr]);
30 | }
31 | }
32 | }
33 | }
34 | return log;
35 | }
36 | }
37 |
38 | try {
39 | module.exports = {OcelFlattening: OcelFlattening};
40 | global.OcelFlattening = OcelFlattening;
41 | }
42 | catch (err) {
43 | // not in node
44 | //console.log(err);
45 | }
46 |
--------------------------------------------------------------------------------
/pm4js/objects/ocel/util/ocel20_fixer.js:
--------------------------------------------------------------------------------
1 | class Ocel20FormatFixer {
2 | static apply(ocel) {
3 | if (!("ocel:objectChanges" in ocel)) {
4 | ocel["ocel:objectChanges"] = [];
5 | }
6 | for (let evId in ocel["ocel:events"]) {
7 | let ev = ocel["ocel:events"][evId];
8 | let omapIdx = 0;
9 | while (omapIdx < ev["ocel:omap"].length) {
10 | let objId = ev["ocel:omap"][omapIdx];
11 | if (!(objId in ocel["ocel:objects"])) {
12 | ev["ocel:omap"].splice(omapIdx, 1);
13 | continue;
14 | }
15 | omapIdx++;
16 | }
17 | for (let idx in ev["ocel:omap"]) {
18 | let objId = ev["ocel:omap"][idx];
19 | if (!(objId in ocel["ocel:objects"])) {
20 | }
21 | }
22 | if (!("ocel:typedOmap" in ev)) {
23 | let typedOmap = [];
24 | for (let objId of ev["ocel:omap"]) {
25 | typedOmap.push({"ocel:oid": objId, "ocel:qualifier": "EMPTY"});
26 | }
27 | ev["ocel:typedOmap"] = typedOmap;
28 | }
29 | }
30 | for (let objId in ocel["ocel:objects"]) {
31 | let obj = ocel["ocel:objects"][objId];
32 | if (!("ocel:o2o" in obj)) {
33 | obj["ocel:o2o"] = [];
34 | }
35 | }
36 | if (!("ocel:objectTypes" in ocel)) {
37 | let objectTypes = {};
38 |
39 | for (let objId in ocel["ocel:objects"]) {
40 | let obj = ocel["ocel:objects"][objId];
41 | let type = obj["ocel:type"];
42 |
43 | if (!(type in objectTypes)) {
44 | objectTypes[type] = {};
45 | }
46 |
47 | for (let att in obj["ocel:ovmap"]) {
48 | let attValue = obj["ocel:ovmap"][att];
49 | let transf = Ocel20FormatFixer.transformAttValue(attValue);
50 | objectTypes[type][att] = transf[0];
51 | }
52 | }
53 |
54 | ocel["ocel:objectTypes"] = objectTypes;
55 | }
56 | if (!("ocel:eventTypes" in ocel)) {
57 | let eventTypes = {};
58 |
59 | for (let evId in ocel["ocel:events"]) {
60 | let eve = ocel["ocel:events"][evId];
61 | let type = eve["ocel:activity"];
62 |
63 | if (!(type in eventTypes)) {
64 | eventTypes[type] = {};
65 | }
66 |
67 | for (let att in eve["ocel:vmap"]) {
68 | let attValue = eve["ocel:vmap"][att];
69 | let transf = Ocel20FormatFixer.transformAttValue(attValue);
70 | eventTypes[type][att] = transf[0];
71 | }
72 |
73 |
74 | }
75 |
76 | ocel["ocel:eventTypes"] = eventTypes;
77 | }
78 | return ocel;
79 | }
80 |
81 | static transformAttValue(attValue) {
82 | let xmlTag = null;
83 | let value = null;
84 | if (typeof attValue == "string") {
85 | xmlTag = "string";
86 | value = attValue;
87 | }
88 | else if (typeof attValue == "object") {
89 | return "date";
90 | xmlTag = "date";
91 | value = attValue.toISOString();
92 | }
93 | else if (typeof attValue == "number") {
94 | xmlTag = "float";
95 | value = ""+attValue;
96 | }
97 | else {
98 | xmlTag = "string";
99 | value = attValue;
100 | }
101 | return [xmlTag, value];
102 | }
103 | }
104 |
105 | try {
106 | module.exports = {Ocel20FormatFixer: Ocel20FormatFixer};
107 | global.Ocel20FormatFixer = Ocel20FormatFixer;
108 | }
109 | catch (err) {
110 | // not in node
111 | //console.log(err);
112 | }
113 |
--------------------------------------------------------------------------------
/pm4js/objects/ocel/util/parent_children.js:
--------------------------------------------------------------------------------
1 | class OcelParentChildrenAttribute {
2 | static apply(ocel, childOt, parentOt) {
3 | let objTypes = {};
4 | for (let objId in ocel["ocel:objects"]) {
5 | let obj = ocel["ocel:objects"][objId];
6 | objTypes[objId] = obj["ocel:type"];
7 | }
8 | let parents = {};
9 | for (let evId in ocel["ocel:events"]) {
10 | let eve = ocel["ocel:events"][evId];
11 | for (let objId of eve["ocel:omap"]) {
12 | if (objTypes[objId] == childOt) {
13 | for (let objId2 of eve["ocel:omap"]) {
14 | if (objTypes[objId2] == parentOt) {
15 | parents[objId] = objId2;
16 | }
17 | }
18 | }
19 | }
20 | }
21 |
22 | for (let childId in parents) {
23 | ocel["ocel:objects"][childId]["ocel:ovmap"][parentOt+"ID"] = parents[childId];
24 | }
25 | return ocel;
26 | }
27 | }
28 |
29 | try {
30 | module.exports = {OcelParentChildrenAttribute: OcelParentChildrenAttribute};
31 | global.OcelParentChildrenAttribute = OcelParentChildrenAttribute;
32 | }
33 | catch (err) {
34 | // not in node
35 | //console.log(err);
36 | }
37 |
--------------------------------------------------------------------------------
/pm4js/objects/petri_net/util/reachable_visible_transitions.js:
--------------------------------------------------------------------------------
1 | class PetriNetReachableVisibleTransitions {
2 | static apply(net, marking) {
3 | let reachableVisibleTransitions = {};
4 | let visited = {};
5 | let toVisit = [];
6 | toVisit.push(marking);
7 | while (toVisit.length > 0) {
8 | //console.log(reachableVisibleTransitions);
9 | let currMarking = toVisit.shift();
10 | if (currMarking in visited) {
11 | continue;
12 | }
13 | visited[currMarking] = 0;
14 | let enabledTransitions = currMarking.getEnabledTransitions();
15 | for (let trans of enabledTransitions) {
16 | if (trans.label != null) {
17 | reachableVisibleTransitions[trans.label] = 0;
18 | }
19 | else {
20 | let newMarking = currMarking.execute(trans);
21 | if (!(newMarking in visited)) {
22 | toVisit.push(newMarking);
23 | }
24 | }
25 | }
26 | }
27 | return Object.keys(reachableVisibleTransitions);
28 | }
29 | }
30 |
31 | try {
32 | module.exports = {PetriNetReachableVisibleTransitions: PetriNetReachableVisibleTransitions};
33 | global.PetriNetReachableVisibleTransitions = PetriNetReachableVisibleTransitions;
34 | }
35 | catch (err) {
36 | //console.log(err);
37 | // not in Node
38 | }
39 |
--------------------------------------------------------------------------------
/pm4js/objects/petri_net/util/reduction.js:
--------------------------------------------------------------------------------
1 | class PetriNetReduction {
2 | static apply(acceptingPetriNet, asPlugin=true) {
3 | PetriNetReduction.reduceSingleEntryTransitions(acceptingPetriNet.net);
4 | PetriNetReduction.reduceSingleExitTransitions(acceptingPetriNet.net);
5 | if (asPlugin) {
6 | Pm4JS.registerObject(acceptingPetriNet, "Accepting Petri Net (reduced)");
7 | }
8 | return acceptingPetriNet;
9 | }
10 |
11 | static reduceSingleEntryTransitions(net) {
12 | let cont = true;
13 | while (cont) {
14 | cont = false;
15 | let singleEntryInvisibleTransitions = [];
16 | for (let transId in net.transitions) {
17 | let trans = net.transitions[transId];
18 | if (trans.label == null && Object.keys(trans.inArcs).length == 1) {
19 | singleEntryInvisibleTransitions.push(trans);
20 | }
21 | }
22 | for (let trans of singleEntryInvisibleTransitions) {
23 | let sourcePlace = null;
24 | let targetPlaces = [];
25 | for (let arcId in trans.inArcs) {
26 | let arc = trans.inArcs[arcId];
27 | sourcePlace = arc.source;
28 | }
29 | for (let arcId in trans.outArcs) {
30 | let arc = trans.outArcs[arcId];
31 | targetPlaces.push(arc.target);
32 | }
33 | if (Object.keys(sourcePlace.inArcs).length == 1 && Object.keys(sourcePlace.outArcs).length == 1) {
34 | //if (Object.keys(sourcePlace.inArcs).length > 0 && Object.keys(sourcePlace.outArcs).length == 1) {
35 | for (let arcId in sourcePlace.inArcs) {
36 | let sourceTransition = sourcePlace.inArcs[arcId].source;
37 | for (let p of targetPlaces) {
38 | net.addArcFromTo(sourceTransition, p);
39 | }
40 | }
41 | net.removeTransition(trans);
42 | net.removePlace(sourcePlace);
43 | cont = true;
44 | break;
45 | }
46 | }
47 | }
48 | }
49 |
50 | static reduceSingleExitTransitions(net) {
51 | let cont = true;
52 | while (cont) {
53 | cont = false;
54 | let singleExitInvisibleTransitions = [];
55 | for (let transId in net.transitions) {
56 | let trans = net.transitions[transId];
57 | if (trans.label == null && Object.keys(trans.outArcs).length == 1) {
58 | singleExitInvisibleTransitions.push(trans);
59 | }
60 | }
61 | for (let trans of singleExitInvisibleTransitions) {
62 | let targetPlace = null;
63 | let sourcePlaces = [];
64 | for (let arcId in trans.outArcs) {
65 | let arc = trans.outArcs[arcId];
66 | targetPlace = arc.target;
67 | }
68 | for (let arcId in trans.inArcs) {
69 | let arc = trans.inArcs[arcId];
70 | sourcePlaces.push(arc.source);
71 | }
72 | if (Object.keys(targetPlace.inArcs).length == 1 && Object.keys(targetPlace.outArcs).length == 1) {
73 | //if (Object.keys(targetPlace.inArcs).length == 1 && Object.keys(targetPlace.outArcs).length > 0) {
74 | for (let arcId in targetPlace.outArcs) {
75 | let targetTransition = targetPlace.outArcs[arcId].target;
76 | for (let p of sourcePlaces) {
77 | net.addArcFromTo(p, targetTransition);
78 | }
79 | }
80 | net.removeTransition(trans);
81 | net.removePlace(targetPlace);
82 | cont = true;
83 | break;
84 | }
85 | }
86 | }
87 | }
88 | }
89 |
90 | try {
91 | module.exports = {PetriNetReduction: PetriNetReduction};
92 | global.PetriNetReduction = PetriNetReduction;
93 | }
94 | catch (err) {
95 | //console.log(err);
96 | // not in Node
97 | }
98 |
99 | Pm4JS.registerAlgorithm("PetriNetReduction", "apply", ["AcceptingPetriNet"], "AcceptingPetriNet", "SESE Reduction of Accepting Petri Net", "Alessandro Berti");
100 |
--------------------------------------------------------------------------------
/pm4js/objects/process_tree/importer/importer.js:
--------------------------------------------------------------------------------
1 | class PtmlImporter {
2 | static apply(xmlString) {
3 | let parser = new DOMParser();
4 | var xmlDoc = parser.parseFromString(xmlString, "text/xml");
5 | let xmlPtml = xmlDoc.getElementsByTagName("ptml")[0];
6 | var xmlProcessTree = xmlPtml.getElementsByTagName("processTree")[0];
7 | let processTree = PtmlImporter.importFromXml(xmlProcessTree);
8 | Pm4JS.registerObject(processTree, "Process Tree imported from a PTML file");
9 | return processTree;
10 | }
11 |
12 | static importFromXml(xmlProcessTree) {
13 | let nodes = {};
14 | for (let childId in xmlProcessTree.childNodes) {
15 | let child = xmlProcessTree.childNodes[childId];
16 | if (child.tagName != null) {
17 | let elId = child.getAttribute("id");
18 | let elLabel = child.getAttribute("name");
19 | let elOperator = null;
20 | if (child.tagName == "and") {
21 | elOperator = ProcessTreeOperator.PARALLEL;
22 | elLabel = null;
23 | }
24 | else if (child.tagName == "xorLoop") {
25 | elOperator = ProcessTreeOperator.LOOP;
26 | elLabel = null;
27 | }
28 | else if (child.tagName == "sequence") {
29 | elOperator = ProcessTreeOperator.SEQUENCE;
30 | elLabel = null;
31 | }
32 | else if (child.tagName == "or") {
33 | elOperator = ProcessTreeOperator.INCLUSIVE;
34 | elLabel = null;
35 | }
36 | else if (child.tagName == "xor") {
37 | elOperator = ProcessTreeOperator.EXCLUSIVE;
38 | elLabel = null;
39 | }
40 | else if (child.tagName == "automaticTask") {
41 | elLabel = null;
42 | }
43 |
44 | if (child.tagName != "parentsNode") {
45 | let tree = new ProcessTree(null, elOperator, elLabel);
46 | nodes[elId] = tree;
47 | }
48 | else {
49 | let sourceId = child.getAttribute("sourceId");
50 | let targetId = child.getAttribute("targetId");
51 | nodes[targetId].parentNode = nodes[sourceId];
52 | nodes[sourceId].children.push(nodes[targetId]);
53 | }
54 | }
55 | }
56 | for (let nodeId in nodes) {
57 | let node = nodes[nodeId];
58 | if (node.parentNode == null) {
59 | return node;
60 | }
61 | }
62 | }
63 | }
64 |
65 | try {
66 | module.exports = {PtmlImporter: PtmlImporter};
67 | global.PtmlImporter = PtmlImporter;
68 | global.DOMParser = require('xmldom').DOMParser;
69 | }
70 | catch (err) {
71 | // not in Node
72 | //console.log(err);
73 | }
74 |
75 | Pm4JS.registerImporter("PtmlImporter", "apply", ["ptml"], "PTML Importer", "Alessandro Berti");
76 |
--------------------------------------------------------------------------------
/pm4js/objects/process_tree/process_tree.js:
--------------------------------------------------------------------------------
1 | class ProcessTreeOperator {
2 | }
3 |
4 | ProcessTreeOperator.SEQUENCE = "sequence";
5 | ProcessTreeOperator.PARALLEL = "and";
6 | ProcessTreeOperator.INCLUSIVE = "or";
7 | ProcessTreeOperator.EXCLUSIVE = "xor";
8 | ProcessTreeOperator.LOOP = "xorLoop";
9 |
10 | class ProcessTree {
11 | static uuidv4() {
12 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
13 | var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
14 | return v.toString(16);
15 | });
16 | }
17 |
18 | constructor(parentNode, operator, label) {
19 | this.parentNode = parentNode;
20 | this.operator = operator;
21 | this.label = label;
22 | this.id = ProcessTree.uuidv4();
23 | this.children = [];
24 | this.properties = {};
25 | }
26 |
27 | toString() {
28 | if (this.operator == null) {
29 | if (this.label == null) {
30 | return "tau";
31 | }
32 | else {
33 | return "'"+this.label+"'";
34 | }
35 | }
36 | else {
37 | let opMapping = {};
38 | opMapping[ProcessTreeOperator.SEQUENCE] = "->";
39 | opMapping[ProcessTreeOperator.PARALLEL] = "+";
40 | opMapping[ProcessTreeOperator.INCLUSIVE] = "O";
41 | opMapping[ProcessTreeOperator.EXCLUSIVE] = "X";
42 | opMapping[ProcessTreeOperator.LOOP] = "*";
43 | let childRepr = [];
44 | for (let n of this.children) {
45 | childRepr.push(n.toString());
46 | }
47 | return opMapping[this.operator] + " ( " + childRepr.join(', ') + " ) ";
48 | }
49 | }
50 | }
51 |
52 | try {
53 | module.exports = { ProcessTree: ProcessTree, ProcessTreeOperator: ProcessTreeOperator };
54 | global.ProcessTree = ProcessTree;
55 | global.ProcessTreeOperator = ProcessTreeOperator;
56 | }
57 | catch (err) {
58 | // not in Node
59 | //console.log(err);
60 | }
61 |
--------------------------------------------------------------------------------
/pm4js/objects/skeleton/log_skeleton.js:
--------------------------------------------------------------------------------
1 | class LogSkeleton {
2 | constructor(equivalence, neverTogether, alwaysAfter, alwaysBefore, directlyFollows, actCounter) {
3 | this.equivalence = equivalence;
4 | this.neverTogether = neverTogether;
5 | this.alwaysAfter = alwaysAfter;
6 | this.alwaysBefore = alwaysBefore;
7 | this.directlyFollows = directlyFollows;
8 | this.actCounter = actCounter;
9 | }
10 |
11 | filterOnNoiseThreshold(thresh) {
12 | thresh = 1.0 - thresh;
13 | let newEquivalence = {};
14 | let newNeverTogether = {};
15 | let newAlwaysAfter = {};
16 | let newAlwaysBefore = {};
17 | let newDirectlyFollows = {};
18 | let newActCounter = {};
19 | for (let cou in this.equivalence) {
20 | if (this.equivalence[cou] >= thresh) {
21 | newEquivalence[cou] = this.equivalence[cou];
22 | }
23 | }
24 | for (let cou in this.neverTogether) {
25 | if (this.neverTogether[cou] >= thresh) {
26 | newNeverTogether[cou] = this.neverTogether[cou];
27 | }
28 | }
29 | for (let cou in this.alwaysAfter) {
30 | if (this.alwaysAfter[cou] >= thresh) {
31 | newAlwaysAfter[cou] = this.alwaysAfter[cou];
32 | }
33 | }
34 | for (let cou in this.alwaysBefore) {
35 | if (this.alwaysBefore[cou] >= thresh) {
36 | newAlwaysBefore[cou] = this.alwaysBefore[cou];
37 | }
38 | }
39 | for (let cou in this.directlyFollows) {
40 | if (this.directlyFollows[cou] >= thresh) {
41 | newDirectlyFollows[cou] = this.directlyFollows[cou];
42 | }
43 | }
44 | for (let act in this.actCounter) {
45 | for (let actocc in this.actCounter[act]) {
46 | if (this.actCounter[act][actocc] >= thresh) {
47 | if (!(act in newActCounter)) {
48 | newActCounter[act] = {};
49 | }
50 | newActCounter[act][actocc] = this.actCounter[act][actocc];
51 | }
52 | }
53 | }
54 | return new LogSkeleton(newEquivalence, newNeverTogether, newAlwaysAfter, newAlwaysBefore, newDirectlyFollows, newActCounter);
55 | }
56 | }
57 |
58 | try {
59 | module.exports = { LogSkeleton: LogSkeleton };
60 | global.LogSkeleton = LogSkeleton;
61 | }
62 | catch (err) {
63 | // not in Node
64 | //console.log(err);
65 | }
--------------------------------------------------------------------------------
/pm4js/utils/browser/download.js:
--------------------------------------------------------------------------------
1 | class DownloadUtility {
2 | static download(text, name, type) {
3 | var a = document.createElement("a");
4 | var file = new Blob([text], {type: type});
5 | a.href = URL.createObjectURL(file);
6 | a.download = name;
7 | a.click();
8 | }
9 | }
--------------------------------------------------------------------------------
/pm4js/utils/celonis/celonis_proxy.php:
--------------------------------------------------------------------------------
1 |
2 | $authHeader = 'Authorization: Bearer '.$_GET["access_token"];
3 | $headers = array(
4 | $authHeader
5 | );
6 | $url = $_GET["url"];
7 | $ch = curl_init($url);
8 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
9 | $data = curl_exec($ch);
10 | curl_close($ch);
11 | ?>
--------------------------------------------------------------------------------
/pm4js/utils/celonis/celonis_proxy.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from flask import Flask, request
3 | from flask_cors import CORS
4 |
5 | app = Flask(__name__)
6 | CORS(app)
7 |
8 |
9 | @app.route('/getWrapper', methods=['GET'])
10 | def get_wrapper():
11 | return requests.get(request.args["url"], headers={"Authorization": "Bearer " + request.args["access_token"]}).text
12 |
13 |
14 | @app.route('/postWrapper', methods=['POST'])
15 | def post_wrapper():
16 | call_contents = request.get_json()
17 | url = call_contents["url"]
18 | access_token = call_contents["access_token"]
19 | files = {}
20 | if "files" in call_contents:
21 | content = call_contents["files"]
22 | content = content.encode("utf-8")
23 | del call_contents["files"]
24 | files["file"] = content
25 | if "@@content" in call_contents:
26 | call_contents = call_contents["@@content"]
27 | return requests.post(url, headers={"Authorization": "Bearer " + access_token},
28 | files=files, json=call_contents).text
29 |
30 |
31 | @app.route('/putWrapper', methods=['POST'])
32 | def put_wrapper():
33 | call_contents = request.get_json()
34 | url = call_contents["url"]
35 | access_token = call_contents["access_token"]
36 | return requests.put(url, headers={"Authorization": "Bearer " + access_token},
37 | json=call_contents).text
38 |
39 |
40 | USE_SSL = False
41 | if __name__ == "__main__":
42 | if USE_SSL:
43 | app.run(threaded=True, port=5004, host="0.0.0.0", ssl_context=('local.crt', 'local.key'))
44 | else:
45 | app.run(threaded=True, port=5004, host="0.0.0.0")
46 |
--------------------------------------------------------------------------------
/pm4js/utils/celonis/celonis_proxy_post.php:
--------------------------------------------------------------------------------
1 |
2 | $_POST = json_decode(file_get_contents('php://input'), true);
3 | $authHeader = 'Authorization: Bearer '.$_POST["access_token"];
4 | $headers = array(
5 | $authHeader,
6 | "Content-type: application/json"
7 | );
8 | $url = $_POST["url"];
9 |
10 | $ch = curl_init($url);
11 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
12 | curl_setopt($ch, CURLOPT_POST, true);
13 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($_POST));
14 | $data = curl_exec($ch);
15 | curl_close($ch);
16 | ?>
--------------------------------------------------------------------------------
/pm4js/utils/celonis/celonis_proxy_put.php:
--------------------------------------------------------------------------------
1 |
2 | $_POST = json_decode(file_get_contents('php://input'), true);
3 | $authHeader = 'Authorization: Bearer '.$_POST["access_token"];
4 | $headers = array(
5 | $authHeader,
6 | "Content-type: application/json"
7 | );
8 | $url = $_POST["url"];
9 |
10 | $ch = curl_init($url);
11 | curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
12 | curl_setopt($ch, CURLOPT_PUT, true);
13 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($_POST));
14 | $data = curl_exec($ch);
15 | curl_close($ch);
16 | ?>
17 |
--------------------------------------------------------------------------------
/pm4js/utils/generic/business_hours.js:
--------------------------------------------------------------------------------
1 | class BusinessHours {
2 | static apply(startDate, endDate, workingHours=null, weekends=null) {
3 | if (workingHours == null) {
4 | workingHours = BusinessHours.DEFAULT_WORKING_HOURS;
5 | }
6 |
7 | if (weekends == null) {
8 | weekends = BusinessHours.DEFAULT_WEEKENDS;
9 | }
10 |
11 | // Store minutes worked
12 | var minutesWorked = 0;
13 |
14 | // Validate input
15 | if (endDate < startDate) { return 0; }
16 |
17 | // Loop from your Start to End dates (by hour)
18 | var current = startDate;
19 |
20 | // Loop while currentDate is less than end Date (by minutes)
21 | while(current < endDate){
22 | // Is the current time within a work day (and if it occurs on a weekend or not)
23 | if(current.getHours() >= workingHours[0] && current.getHours() <= workingHours[1]
24 | && !(weekends.includes(current.getDay()))) {
25 | minutesWorked++;
26 | }
27 |
28 | // Increment current time
29 | current.setTime(current.getTime() + 1000 * 60);
30 | }
31 |
32 | // Return the number of seconds
33 | return minutesWorked * 60;
34 | }
35 | }
36 |
37 | BusinessHours.DEFAULT_WORKING_HOURS = [7, 17];
38 | BusinessHours.DEFAULT_WEEKENDS = [0, 6];
39 | BusinessHours.ENABLED = false;
40 |
41 | try {
42 | global.BusinessHours = BusinessHours;
43 | module.exports = {BusinessHours: BusinessHours};
44 | }
45 | catch (err) {
46 | // not in Node
47 | //console.log(err);
48 | }
49 |
--------------------------------------------------------------------------------
/pm4js/utils/generic/dates.js:
--------------------------------------------------------------------------------
1 | class DateUtils {
2 | static formatDateString(d) {
3 | return ("0" + d.getDate()).slice(-2) + "-" + ("0"+(d.getMonth()+1)).slice(-2) + "-" + d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2)+ ":" + ("0" + d.getSeconds()).slice(-2);
4 | }
5 | }
6 |
7 | try {
8 | module.exports = {DateUtils: DateUtils};
9 | global.DateUtils = DateUtils;
10 | }
11 | catch (err) {
12 | // not in node
13 | //console.log(err);
14 | }
15 |
--------------------------------------------------------------------------------
/pm4js/utils/generic/stats-utils.js:
--------------------------------------------------------------------------------
1 | class StatisticsUtils {
2 | static average(x) {
3 | if (x.length > 0) {
4 | let ret = 0.0;
5 | for (let el of x) {
6 | ret += el;
7 | }
8 | return ret / x.length;
9 | }
10 | return 0.0;
11 | }
12 |
13 | static stddev(x) {
14 | let avg = StatisticsUtils.average(x);
15 | if (x.length > 0) {
16 | let ret = 0.0;
17 | for (let el of x) {
18 | ret += (el - avg)*(el-avg);
19 | }
20 | ret = ret / x.length;
21 | ret = Math.sqrt(ret);
22 | return ret;
23 | }
24 | return 0.0;
25 | }
26 |
27 | static covariance(x, y) {
28 | if (x.length != y.length) {
29 | throw "Incompatible dimensions";
30 | }
31 | else if (x.length > 0) {
32 | let avgX = StatisticsUtils.average(x);
33 | let avgY = StatisticsUtils.average(y);
34 | let ret = 0.0;
35 | let i = 0;
36 | while (i < x.length) {
37 | ret += (x[i] - avgX) * (y[i] - avgY);
38 | i = i + 1;
39 | }
40 | ret = ret / x.length;
41 | return ret;
42 | }
43 | return 0.0;
44 | }
45 |
46 | static pearsonCorrelation(x, y) {
47 | return StatisticsUtils.covariance(x, y) / (StatisticsUtils.stddev(x) * StatisticsUtils.stddev(y));
48 | }
49 | }
50 |
51 | try {
52 | module.exports = {StatisticsUtils: StatisticsUtils};
53 | global.StatisticsUtils = StatisticsUtils;
54 | }
55 | catch (err) {
56 | // not in node
57 | //console.log(err);
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/pm4js/utils/ml/rules.js:
--------------------------------------------------------------------------------
1 | class MlRules {
2 | static dataRandomClassification(data) {
3 | let classification = [];
4 | let i = 0;
5 | while (i < data.length) {
6 | let r = Math.random();
7 | if (r <= 0.5) {
8 | classification.push(1);
9 | }
10 | else {
11 | classification.push(-1);
12 | }
13 | i++;
14 | }
15 | return classification;
16 | }
17 |
18 | static extractRangePerFeature(data, j, classification) {
19 | let minRange = 9999999;
20 | let maxRange = -9999999;
21 | let i = 0;
22 | while (i < data.length) {
23 | if (classification[i] == 1) {
24 | minRange = Math.min(minRange, data[i][j]);
25 | maxRange = Math.max(maxRange, data[i][j]);
26 | }
27 | i++;
28 | }
29 | return [minRange, maxRange];
30 | }
31 |
32 | static ruleDiscovery(data, featureNames, classification) {
33 | let ret = {};
34 | let j = 0;
35 | while (j < featureNames.length) {
36 | let ranges = MlRules.extractRangePerFeature(data, j, classification);
37 | ret[featureNames[j]] = ranges;
38 | j++;
39 | }
40 | return ret;
41 | }
42 |
43 | static ruleClassificationScore(rules, data, features, classification) {
44 | let ret = {};
45 | let j = 0;
46 | while (j < features.length) {
47 | let feature = features[j];
48 | let ranges = rules[feature];
49 | let i = 0;
50 | let devCount = 0;
51 | let devDetectedCount = 0;
52 | while (i < data.length) {
53 | if (classification[i] == -1) {
54 | devCount++;
55 | if (data[i][j] < ranges[0] || data[i][j] > ranges[1]) {
56 | devDetectedCount++;
57 | }
58 | }
59 | i++;
60 | }
61 | ret[feature] = 0;
62 | if (devCount > 0) {
63 | ret[feature] = devDetectedCount / devCount;
64 | }
65 | j++;
66 | }
67 | return ret;
68 | }
69 |
70 | static getClassificationFromRule(rules, data, features, feature) {
71 | let ret = [];
72 | let j = features.indexOf(feature);
73 | let ranges = rules[feature];
74 | let i = 0;
75 | while (i < data.length) {
76 | if (data[i][j] < ranges[0] || data[i][j] > ranges[1]) {
77 | ret.push(-1);
78 | }
79 | else {
80 | ret.push(1);
81 | }
82 | i++;
83 | }
84 | return ret;
85 | }
86 | }
87 |
88 | try {
89 | module.exports = {MlRules: MlRules};
90 | global.MlRules = MlRules;
91 | }
92 | catch (err) {
93 | // not in node
94 | }
95 |
--------------------------------------------------------------------------------
/pm4js/utils/random_variables/exp_mod_gaussian.js:
--------------------------------------------------------------------------------
1 | class ExponentiallyModifiedGaussian {
2 | constructor(mu, sig, lam) {
3 | this.mu = mu;
4 | this.sig = sig;
5 | this.lam = lam;
6 | }
7 |
8 | toString() {
9 | return "ExponentiallyModifiedGaussian mu="+this.mu+" sig="+this.sig+" lam="+this.lam;
10 | }
11 |
12 | static erf(x) {
13 | let v = 1;
14 | v = v + 0.278393*x;
15 | let y = x * x;
16 | v = v + 0.230389*y;
17 | y = y * x;
18 | v = v + 0.000972*y;
19 | y = y * x;
20 | v = v + 0.078108*y;
21 | v = v * v;
22 | v = v * v;
23 | v = 1.0 / v;
24 | v = 1.0 - v;
25 | return v;
26 | }
27 |
28 | static estimateParameters(arrayValues) {
29 | let n = arrayValues.length;
30 | let mu = 0.0;
31 | for (let v of arrayValues) {
32 | mu += v;
33 | }
34 | mu = mu / n;
35 | let std = 0.0;
36 | for (let v of arrayValues) {
37 | std += (v - mu) * (v - mu);
38 | }
39 | std = std / n;
40 | std = Math.sqrt(std);
41 | let skew = 0.0;
42 | for (let v of arrayValues) {
43 | skew += v * v * v;
44 | }
45 | skew = skew / n;
46 | skew = (skew - 3 * mu * std * std - mu * mu * mu) / (std * std * std);
47 | let muDist = mu - std * Math.pow(Math.abs(skew) / 2.0, 2.0 / 3.0);
48 | let stdDist = Math.sqrt(std * std * (1 - Math.pow((Math.abs(skew) / 2.0), 2.0 / 3.0)));
49 | let tauDist = std * Math.pow((Math.abs(skew) / 2), 1.0 / 3.0);
50 | return new ExponentiallyModifiedGaussian(muDist, stdDist, 1.0 / tauDist);
51 | }
52 |
53 | getMean() {
54 | return this.mu + 1.0 / this.lam;
55 | }
56 |
57 | getVariance() {
58 | return this.sig * this.sig + 1.0 / (this.lam * this.lam);
59 | }
60 |
61 | pdf(x) {
62 | return this.lam / 2.0 * Math.exp(this.lam / 2.0 * (2 * this.mu + this.lam * this.sig * this.sig - 2*x)) * (1 - ExponentiallyModifiedGaussian.erf((this.mu + this.lam * this.sig * this.sig - x)/(Math.sqrt(2) * this.sig)));
63 | }
64 |
65 | cdf(x) {
66 | let u = this.lam * (x - this.mu);
67 | let v = this.lam * this.sig;
68 | let rv1 = new NormalRandomVariable(0, v);
69 | let rv2 = new NormalRandomVariable(v*v, v);
70 | return rv1.cdf(u) - Math.exp(-(u + v*v)/(2 + Math.log(rv2.cdf(u))));
71 | }
72 |
73 | logLikelihood(arrayValues) {
74 | let ret = 0.0;
75 | for (let v of arrayValues) {
76 | ret += Math.log(this.pdf(v));
77 | }
78 | return ret;
79 | }
80 |
81 | getValue() {
82 | let rv1 = new NormalRandomVariable(this.mu, this.sig);
83 | let rv2 = new ExponentialRandomVariable(this.lam);
84 | return rv1.getValue() + rv2.getValue();
85 | }
86 | }
87 |
88 | try {
89 | global.ExponentiallyModifiedGaussian = ExponentiallyModifiedGaussian;
90 | module.exports = {ExponentiallyModifiedGaussian: ExponentiallyModifiedGaussian};
91 | }
92 | catch (err) {
93 | // not in Node
94 | //console.log(err);
95 | }
96 |
97 |
--------------------------------------------------------------------------------
/pm4js/utils/random_variables/expon.js:
--------------------------------------------------------------------------------
1 | class ExponentialRandomVariable {
2 | constructor(lam) {
3 | this.lam = lam;
4 | }
5 |
6 | toString() {
7 | return "ExponentialRandomVariable lam="+this.lam;
8 | }
9 |
10 | static gen() {
11 | ExponentialRandomVariable.C = (ExponentialRandomVariable.C*ExponentialRandomVariable.G) % ExponentialRandomVariable.P;
12 | return ExponentialRandomVariable.C / ExponentialRandomVariable.P;
13 | }
14 |
15 | pdf(x) {
16 | if (x < 0) {
17 | throw "Exponential not defined for x < 0";
18 | }
19 | return this.lam * Math.exp(-this.lam * x);
20 | }
21 |
22 | cdf(x) {
23 | if (x < 0) {
24 | throw "Exponential not defined for x < 0";
25 | }
26 | return 1 - Math.exp(-this.lam * x);
27 | }
28 |
29 | getValue() {
30 | return (-1.0 / this.lam) * Math.log(1.0 - ExponentialRandomVariable.gen());
31 | }
32 |
33 | logLikelihood(arrayValues) {
34 | let ret = 0.0;
35 | for (let v of arrayValues) {
36 | ret += Math.log(this.pdf(v));
37 | }
38 | return ret;
39 | }
40 |
41 | static estimateParameters(arrayValues) {
42 | let sum = 0.0;
43 | for (let v of arrayValues) {
44 | if (v < 0) {
45 | throw "Exponential not defined for x < 0";
46 | }
47 | sum += v;
48 | }
49 | return new ExponentialRandomVariable(1.0 / (sum / arrayValues.length));
50 | }
51 |
52 | getMean() {
53 | return 1.0 / this.lam;
54 | }
55 |
56 | getVariance() {
57 | return 1.0 / (this.lam * this.lam);
58 | }
59 |
60 | getMedian() {
61 | return Math.log(2) / this.lam;
62 | }
63 |
64 | getMode() {
65 | return 0;
66 | }
67 |
68 | getQuantile(p) {
69 | return - Math.log(1 - p) / this.lam;
70 | }
71 | }
72 |
73 | ExponentialRandomVariable.G = 536870911;
74 | ExponentialRandomVariable.P = 2147483647;
75 | ExponentialRandomVariable.C = 1;
76 |
77 |
78 | try {
79 | global.ExponentialRandomVariable = ExponentialRandomVariable;
80 | module.exports = {ExponentialRandomVariable: ExponentialRandomVariable};
81 | }
82 | catch (err) {
83 | // not in Node
84 | //console.log(err);
85 | }
86 |
--------------------------------------------------------------------------------
/pm4js/utils/random_variables/fitter.js:
--------------------------------------------------------------------------------
1 | class RandomVariableFitter {
2 | static apply(arrayValues, debug=false) {
3 | let rv = null;
4 | let likelihood = -Number.MAX_VALUE;
5 | if (debug) {
6 | console.log("----- debug -----");
7 | }
8 | try {
9 | let un = UniformRandomVariable.estimateParameters(arrayValues);
10 | let unLikelihood = un.logLikelihood(arrayValues);
11 | if (debug) {
12 | console.log(un.toString() + " unLikelihood = "+unLikelihood);
13 | }
14 | if (unLikelihood > likelihood) {
15 | rv = un;
16 | likelihood = unLikelihood;
17 | }
18 | }
19 | catch (err) {
20 | }
21 | try {
22 | let nv = NormalRandomVariable.estimateParameters(arrayValues);
23 | let nvLikelihood = nv.logLikelihood(arrayValues);
24 | if (debug) {
25 | console.log(nv.toString() + " nvLikelihood = "+nvLikelihood);
26 | }
27 | if (nvLikelihood > likelihood) {
28 | rv = nv;
29 | likelihood = nvLikelihood;
30 | }
31 | }
32 | catch (err) {
33 | }
34 | try {
35 | let lnv = LogNormalRandomVariable.estimateParameters(arrayValues);
36 | let lnvLikelihood = lnv.logLikelihood(arrayValues);
37 | if (debug) {
38 | console.log(lnv.toString() + " lnvLikelihood = "+lnvLikelihood);
39 | }
40 | if (lnvLikelihood > likelihood) {
41 | rv = lnv;
42 | likelihood = lnvLikelihood;
43 | }
44 | }
45 | catch (err) {
46 | }
47 | try {
48 | let ev = ExponentialRandomVariable.estimateParameters(arrayValues);
49 | let evLikelihood = ev.logLikelihood(arrayValues);
50 | if (debug) {
51 | console.log(ev.toString() + "evLikelihood = "+evLikelihood);
52 | }
53 | if (evLikelihood > likelihood) {
54 | rv = ev;
55 | likelihood = evLikelihood;
56 | }
57 | }
58 | catch (err) {
59 | }
60 | try {
61 | let gv = GammaRandomVariable.estimateParameters(arrayValues);
62 | let gvLikelihood = gv.logLikelihood(arrayValues);
63 | if (debug) {
64 | console.log(gv.toString() + " gvLikelihood = "+gvLikelihood);
65 | }
66 | if (gvLikelihood > likelihood) {
67 | rv = gv;
68 | likelihood = gvLikelihood;
69 | }
70 | }
71 | catch (err) {
72 | }
73 | try {
74 | let emn = ExponentiallyModifiedGaussian.estimateParameters(arrayValues);
75 | let emnLikelihood = emn.logLikelihood(arrayValues);
76 | if (debug) {
77 | console.log(emn.toString() + " emnLikelihood = "+emnLikelihood);
78 | }
79 | if (emnLikelihood > likelihood) {
80 | rv = emn;
81 | likelihood = emnLikelihood;
82 | }
83 | }
84 | catch (err) {
85 | }
86 | if (debug) {
87 | console.log("----- /debug -----");
88 | }
89 | return rv;
90 | }
91 | }
92 |
93 | try {
94 | global.RandomVariableFitter = RandomVariableFitter;
95 | module.exports = {RandomVariableFitter: RandomVariableFitter};
96 | }
97 | catch (err) {
98 | // not in Node
99 | //console.log(err);
100 | }
101 |
102 |
--------------------------------------------------------------------------------
/pm4js/utils/random_variables/gamma.js:
--------------------------------------------------------------------------------
1 | class GammaRandomVariable {
2 | constructor(k, theta) {
3 | this.k = k;
4 | this.theta = theta;
5 | }
6 |
7 | toString() {
8 | return "GammaRandomVariable k="+this.k+" theta="+this.theta;
9 | }
10 |
11 | static gen() {
12 | GammaRandomVariable.C = (GammaRandomVariable.C*GammaRandomVariable.G) % GammaRandomVariable.P;
13 | return GammaRandomVariable.C / GammaRandomVariable.P;
14 | }
15 |
16 | static estimateParameters(arrayValues) {
17 | let n = arrayValues.length;
18 | let kn = 0;
19 | for (let v of arrayValues) {
20 | if (v < 0) {
21 | throw "Gamma not defined for x < 0";
22 | }
23 | kn += v;
24 | }
25 | kn = kn * n * (n-1);
26 | let kd1 = 0;
27 | let kd2 = 0;
28 | let kd3 = 0;
29 | for (let v of arrayValues) {
30 | kd1 += v * Math.log(v);
31 | kd2 += Math.log(v);
32 | kd3 += v;
33 | }
34 | kd1 = kd1 * n;
35 | let kd = (n+2)*(kd1 - kd2 * kd3);
36 | let k = kn / kd;
37 | let theta = kd / (n * n * (n-1));
38 | return new GammaRandomVariable(k, theta);
39 | }
40 |
41 | static eulerGamma(x) {
42 | x = x - 1;
43 | return Math.sqrt(Math.PI) * Math.pow(Math.abs(x) / Math.E, x) * Math.pow(8 * x * x *x + 4 *x *x + x + 1.0 / 3.0, 1.0 / 6.0);
44 | }
45 |
46 | pdf(x) {
47 | if (x < 0) {
48 | throw "Gamma not defined for x < 0";
49 | }
50 | return (Math.pow(x, this.k - 1) * Math.exp(-x / this.theta)) / (Math.pow(this.theta, this.k) * GammaRandomVariable.eulerGamma(this.k));
51 | }
52 |
53 | logLikelihood(arrayValues) {
54 | let ret = 0.0;
55 | for (let v of arrayValues) {
56 | ret += Math.log(this.pdf(v));
57 | }
58 | return ret;
59 | }
60 |
61 | getMean() {
62 | return this.k * this.theta;
63 | }
64 |
65 | getVariance() {
66 | return this.k * this.theta * this.theta;
67 | }
68 |
69 | getMode() {
70 | if (this.k > 1) {
71 | return (this.k - 1)*this.theta;
72 | }
73 | return 0;
74 | }
75 |
76 | getValue() {
77 | let k = 0 + this.k;
78 | let exp = new ExponentialRandomVariable(1.0 / this.theta);
79 | let ret = 0;
80 | while (k > 1) {
81 | ret += exp.getValue();
82 | k = k - 1;
83 | }
84 | let umax = Math.pow((k / Math.E), k / 2.0);
85 | let vmin = -2 / Math.E;
86 | let vmax = 2*k / (Math.E * (Math.E - k));
87 | while (true) {
88 | let v1 = GammaRandomVariable.gen();
89 | let v2 = GammaRandomVariable.gen();
90 | let u = umax * v1;
91 | let v = (vmax - vmin) * v2 + vmin;
92 | let t = v / u;
93 | let x = Math.exp(t / k);
94 | if (2*Math.log(u) <= t - x) {
95 | ret += x * this.theta;
96 | break;
97 | }
98 | }
99 | return ret;
100 | }
101 | }
102 |
103 | GammaRandomVariable.G = 536870911;
104 | GammaRandomVariable.P = 2147483647;
105 | GammaRandomVariable.C = 1;
106 |
107 | try {
108 | global.GammaRandomVariable = GammaRandomVariable;
109 | module.exports = {GammaRandomVariable: GammaRandomVariable};
110 | }
111 | catch (err) {
112 | // not in Node
113 | //console.log(err);
114 | }
115 |
--------------------------------------------------------------------------------
/pm4js/utils/random_variables/lognormal.js:
--------------------------------------------------------------------------------
1 | class LogNormalRandomVariable {
2 | constructor(mu, sig) {
3 | this.mu = mu;
4 | this.sig = sig;
5 | }
6 |
7 | toString() {
8 | return "LogNormalRandomVariable mu="+this.mu+" sig="+this.sig;
9 | }
10 |
11 | static gen() {
12 | LogNormalRandomVariable.C = (LogNormalRandomVariable.C*LogNormalRandomVariable.G) % LogNormalRandomVariable.P;
13 | return LogNormalRandomVariable.C / LogNormalRandomVariable.P;
14 | }
15 |
16 | static erf(x) {
17 | let v = 1;
18 | v = v + 0.278393*x;
19 | let y = x * x;
20 | v = v + 0.230389*y;
21 | y = y * x;
22 | v = v + 0.000972*y;
23 | y = y * x;
24 | v = v + 0.078108*y;
25 | v = v * v;
26 | v = v * v;
27 | v = 1.0 / v;
28 | v = 1.0 - v;
29 | return v;
30 | }
31 |
32 | static erfinv(x) {
33 | let sgn = 1;
34 | if (x < 0) {
35 | sgn = -1;
36 | x = -x;
37 | }
38 | x = (1 - x)*(1 + x);
39 | let lnx = Math.log(x);
40 | let tt1 = 2/(Math.PI * 0.147) + 0.5 * lnx;
41 | let tt2 = 1/0.147 * lnx;
42 | return sgn * Math.sqrt(-tt1 + Math.sqrt(tt1 * tt1 - tt2));
43 | }
44 |
45 | pdf(x) {
46 | if (x < 0) {
47 | throw "Lognormal not defined for x < 0";
48 | }
49 | return 1.0 / (x * this.sig * Math.sqrt(2 * Math.PI)) * Math.exp(-(Math.log(x) - this.mu)*(Math.log(x) - this.mu)/(2 * this.sig * this.sig));
50 | }
51 |
52 | cdf(x) {
53 | if (x < 0) {
54 | throw "Lognormal not defined for x < 0";
55 | }
56 | return 0.5*(1.0 + LogNormalRandomVariable.erf((Math.log(x) - this.mu)/(this.sig * Math.sqrt(2))));
57 | }
58 |
59 | getValue() {
60 | let v1 = NormalRandomVariable.gen();
61 | let v2 = NormalRandomVariable.gen();
62 | return Math.exp(this.mu + this.sig * Math.cos(2*Math.PI*v2) * Math.sqrt(-2.0 * Math.log(v1)));
63 | }
64 |
65 | logLikelihood(arrayValues) {
66 | let ret = 0.0;
67 | for (let v of arrayValues) {
68 | ret += Math.log(this.pdf(v));
69 | }
70 | return ret;
71 | }
72 |
73 | static estimateParameters(arrayValues) {
74 | let sum = 0.0;
75 | for (let v of arrayValues) {
76 | if (v < 0) {
77 | throw "Lognormal not defined for x < 0";
78 | }
79 | sum += v;
80 | }
81 | let avg = sum / arrayValues.length;
82 | sum = 0.0;
83 | for (let v of arrayValues) {
84 | sum += (v - avg) * (v-avg);
85 | }
86 | let std = Math.sqrt(sum / arrayValues.length);
87 | let mu = Math.log((avg * avg)/(Math.sqrt(avg*avg + std*std)));
88 | let s = Math.sqrt(Math.log(1 + (std*std)/(avg*avg)))
89 | return new LogNormalRandomVariable(mu, s);
90 | }
91 |
92 | getMean() {
93 | return Math.exp(this.mu + this.sig * this.sig / 2.0);
94 | }
95 |
96 | getVariance() {
97 | return (Math.exp(this.sig * this.sig) - 1) * Math.exp(2*this.mu + this.sig * this.sig);
98 | }
99 |
100 | getMedian() {
101 | return Math.exp(this.mu);
102 | }
103 |
104 | getMode() {
105 | return Math.exp(this.mu - this.sig * this.sig);
106 | }
107 |
108 | getQuantile(p) {
109 | return Math.exp(this.mu + Math.sqrt(2 * this.sig * this.sig) * LogNormalRandomVariable.erfinv(2 * p - 1));
110 | }
111 | }
112 |
113 | LogNormalRandomVariable.G = 536870911;
114 | LogNormalRandomVariable.P = 2147483647;
115 | LogNormalRandomVariable.C = 1;
116 |
117 |
118 | try {
119 | global.LogNormalRandomVariable = LogNormalRandomVariable;
120 | module.exports = {LogNormalRandomVariable: LogNormalRandomVariable};
121 | }
122 | catch (err) {
123 | // not in Node
124 | //console.log(err);
125 | }
126 |
--------------------------------------------------------------------------------
/pm4js/utils/random_variables/normal.js:
--------------------------------------------------------------------------------
1 | class NormalRandomVariable {
2 | constructor(mu, sig) {
3 | this.mu = mu;
4 | this.sig = sig;
5 | }
6 |
7 | toString() {
8 | return "NormalRandomVariable mu="+this.mu+" sig="+this.sig;
9 | }
10 |
11 | static gen() {
12 | NormalRandomVariable.C = (NormalRandomVariable.C*NormalRandomVariable.G) % NormalRandomVariable.P;
13 | return NormalRandomVariable.C / NormalRandomVariable.P;
14 | }
15 |
16 | static erf(x) {
17 | let v = 1;
18 | v = v + 0.278393*x;
19 | let y = x * x;
20 | v = v + 0.230389*y;
21 | y = y * x;
22 | v = v + 0.000972*y;
23 | y = y * x;
24 | v = v + 0.078108*y;
25 | v = v * v;
26 | v = v * v;
27 | v = 1.0 / v;
28 | v = 1.0 - v;
29 | return v;
30 | }
31 |
32 | static erfinv(x) {
33 | let sgn = 1;
34 | if (x < 0) {
35 | sgn = -1;
36 | x = -x;
37 | }
38 | x = (1 - x)*(1 + x);
39 | let lnx = Math.log(x);
40 | let tt1 = 2/(Math.PI * 0.147) + 0.5 * lnx;
41 | let tt2 = 1/0.147 * lnx;
42 | return sgn * Math.sqrt(-tt1 + Math.sqrt(tt1 * tt1 - tt2));
43 | }
44 |
45 | pdf(x) {
46 | return 1.0/(this.sig*Math.sqrt(2*Math.PI)) * Math.exp(-0.5*((x-this.mu)/this.sig)*((x-this.mu)/this.sig));
47 | }
48 |
49 | cdf(x) {
50 | return 0.5*(1.0 + NormalRandomVariable.erf((x - this.mu)/(this.sig * Math.sqrt(2))));
51 | }
52 |
53 | getValue() {
54 | let v1 = NormalRandomVariable.gen();
55 | let v2 = NormalRandomVariable.gen();
56 | return this.mu + this.sig * Math.cos(2*Math.PI*v2) * Math.sqrt(-2.0 * Math.log(v1));
57 | }
58 |
59 | logLikelihood(arrayValues) {
60 | let ret = 0.0;
61 | for (let v of arrayValues) {
62 | ret += Math.log(this.pdf(v));
63 | }
64 | return ret;
65 | }
66 |
67 | static estimateParameters(arrayValues) {
68 | let sum = 0.0;
69 | for (let v of arrayValues) {
70 | sum += v;
71 | }
72 | let avg = sum / arrayValues.length;
73 | sum = 0.0;
74 | for (let v of arrayValues) {
75 | sum += (v - avg) * (v-avg);
76 | }
77 | let std = Math.sqrt(sum / arrayValues.length);
78 | return new NormalRandomVariable(avg, std);
79 | }
80 |
81 | getMean() {
82 | return this.mu;
83 | }
84 |
85 | getVariance() {
86 | return this.sig * this.sig;
87 | }
88 |
89 | getMedian() {
90 | return this.mu;
91 | }
92 |
93 | getMode() {
94 | return this.mu;
95 | }
96 |
97 | getQuantile(p) {
98 | return this.mu + this.sig * Math.sqrt(2) * NormalRandomVariable.erfinv(2*p - 1);
99 | }
100 | }
101 |
102 | NormalRandomVariable.G = 536870911;
103 | NormalRandomVariable.P = 2147483647;
104 | NormalRandomVariable.C = 1;
105 |
106 |
107 | try {
108 | global.NormalRandomVariable = NormalRandomVariable;
109 | module.exports = {NormalRandomVariable: NormalRandomVariable};
110 | }
111 | catch (err) {
112 | // not in Node
113 | //console.log(err);
114 | }
115 |
--------------------------------------------------------------------------------
/pm4js/utils/random_variables/uniform.js:
--------------------------------------------------------------------------------
1 | class UniformRandomVariable {
2 | constructor(a, b) {
3 | if (a >= b) {
4 | throw "a must be lower than b";
5 | }
6 | this.a = a;
7 | this.b = b;
8 | }
9 |
10 | toString() {
11 | return "UniformRandomVariable a="+this.a+" b="+this.b;
12 | }
13 |
14 | pdf(x) {
15 | if (x >= this.a && x <= this.b) {
16 | return 1.0 / (this.b - this.a);
17 | }
18 | return 0.0;
19 | }
20 |
21 | cdf(x) {
22 | if (x <= this.a) {
23 | return 0.0;
24 | }
25 | else if (x > this.a && x < this.b) {
26 | return (x - this.a)/(this.b - this.a);
27 | }
28 | else {
29 | return 1.0;
30 | }
31 | }
32 |
33 | static estimateParameters(arrayValues) {
34 | let minValue = Number.MAX_VALUE;
35 | let maxValue = -Number.MAX_VALUE;
36 | for (let v of arrayValues) {
37 | if (v < minValue) {
38 | minValue = v;
39 | }
40 | if (v > maxValue) {
41 | maxValue = v;
42 | }
43 | }
44 | return new UniformRandomVariable(minValue, maxValue);
45 | }
46 |
47 | getMean() {
48 | return 0.5 * (this.a + this.b);
49 | }
50 |
51 | getMedian() {
52 | return 0.5 * (this.a + this.b);
53 | }
54 |
55 | getMode() {
56 | return 0.5 * (this.a + this.b);
57 | }
58 |
59 | getVariance() {
60 | return 1.0 / 12.0 * (this.b - this.a) * (this.b - this.a);
61 | }
62 |
63 | logLikelihood(arrayValues) {
64 | let ret = 0.0;
65 | for (let v of arrayValues) {
66 | ret += Math.log(this.pdf(v));
67 | }
68 | return ret;
69 | }
70 |
71 | static gen() {
72 | UniformRandomVariable.C = (UniformRandomVariable.C*UniformRandomVariable.G) % UniformRandomVariable.P;
73 | return UniformRandomVariable.C / UniformRandomVariable.P;
74 | }
75 |
76 | getValue() {
77 | let val = UniformRandomVariable.gen();
78 | return this.a + (this.b - this.a) * val;
79 | }
80 |
81 | getQuantile(p) {
82 | return this.a + p * (this.b - this.a);
83 | }
84 | }
85 |
86 | UniformRandomVariable.G = 536870911;
87 | UniformRandomVariable.P = 2147483647;
88 | UniformRandomVariable.C = 1;
89 |
90 | try {
91 | global.UniformRandomVariable = UniformRandomVariable;
92 | module.exports = {UniformRandomVariable: UniformRandomVariable};
93 | }
94 | catch (err) {
95 | // not in Node
96 | //console.log(err);
97 | }
98 |
99 |
--------------------------------------------------------------------------------
/pm4js/utils/stream/stream_attr_wrapper.js:
--------------------------------------------------------------------------------
1 | class StreamAttrWrapper {
2 | static accessAttribute(eve, attribute) {
3 | if (eve.constructor.name == "Event") {
4 | // EventLog Event
5 | if (attribute in eve.attributes) {
6 | return eve.attributes[attribute].value;
7 | }
8 | }
9 | else {
10 | // OCEL
11 | if (attribute == "ocel:activity" || attribute == "ocel:timestamp") {
12 | return eve[attribute];
13 | }
14 | else if (attribute in eve["ocel:vmap"]) {
15 | return eve["ocel:vmap"][attribute];
16 | }
17 | }
18 | return null;
19 | }
20 |
21 | static attributesList(stream) {
22 | let attList = {};
23 | if (stream.length > 0) {
24 | if (stream[0].constructor.name == "Event") {
25 | // EventLog Event
26 | for (let eve of stream) {
27 | for (let attr in eve.attributes) {
28 | attList[attr] = 0;
29 | }
30 | }
31 | }
32 | else {
33 | // OCEL
34 | attList["ocel:activity"] = 0;
35 | attList["ocel:timestamp"] = 0;
36 | for (let eve of stream) {
37 | for (let attr in eve["ocel:vmap"]) {
38 | attList[attr] = 0;
39 | }
40 | }
41 | }
42 | }
43 | return Object.keys(attList);
44 | }
45 |
46 | static defaultTimestamp(eve) {
47 | if (eve.constructor.name == "Event") {
48 | // EventLog Event
49 | return eve.attributes["time:timestamp"].value;
50 | }
51 | else {
52 | // OCEL
53 | return eve["ocel:timestamp"];
54 | }
55 | }
56 | }
57 |
58 | try {
59 | module.exports = {StreamAttrWrapper: StreamAttrWrapper};
60 | global.StreamAttrWrapper = StreamAttrWrapper;
61 | }
62 | catch (err) {
63 | // not in node
64 | //console.log(err);
65 | }
66 |
--------------------------------------------------------------------------------
/pm4js/visualization/dfg/alignments.js:
--------------------------------------------------------------------------------
1 | class AlignmentsDfgGraphvizVisualizer {
2 | static uuidv4() {
3 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
4 | var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
5 | return v.toString(16);
6 | });
7 | }
8 |
9 | static nodeUuid() {
10 | let uuid = FrequencyDfgGraphvizVisualizer.uuidv4();
11 | return "n"+uuid.replace(/-/g, "");
12 | }
13 |
14 | static apply(frequencyDfg, alignedTraces) {
15 | let smCount = {};
16 | let mmCount = {};
17 | let lmCount = {};
18 | for (let act in frequencyDfg.activities) {
19 | smCount[act] = 0;
20 | mmCount[act] = 0;
21 | lmCount[act] = 0;
22 | }
23 | for (let move0 in alignedTraces.movesUsage) {
24 | let move = move0.split(";");
25 | move[0] = move[0].substring(1, move[0].length);
26 | move[1] = move[1].substring(0, move[1].length-1);
27 | if (move[0] == move[1]) {
28 | // sync
29 | smCount[move[0]] = alignedTraces.movesUsage[move0];
30 | }
31 | else if (move[1] == ">>") {
32 | lmCount[move[0]] = alignedTraces.movesUsage[move0];
33 | }
34 | else if (move[0] == ">>") {
35 | mmCount[move[1]] = alignedTraces.movesUsage[move0];
36 | }
37 | }
38 | let ret = [];
39 | let uidMap = {};
40 | ret.push("digraph G {");
41 | for (let act in frequencyDfg.activities) {
42 | let nUid = FrequencyDfgGraphvizVisualizer.nodeUuid();
43 | uidMap[act] = nUid;
44 | ret.push(nUid+" [shape=box, label=\""+act+"\nSM="+smCount[act]+";MM="+mmCount[act]+";LM="+lmCount[act]+"\"]");
45 | }
46 | let startNodeUid = FrequencyDfgGraphvizVisualizer.nodeUuid();
47 | let endNodeUid = FrequencyDfgGraphvizVisualizer.nodeUuid();
48 | ret.push(startNodeUid+" [shape=circle, label=\" \", style=filled, fillcolor=green]");
49 | ret.push(endNodeUid+" [shape=circle, label=\" \", style=filled, fillcolor=orange]");
50 | for (let sa in frequencyDfg.startActivities) {
51 | let occ = frequencyDfg.startActivities[sa];
52 | let penwidth = 0.5 + Math.log10(occ);
53 | ret.push(startNodeUid+" -> "+uidMap[sa]+" [penwidth=\""+penwidth+"\"]");
54 | }
55 | for (let ea in frequencyDfg.endActivities) {
56 | let occ = frequencyDfg.endActivities[ea];
57 | let penwidth = 0.5 + Math.log10(occ);
58 | ret.push(uidMap[ea]+" -> "+endNodeUid+" [penwidth=\""+penwidth+"\"]");
59 | }
60 | for (let arc in frequencyDfg.pathsFrequency) {
61 | let act1 = arc.split(",")[0];
62 | let act2 = arc.split(",")[1];
63 | let occ = frequencyDfg.pathsFrequency[arc];
64 | let penwidth = 0.5 + Math.log10(occ);
65 | ret.push(uidMap[act1]+" -> "+uidMap[act2]+" [penwidth=\""+penwidth+"\"]");
66 | }
67 | ret.push("}");
68 | return ret.join("\n");
69 | }
70 | }
71 |
72 | try {
73 | module.exports = {AlignmentsDfgGraphvizVisualizer: AlignmentsDfgGraphvizVisualizer};
74 | global.AlignmentsDfgGraphvizVisualizer = AlignmentsDfgGraphvizVisualizer;
75 | }
76 | catch (err) {
77 | // not in node
78 | }
--------------------------------------------------------------------------------
/pm4js/visualization/dfg/frequency.js:
--------------------------------------------------------------------------------
1 | class FrequencyDfgGraphvizVisualizer {
2 | static uuidv4() {
3 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
4 | var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
5 | return v.toString(16);
6 | });
7 | }
8 |
9 | static nodeUuid() {
10 | let uuid = FrequencyDfgGraphvizVisualizer.uuidv4();
11 | return "n"+uuid.replace(/-/g, "");
12 | }
13 |
14 | static apply(frequencyDfg) {
15 | let ret = [];
16 | let uidMap = {};
17 | ret.push("digraph G {");
18 | for (let act in frequencyDfg.activities) {
19 | let nUid = FrequencyDfgGraphvizVisualizer.nodeUuid();
20 | uidMap[act] = nUid;
21 | ret.push(nUid+" [shape=box, label=\""+act+"\n"+frequencyDfg.activities[act]+"\"]");
22 | }
23 | let startNodeUid = FrequencyDfgGraphvizVisualizer.nodeUuid();
24 | let endNodeUid = FrequencyDfgGraphvizVisualizer.nodeUuid();
25 | ret.push(startNodeUid+" [shape=circle, label=\" \", style=filled, fillcolor=green]");
26 | ret.push(endNodeUid+" [shape=circle, label=\" \", style=filled, fillcolor=orange]");
27 | for (let sa in frequencyDfg.startActivities) {
28 | let occ = frequencyDfg.startActivities[sa];
29 | let penwidth = 0.5 + Math.log10(occ);
30 | ret.push(startNodeUid+" -> "+uidMap[sa]+" [label=\""+occ+"\", penwidth=\""+penwidth+"\"]");
31 | }
32 | for (let ea in frequencyDfg.endActivities) {
33 | let occ = frequencyDfg.endActivities[ea];
34 | let penwidth = 0.5 + Math.log10(occ);
35 | ret.push(uidMap[ea]+" -> "+endNodeUid+" [label=\""+occ+"\", penwidth=\""+penwidth+"\"]");
36 | }
37 | for (let arc in frequencyDfg.pathsFrequency) {
38 | let act1 = arc.split(",")[0];
39 | let act2 = arc.split(",")[1];
40 | let occ = frequencyDfg.pathsFrequency[arc];
41 | let penwidth = 0.5 + Math.log10(occ);
42 | ret.push(uidMap[act1]+" -> "+uidMap[act2]+" [label=\""+occ+"\", penwidth=\""+penwidth+"\"]");
43 | }
44 | ret.push("}");
45 | return ret.join("\n");
46 | }
47 | }
48 |
49 | try {
50 | module.exports = {FrequencyDfgGraphvizVisualizer: FrequencyDfgGraphvizVisualizer};
51 | global.FrequencyDfgGraphvizVisualizer = FrequencyDfgGraphvizVisualizer;
52 | }
53 | catch (err) {
54 | // not in node
55 | }
--------------------------------------------------------------------------------
/pm4js/visualization/dfg/performance.js:
--------------------------------------------------------------------------------
1 | class PerformanceDfgGraphvizVisualizer {
2 | static uuidv4() {
3 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
4 | var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
5 | return v.toString(16);
6 | });
7 | }
8 |
9 | static nodeUuid() {
10 | let uuid = PerformanceDfgGraphvizVisualizer.uuidv4();
11 | return "n"+uuid.replace(/-/g, "");
12 | }
13 |
14 | static apply(performanceDfg) {
15 | let ret = [];
16 | let uidMap = {};
17 | ret.push("digraph G {");
18 | for (let act in performanceDfg.activities) {
19 | let nUid = PerformanceDfgGraphvizVisualizer.nodeUuid();
20 | uidMap[act] = nUid;
21 | let st = performanceDfg.sojournTimes[act];
22 | ret.push(nUid+" [shape=box, label=\""+act+"\n("+humanizeDuration(st*1000)+")\"]");
23 | }
24 | let startNodeUid = PerformanceDfgGraphvizVisualizer.nodeUuid();
25 | let endNodeUid = PerformanceDfgGraphvizVisualizer.nodeUuid();
26 | ret.push(startNodeUid+" [shape=circle, label=\" \", style=filled, fillcolor=green]");
27 | ret.push(endNodeUid+" [shape=circle, label=\" \", style=filled, fillcolor=orange]");
28 | for (let sa in performanceDfg.startActivities) {
29 | ret.push(startNodeUid+" -> "+uidMap[sa]);
30 | }
31 | for (let ea in performanceDfg.endActivities) {
32 | ret.push(uidMap[ea]+" -> "+endNodeUid);
33 | }
34 | for (let arc in performanceDfg.pathsPerformance) {
35 | let act1 = arc.split(",")[0];
36 | let act2 = arc.split(",")[1];
37 | let perf = performanceDfg.pathsPerformance[arc];
38 | let penwidth = 0.5 + 0.3 * Math.log10(1 + perf);
39 | ret.push(uidMap[act1]+" -> "+uidMap[act2]+" [label=\""+humanizeDuration(Math.round(perf*1000))+"\", penwidth=\""+penwidth+"\"]");
40 | }
41 | ret.push("}");
42 | return ret.join("\n");
43 | }
44 | }
45 |
46 | try {
47 | module.exports = {PerformanceDfgGraphvizVisualizer: PerformanceDfgGraphvizVisualizer};
48 | global.PerformanceDfgGraphvizVisualizer = PerformanceDfgGraphvizVisualizer;
49 | }
50 | catch (err) {
51 | // not in node
52 | //console.log(err);
53 | }
--------------------------------------------------------------------------------
/pm4js/visualization/network_analysis/graphviz.js:
--------------------------------------------------------------------------------
1 | class NetworkAnalysisGraphvizVisualizer {
2 | static uuidv4() {
3 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
4 | var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
5 | return v.toString(16);
6 | });
7 | }
8 |
9 | static nodeUuid() {
10 | let uuid = NetworkAnalysisGraphvizVisualizer.uuidv4();
11 | return "n"+uuid.replace(/-/g, "");
12 | }
13 |
14 | static calculateAverage(times) {
15 | if (times.length > 0) {
16 | let sum = 0;
17 | for (let el of times) {
18 | sum += el;
19 | }
20 | return sum / times.length;
21 | }
22 | return 0;
23 | }
24 |
25 |
26 | static apply(networkAnalysis, performance=false) {
27 | let ret = [];
28 | ret.push("digraph G {");
29 | let nodesMap = {};
30 | for (let nk in networkAnalysis.nodes) {
31 | let nstats = networkAnalysis.nodes[nk];
32 | let nuid = NetworkAnalysisGraphvizVisualizer.nodeUuid();
33 | nodesMap[nk] = nuid;
34 | ret.push(nuid+" [shape=ellipse, label=\""+nk+"\nIN="+nstats["IN"]+"\nOUT="+nstats["OUT"]+"\"]");
35 | }
36 | for (let eg in networkAnalysis.multiEdges) {
37 | let estats = networkAnalysis.multiEdges[eg];
38 | let egs = eg.split(",");
39 | let sn = egs[0];
40 | let tn = egs[1];
41 | let ml = egs[2];
42 | let label = ml+"\n";
43 | if (performance) {
44 | let perf = NetworkAnalysisGraphvizVisualizer.calculateAverage(estats["timeDiff"]);
45 | label += humanizeDuration(Math.round(perf*1000));
46 | }
47 | else {
48 | label += "(" + estats["count"]+")";
49 | }
50 | ret.push(nodesMap[sn]+" -> "+nodesMap[tn]+" [label=\""+label+"\"]");
51 | }
52 | ret.push("}");
53 | return ret.join("\n");
54 | }
55 | }
56 |
57 | try {
58 | module.exports = {NetworkAnalysisGraphvizVisualizer: NetworkAnalysisGraphvizVisualizer};
59 | global.NetworkAnalysisGraphvizVisualizer = NetworkAnalysisGraphvizVisualizer;
60 | }
61 | catch (err) {
62 | // not in node
63 | }
64 |
--------------------------------------------------------------------------------
/pm4js/visualization/petri_net/frequency_graphviz.js:
--------------------------------------------------------------------------------
1 | class PetriNetFrequencyVisualizer {
2 | static rgbColor(percent) {
3 | return [255 * percent, 255 * (1 - percent), 255 * (1 - percent)];
4 | }
5 |
6 | static hexFromRGB(r, g, b) {
7 | var hex = [
8 | Math.floor(r).toString( 16 ),
9 | Math.floor(g).toString( 16 ),
10 | Math.floor(b).toString( 16 )
11 | ];
12 | let i = 0;
13 | while (i < hex.length) {
14 | if (hex[i].length == 1) {
15 | hex[i] = "0" + hex[i];
16 | }
17 | i++;
18 | }
19 | return "#" + hex.join( "" ).toLowerCase();
20 | }
21 |
22 | static uuidv4() {
23 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
24 | var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
25 | return v.toString(16);
26 | });
27 | }
28 |
29 | static nodeUuid() {
30 | let uuid = PetriNetFrequencyVisualizer.uuidv4();
31 | return "n"+uuid.replace(/-/g, "");
32 | }
33 |
34 | static apply(acceptingPetriNet, tbrResult) {
35 | let petriNet = acceptingPetriNet.net;
36 | let im = acceptingPetriNet.im;
37 | let fm = acceptingPetriNet.fm;
38 | let ret = [];
39 | let uidMap = {};
40 | let transMaxFrequency = -1;
41 | let arcMaxFrequency = -1;
42 | for (let trans in tbrResult.transExecutions) {
43 | transMaxFrequency = Math.max(tbrResult.transExecutions[trans], transMaxFrequency);
44 | }
45 | for (let arc in tbrResult.arcExecutions) {
46 | arcMaxFrequency = Math.max(tbrResult.arcExecutions[arc], arcMaxFrequency);
47 | }
48 | ret.push("digraph G {");
49 | ret.push("rankdir=\"LR\"");
50 | for (let placeKey in petriNet.places) {
51 | let place = petriNet.places[placeKey];
52 | let nUid = PetriNetFrequencyVisualizer.nodeUuid();
53 | let fillColor = "white";
54 | if (place in im.tokens) {
55 | fillColor = "green";
56 | }
57 | else if (place in fm.tokens) {
58 | fillColor = "orange";
59 | }
60 | let placeLabel = "p="+tbrResult.totalProducedPerPlace[place]+";m="+tbrResult.totalMissingPerPlace[place]+"\nc="+tbrResult.totalConsumedPerPlace[place]+";r="+tbrResult.totalRemainingPerPlace[place];
61 | ret.push(nUid+" [shape=ellipse, label=\""+placeLabel+"\", style=filled, fillcolor="+fillColor+"]");
62 | uidMap[place] = nUid;
63 | }
64 | for (let transKey in petriNet.transitions) {
65 | let trans = petriNet.transitions[transKey];
66 | let perc = (1.0 - tbrResult.transExecutions[trans] / transMaxFrequency);
67 | let rgb = PetriNetFrequencyVisualizer.rgbColor(perc);
68 | let rgbHex = PetriNetFrequencyVisualizer.hexFromRGB(rgb[0], rgb[1], rgb[2]);
69 | let nUid = PetriNetFrequencyVisualizer.nodeUuid();
70 | if (trans.label != null) {
71 | ret.push(nUid+" [shape=box, label=\""+trans.label+"\n("+tbrResult.transExecutions[trans]+")\"; style=filled, fillcolor=\""+rgbHex+"\"]");
72 | }
73 | else {
74 | ret.push(nUid+" [shape=box, label=\" \", style=filled, fillcolor=black]");
75 | }
76 | uidMap[trans] = nUid;
77 | }
78 | for (let arcKey in petriNet.arcs) {
79 | let arc = petriNet.arcs[arcKey];
80 | let uid1 = uidMap[arc.source];
81 | let uid2 = uidMap[arc.target];
82 | let penwidth = 0.5 + Math.log10(1 + tbrResult.arcExecutions[arcKey]);
83 | ret.push(uid1+" -> "+uid2+" [label=\""+tbrResult.arcExecutions[arcKey]+"\", penwidth=\""+penwidth+"\"]");
84 | }
85 | ret.push("}");
86 | return ret.join('\n');
87 | }
88 | }
89 |
90 | try {
91 | module.exports = {PetriNetFrequencyVisualizer: PetriNetFrequencyVisualizer};
92 | global.PetriNetFrequencyVisualizer = PetriNetFrequencyVisualizer;
93 | }
94 | catch (err) {
95 | // not in node
96 | }
--------------------------------------------------------------------------------
/pm4js/visualization/petri_net/vanilla_graphviz.js:
--------------------------------------------------------------------------------
1 | class PetriNetVanillaVisualizer {
2 | static uuidv4() {
3 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
4 | var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
5 | return v.toString(16);
6 | });
7 | }
8 |
9 | static nodeUuid() {
10 | let uuid = PetriNetVanillaVisualizer.uuidv4();
11 | return "n"+uuid.replace(/-/g, "");
12 | }
13 |
14 | static apply(acceptingPetriNet, debug=false) {
15 | let petriNet = acceptingPetriNet.net;
16 | let im = acceptingPetriNet.im;
17 | let fm = acceptingPetriNet.fm;
18 | let ret = [];
19 | let uidMap = {};
20 | ret.push("digraph G {");
21 | ret.push("rankdir=\"LR\"");
22 | for (let placeKey in petriNet.places) {
23 | let place = petriNet.places[placeKey];
24 | let nUid = PetriNetVanillaVisualizer.nodeUuid();
25 | let fillColor = "white";
26 | if (place in im.tokens) {
27 | fillColor = "green";
28 | }
29 | else if (place in fm.tokens) {
30 | fillColor = "orange";
31 | }
32 | let placeLabel = " ";
33 | if (debug == true) {
34 | placeLabel = placeKey;
35 | }
36 | ret.push(nUid+" [shape=circle, label=\""+placeLabel+"\", style=filled, fillcolor="+fillColor+"]");
37 | uidMap[place] = nUid;
38 | }
39 | for (let transKey in petriNet.transitions) {
40 | let trans = petriNet.transitions[transKey];
41 | let nUid = PetriNetVanillaVisualizer.nodeUuid();
42 | if (trans.label != null) {
43 | ret.push(nUid+" [shape=box, label=\""+trans.label+"\"]");
44 | }
45 | else {
46 | if (debug == true) {
47 | ret.push(nUid+" [shape=box, label=\""+trans.name+"\"]");
48 | }
49 | else {
50 | ret.push(nUid+" [shape=box, label=\" \", style=filled, fillcolor=black]");
51 | }
52 | }
53 | uidMap[trans] = nUid;
54 | }
55 | for (let arcKey in petriNet.arcs) {
56 | let arc = petriNet.arcs[arcKey];
57 | let uid1 = uidMap[arc.source];
58 | let uid2 = uidMap[arc.target];
59 | ret.push(uid1+" -> "+uid2+"");
60 | }
61 | ret.push("}");
62 | return ret.join('\n');
63 | }
64 | }
65 |
66 | try {
67 | module.exports = {PetriNetVanillaVisualizer: PetriNetVanillaVisualizer};
68 | global.PetriNetVanillaVisualizer = PetriNetVanillaVisualizer;
69 | }
70 | catch (err) {
71 | // not in node
72 | }
--------------------------------------------------------------------------------
/pm4js/visualization/process_tree/vanilla_graphviz.js:
--------------------------------------------------------------------------------
1 | class ProcessTreeVanillaVisualizer {
2 | static nodeUuid(uuid) {
3 | return "n"+uuid.replace(/-/g, "");
4 | }
5 |
6 | static apply(processTree) {
7 | let descendants = {};
8 | ProcessTreeVanillaVisualizer.findAllDescendants(processTree, descendants);
9 | let ret = [];
10 | ret.push("digraph G {");
11 | for (let desc in descendants) {
12 | let tree = descendants[desc];
13 | let treeId = ProcessTreeVanillaVisualizer.nodeUuid(desc);
14 | let nodeLabel = "";
15 | if (tree.label != null) {
16 | nodeLabel = tree.label;
17 | }
18 |
19 | if (tree.operator == ProcessTreeOperator.SEQUENCE) {
20 | nodeLabel = "seq";
21 | }
22 | else if (tree.operator == ProcessTreeOperator.PARALLEL) {
23 | nodeLabel = "and";
24 | }
25 | else if (tree.operator == ProcessTreeOperator.INCLUSIVE) {
26 | nodeLabel = "or";
27 | }
28 | else if (tree.operator == ProcessTreeOperator.EXCLUSIVE) {
29 | nodeLabel = "xor";
30 | }
31 | else if (tree.operator == ProcessTreeOperator.LOOP) {
32 | nodeLabel = "xorLoop";
33 | }
34 |
35 | if (tree.operator == null && tree.label == null) {
36 | ret.push(treeId+" [shape=point, label=\"\", style=filled, fillcolor=black]");
37 | }
38 | else {
39 | ret.push(treeId+" [shape=ellipse; label=\""+nodeLabel+"\"]");
40 | }
41 | }
42 | for (let desc in descendants) {
43 | let tree = descendants[desc];
44 | let treeId = ProcessTreeVanillaVisualizer.nodeUuid(desc);
45 | let childCount = 0;
46 | for (let child of tree.children) {
47 | let childId = ProcessTreeVanillaVisualizer.nodeUuid(child.id);
48 | ret.push(treeId+" -> "+childId+" [dir=none]");
49 | childCount++;
50 | if (tree.operator == ProcessTreeOperator.LOOP) {
51 | if (childCount == 2) {
52 | break;
53 | }
54 | }
55 | }
56 | }
57 | ret.push("}");
58 | return ret.join('\n');
59 | }
60 |
61 | static findAllDescendants(processTree, descendants) {
62 | descendants[processTree.id] = processTree;
63 | if (processTree.operator == ProcessTreeOperator.LOOP) {
64 | ProcessTreeVanillaVisualizer.findAllDescendants(processTree.children[0], descendants);
65 | ProcessTreeVanillaVisualizer.findAllDescendants(processTree.children[1], descendants);
66 | }
67 | else {
68 | for (let child of processTree.children) {
69 | ProcessTreeVanillaVisualizer.findAllDescendants(child, descendants);
70 | }
71 | }
72 | }
73 | }
74 |
75 | try {
76 | module.exports = {ProcessTreeVanillaVisualizer: ProcessTreeVanillaVisualizer};
77 | global.ProcessTreeVanillaVisualizer = ProcessTreeVanillaVisualizer;
78 | }
79 | catch (err) {
80 | // not in node
81 | //console.log(err);
82 | }
83 |
--------------------------------------------------------------------------------
/simple_example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
18 |
19 |
--------------------------------------------------------------------------------
/tests/bpmn.test.js:
--------------------------------------------------------------------------------
1 | require("../init.js");
2 | var fs = require('fs');
3 | const os = require('os');
4 |
5 | test("BPMN to Petri net (running example) and exporting", () => {
6 | let data = fs.readFileSync('examples/input_data/running-example.bpmn', {encoding: 'utf-8'});
7 | let bpmnGraph = BpmnImporter.apply(data);
8 | let acceptingPetriNet = BpmnToPetriNetConverter.apply(data);
9 | BpmnExporter.apply(bpmnGraph);
10 | PnmlExporter.apply(acceptingPetriNet);
11 | });
12 |
13 | test("BPMN to Petri net (sepsis) and exporting", () => {
14 | let data = fs.readFileSync('examples/input_data/sepsis.bpmn', {encoding: 'utf-8'});
15 | let bpmnGraph = BpmnImporter.apply(data);
16 | let acceptingPetriNet = BpmnToPetriNetConverter.apply(data);
17 | BpmnExporter.apply(bpmnGraph);
18 | PnmlExporter.apply(acceptingPetriNet);
19 | });
20 |
21 | test("Petri net to BPMN (running example) and exporting", () => {
22 | let data = fs.readFileSync('examples/input_data/running-example.pnml', {encoding: 'utf-8'});
23 | let acceptingPetriNet = PnmlImporter.apply(data);
24 | let bpmnGraph = WfNetToBpmnConverter.apply(acceptingPetriNet);
25 | acceptingPetriNet = BpmnToPetriNetConverter.apply(bpmnGraph);
26 | BpmnExporter.apply(bpmnGraph);
27 | PnmlExporter.apply(acceptingPetriNet);
28 | });
29 |
30 | test("BPMN alignments", () => {
31 | let eventLog = XesImporter.apply(fs.readFileSync('examples/input_data/running-example.xes', {encoding: 'utf-8'}));
32 | let bpmnGraph = BpmnImporter.apply(fs.readFileSync('examples/input_data/running-example.bpmn', {encoding: 'utf-8'}));
33 | let acceptingPetriNet = BpmnToPetriNetConverter.apply(bpmnGraph);
34 | let alignedTraces = PetriNetAlignments.apply(eventLog, acceptingPetriNet);
35 | });
36 |
--------------------------------------------------------------------------------
/tests/csv_importing.test.js:
--------------------------------------------------------------------------------
1 | require("../init.js");
2 | var fs = require('fs');
3 | const os = require('os');
4 |
5 | test("CSV importing running-example", () => {
6 | let data = fs.readFileSync('examples/input_data/running-example.csv', {encoding: 'utf-8'});
7 | let eventLog = CsvImporter.apply(data);
8 | });
9 |
10 | test("CSV importing running-example_unchanged - CSV exporting", () => {
11 | let data = fs.readFileSync('examples/input_data/running-example_unchanged.csv', {encoding: 'utf-8'});
12 | let eventLog = CsvImporter.apply(data, ";", '"', "case_id", "activity", "timestamp");
13 | data = CsvExporter.apply(eventLog);
14 | let fileName = os.tmpdir() + "/" + "running-example.csv";
15 | fs.writeFileSync(fileName, data);
16 | });
17 |
18 | test("CSV importing running-example_unchanged - XES exporting", () => {
19 | let data = fs.readFileSync('examples/input_data/running-example_unchanged.csv', {encoding: 'utf-8'});
20 | let eventLog = CsvImporter.apply(data, ";", '"', "case_id", "activity", "timestamp");
21 | data = XesExporter.apply(eventLog);
22 | let fileName = os.tmpdir() + "/" + "running-example.xes";
23 | fs.writeFileSync(fileName, data);
24 | });
25 |
26 | test("XES importing running-example - XES exporting", () => {
27 | let data = fs.readFileSync('examples/input_data/running-example.xes', {encoding: 'utf-8'});
28 | let eventLog = XesImporter.apply(data);
29 | data = CsvExporter.apply(eventLog);
30 | let fileName = os.tmpdir() + "/" + "running-example2.csv";
31 | fs.writeFileSync(fileName, data);
32 | });
33 |
--------------------------------------------------------------------------------
/tests/feature_extraction.test.js:
--------------------------------------------------------------------------------
1 | require("../init.js");
2 | var fs = require('fs');
3 | const os = require('os');
4 |
5 | test("feature extraction - receipt - automatic", () => {
6 | let data = fs.readFileSync('examples/input_data/receipt.xes', {encoding: 'utf-8'});
7 | let eventLog = XesImporter.apply(data);
8 | for (let trace of eventLog.traces) {
9 | for (let eve of trace.events) {
10 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
11 | }
12 | }
13 | let features = CaseFeatures.apply(eventLog, "@@classifier", "concept:name");
14 | });
15 |
16 | test("feature extraction - receipt - manual", () => {
17 | let data = fs.readFileSync('examples/input_data/receipt.xes', {encoding: 'utf-8'});
18 | let eventLog = XesImporter.apply(data);
19 | for (let trace of eventLog.traces) {
20 | for (let eve of trace.events) {
21 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
22 | }
23 | }
24 | let features = CaseFeatures.apply(eventLog, "@@classifier", "concept:name", ["concept:name", "org:resource"], [], [], [], ["concept:name"]);
25 | });
26 |
--------------------------------------------------------------------------------
/tests/inductive_miner.test.js:
--------------------------------------------------------------------------------
1 | require("../init.js");
2 | var fs = require('fs');
3 | const os = require('os');
4 |
5 | test("Inductive Miner reviewing (IM)", () => {
6 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
7 | let eventLog = XesImporter.apply(data);
8 | for (let trace of eventLog.traces) {
9 | for (let eve of trace.events) {
10 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
11 | }
12 | }
13 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
14 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
15 | let xmlString = PnmlExporter.apply(acceptingPetriNet);
16 | acceptingPetriNet = PnmlImporter.apply(xmlString);
17 | });
18 |
19 | test("Inductive Miner reviewing (IMd)", () => {
20 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
21 | let eventLog = XesImporter.apply(data);
22 | for (let trace of eventLog.traces) {
23 | for (let eve of trace.events) {
24 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
25 | }
26 | }
27 | let frequencyDfg = FrequencyDfgDiscovery.apply(eventLog, "@@classifier");
28 | let processTree = InductiveMiner.apply(null, null, 0.2, frequencyDfg);
29 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
30 | let xmlString = PnmlExporter.apply(acceptingPetriNet);
31 | acceptingPetriNet = PnmlImporter.apply(xmlString);
32 | });
33 |
34 | test("Inductive Miner reviewing (IMf)", () => {
35 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
36 | let eventLog = XesImporter.apply(data);
37 | for (let trace of eventLog.traces) {
38 | for (let eve of trace.events) {
39 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
40 | }
41 | }
42 | let processTree = InductiveMiner.apply(eventLog, "@@classifier", 0.5);
43 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
44 | let xmlString = PnmlExporter.apply(acceptingPetriNet);
45 | acceptingPetriNet = PnmlImporter.apply(xmlString);
46 | });
47 |
48 | test("Inductive Miner receipt (IM)", () => {
49 | let data = fs.readFileSync('examples/input_data/receipt.xes', {encoding: 'utf-8'});
50 | let eventLog = XesImporter.apply(data);
51 | for (let trace of eventLog.traces) {
52 | for (let eve of trace.events) {
53 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
54 | }
55 | }
56 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
57 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
58 | let xmlString = PnmlExporter.apply(acceptingPetriNet);
59 | acceptingPetriNet = PnmlImporter.apply(xmlString);
60 | xmlString = PtmlExporter.apply(processTree);
61 | processTree = PtmlImporter.apply(xmlString);
62 | });
63 |
--------------------------------------------------------------------------------
/tests/log_skeleton.test.js:
--------------------------------------------------------------------------------
1 | require("../init.js");
2 | var fs = require('fs');
3 | const os = require('os');
4 |
5 | test("log skeleton - receipt - 0% noise", () => {
6 | let data = fs.readFileSync('examples/input_data/receipt.xes', {encoding: 'utf-8'});
7 | let eventLog = XesImporter.apply(data);
8 | for (let trace of eventLog.traces) {
9 | for (let eve of trace.events) {
10 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
11 | }
12 | }
13 | let skeleton = LogSkeletonDiscovery.apply(eventLog, "@@classifier");
14 | let skeletonConf = LogSkeletonConformanceChecking.apply(eventLog, skeleton, 0.0, "@@classifier");
15 | });
16 |
17 | test("log skeleton - receipt - 5% noise", () => {
18 | let data = fs.readFileSync('examples/input_data/receipt.xes', {encoding: 'utf-8'});
19 | let eventLog = XesImporter.apply(data);
20 | for (let trace of eventLog.traces) {
21 | for (let eve of trace.events) {
22 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
23 | }
24 | }
25 | let skeleton = LogSkeletonDiscovery.apply(eventLog, "@@classifier");
26 | let skeletonConf = LogSkeletonConformanceChecking.apply(eventLog, skeleton, 0.05, "@@classifier");
27 | });
28 |
--------------------------------------------------------------------------------
/tests/petri_evaluation.test.js:
--------------------------------------------------------------------------------
1 | require("../init.js");
2 | var fs = require('fs');
3 | const os = require('os');
4 |
5 | test("TBR fitness reviewing", () => {
6 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
7 | let eventLog = XesImporter.apply(data);
8 | for (let trace of eventLog.traces) {
9 | for (let eve of trace.events) {
10 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
11 | }
12 | }
13 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
14 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
15 | let fitnessTbr = TbrFitness.apply(eventLog, acceptingPetriNet, "@@classifier");
16 | });
17 |
18 | test("Alignments fitness reviewing", () => {
19 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
20 | let eventLog = XesImporter.apply(data);
21 | for (let trace of eventLog.traces) {
22 | for (let eve of trace.events) {
23 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
24 | }
25 | }
26 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
27 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
28 | let fitnessAli = AlignmentsFitness.apply(eventLog, acceptingPetriNet, "@@classifier");
29 | });
30 |
31 | test("TBR generalization reviewing", () => {
32 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
33 | let eventLog = XesImporter.apply(data);
34 | for (let trace of eventLog.traces) {
35 | for (let eve of trace.events) {
36 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
37 | }
38 | }
39 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
40 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
41 | let generalization = GeneralizationTbr.apply(eventLog, acceptingPetriNet, "@@classifier");
42 | });
43 |
44 | test("TBR simplicity reviewing", () => {
45 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
46 | let eventLog = XesImporter.apply(data);
47 | for (let trace of eventLog.traces) {
48 | for (let eve of trace.events) {
49 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
50 | }
51 | }
52 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
53 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
54 | let simplicity = SimplicityArcDegree.apply(acceptingPetriNet);
55 | });
56 |
57 | test("ETConformance precision running-example", () => {
58 | let data = fs.readFileSync('examples/input_data/running-example.xes', {encoding: 'utf-8'});
59 | let eventLog = XesImporter.apply(data);
60 | let processTree = InductiveMiner.apply(eventLog);
61 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
62 | let precision = ETConformance.apply(eventLog, acceptingPetriNet);
63 | });
--------------------------------------------------------------------------------
/tests/petri_replay.test.js:
--------------------------------------------------------------------------------
1 | require("../init.js");
2 | var fs = require('fs');
3 | const os = require('os');
4 |
5 | test("Inductive Miner + Alignments reviewing (IM)", () => {
6 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
7 | let eventLog = XesImporter.apply(data);
8 | for (let trace of eventLog.traces) {
9 | for (let eve of trace.events) {
10 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
11 | }
12 | }
13 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
14 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
15 | let alignedTraces = PetriNetAlignments.apply(eventLog, acceptingPetriNet, "@@classifier");
16 | });
17 |
18 |
19 | test("Inductive Miner + TBR reviewing (IM)", () => {
20 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
21 | let eventLog = XesImporter.apply(data);
22 | for (let trace of eventLog.traces) {
23 | for (let eve of trace.events) {
24 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
25 | }
26 | }
27 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
28 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
29 | let replayedTraces = TokenBasedReplay.apply(eventLog, acceptingPetriNet, "@@classifier");
30 | });
31 |
--------------------------------------------------------------------------------
/tests/random_variables.test.js:
--------------------------------------------------------------------------------
1 | require("../init.js");
2 | var fs = require('fs');
3 | const os = require('os');
4 |
5 | test("exponential random variable", () => {
6 | let rv = ExponentialRandomVariable.estimateParameters([1.9, 2, 2.1]);
7 | let rvMean = rv.getMean();
8 | let rvVariance = rv.getVariance();
9 | let rvMode = rv.getMode();
10 | let pdfMean = rv.pdf(rv.getMean());
11 | let cdfMean = rv.cdf(rv.getMean());
12 | let pdfMedian = rv.pdf(rv.getMedian());
13 | let cdfMedian = rv.cdf(rv.getMedian());
14 | let quantile5 = rv.getQuantile(0.5);
15 | let quantile75 = rv.getQuantile(0.75);
16 | let quantile9 = rv.getQuantile(0.9);
17 | let simValue = rv.getValue();
18 | });
19 |
20 | test("normal random variable", () => {
21 | let rv = NormalRandomVariable.estimateParameters([1.9, 2, 2.1]);
22 | let rvMean = rv.getMean();
23 | let rvVariance = rv.getVariance();
24 | let rvMode = rv.getMode();
25 | let pdfMean = rv.pdf(rv.getMean());
26 | let cdfMean = rv.cdf(rv.getMean());
27 | let pdfMedian = rv.pdf(rv.getMedian());
28 | let cdfMedian = rv.cdf(rv.getMedian());
29 | let quantile5 = rv.getQuantile(0.5);
30 | let quantile75 = rv.getQuantile(0.75);
31 | let quantile9 = rv.getQuantile(0.9);
32 | let simValue = rv.getValue();
33 | });
34 |
35 | test("log-normal random variable", () => {
36 | let rv = LogNormalRandomVariable.estimateParameters([1.9, 2, 2.1]);
37 | let rvMean = rv.getMean();
38 | let rvVariance = rv.getVariance();
39 | let rvMode = rv.getMode();
40 | let pdfMean = rv.pdf(rv.getMean());
41 | let cdfMean = rv.cdf(rv.getMean());
42 | let pdfMedian = rv.pdf(rv.getMedian());
43 | let cdfMedian = rv.cdf(rv.getMedian());
44 | let quantile5 = rv.getQuantile(0.5);
45 | let quantile75 = rv.getQuantile(0.75);
46 | let quantile9 = rv.getQuantile(0.9);
47 | let simValue = rv.getValue();
48 | });
49 |
50 | test("gamma random variable", () => {
51 | let rv = GammaRandomVariable.estimateParameters([1.9, 2, 2.1]);
52 | let rvMean = rv.getMean();
53 | let rvVariance = rv.getVariance();
54 | let rvMode = rv.getMode();
55 | let pdfMean = rv.pdf(rv.getMean());
56 | let simValue = rv.getValue();
57 | });
58 |
59 | test("uniform random variable", () => {
60 | let rv = UniformRandomVariable.estimateParameters([1.9, 2, 2.1]);
61 | let rvMean = rv.getMean();
62 | let rvVariance = rv.getVariance();
63 | let rvMode = rv.getMode();
64 | let pdfMean = rv.pdf(rv.getMean());
65 | let cdfMean = rv.cdf(rv.getMean());
66 | let pdfMedian = rv.pdf(rv.getMedian());
67 | let cdfMedian = rv.cdf(rv.getMedian());
68 | let quantile5 = rv.getQuantile(0.5);
69 | let quantile75 = rv.getQuantile(0.75);
70 | let quantile9 = rv.getQuantile(0.9);
71 | let simValue = rv.getValue();
72 | });
73 |
74 | test("exponentially modified gaussian random variable", () => {
75 | let rv = ExponentiallyModifiedGaussian.estimateParameters([1.9, 2, 2.1]);
76 | let rvMean = rv.getMean();
77 | let rvVariance = rv.getVariance();
78 | let pdfMean = rv.pdf(rv.getMean());
79 | let simValue = rv.getValue();
80 | });
--------------------------------------------------------------------------------
/tests/visualization.test.js:
--------------------------------------------------------------------------------
1 | require("../init.js");
2 | var fs = require('fs');
3 | const os = require('os');
4 |
5 | test("frequency DFG visualization reviewing", () => {
6 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
7 | let eventLog = XesImporter.apply(data);
8 | for (let trace of eventLog.traces) {
9 | for (let eve of trace.events) {
10 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
11 | }
12 | }
13 | let frequencyDfg = FrequencyDfgDiscovery.apply(eventLog);
14 | let gv = FrequencyDfgGraphvizVisualizer.apply(frequencyDfg);
15 | });
16 |
17 | test("performance DFG visualization reviewing", () => {
18 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
19 | let eventLog = XesImporter.apply(data);
20 | for (let trace of eventLog.traces) {
21 | for (let eve of trace.events) {
22 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
23 | }
24 | }
25 | let performanceDfg = PerformanceDfgDiscovery.apply(eventLog);
26 | let gv = PerformanceDfgGraphvizVisualizer.apply(performanceDfg);
27 | });
28 |
29 | test("process tree visualization reviewing", () => {
30 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
31 | let eventLog = XesImporter.apply(data);
32 | for (let trace of eventLog.traces) {
33 | for (let eve of trace.events) {
34 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
35 | }
36 | }
37 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
38 | let gv = ProcessTreeVanillaVisualizer.apply(processTree);
39 | });
40 |
41 | test("Petri visualization reviewing", () => {
42 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
43 | let eventLog = XesImporter.apply(data);
44 | for (let trace of eventLog.traces) {
45 | for (let eve of trace.events) {
46 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
47 | }
48 | }
49 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
50 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
51 | let gv = PetriNetVanillaVisualizer.apply(acceptingPetriNet);
52 | });
53 |
54 | test("Petri visualization reviewing - Frequency decoration", () => {
55 | let data = fs.readFileSync('examples/input_data/reviewing.xes', {encoding: 'utf-8'});
56 | let eventLog = XesImporter.apply(data);
57 | for (let trace of eventLog.traces) {
58 | for (let eve of trace.events) {
59 | eve.attributes["@@classifier"] = new Attribute(eve.attributes["concept:name"].value + "+" + eve.attributes["lifecycle:transition"].value);
60 | }
61 | }
62 | let processTree = InductiveMiner.apply(eventLog, "@@classifier");
63 | let acceptingPetriNet = ProcessTreeToPetriNetConverter.apply(processTree);
64 | let tbrResults = TokenBasedReplay.apply(eventLog, acceptingPetriNet, "@@classifier");
65 | let gv = PetriNetFrequencyVisualizer.apply(acceptingPetriNet, tbrResults);
66 | });
--------------------------------------------------------------------------------
/tests/xes_importing.test.js:
--------------------------------------------------------------------------------
1 | require("../init.js");
2 | var fs = require('fs');
3 | const os = require('os');
4 |
5 | test("XES importing running-example", () => {
6 | let data = fs.readFileSync('examples/input_data/running-example.xes', {encoding: 'utf-8'});
7 | let eventLog = XesImporter.apply(data);
8 | let xmlStri = XesExporter.apply(eventLog);
9 | let fileName = os.tmpdir() + "/" + "running-example.xes";
10 | fs.writeFileSync(fileName, xmlStri);
11 | data = fs.readFileSync(fileName, {encoding: 'utf-8'});
12 | eventLog = XesImporter.apply(data);
13 | });
14 |
15 | test("XES importing receipt", () => {
16 | let data = fs.readFileSync('examples/input_data/receipt.xes', {encoding: 'utf-8'});
17 | let eventLog = XesImporter.apply(data);
18 | let xmlStri = XesExporter.apply(eventLog);
19 | let fileName = os.tmpdir() + "/" + "receipt.xes";
20 | fs.writeFileSync(fileName, xmlStri);
21 | data = fs.readFileSync(fileName, {encoding: 'utf-8'});
22 | eventLog = XesImporter.apply(data);
23 | });
24 |
--------------------------------------------------------------------------------