Example: Generate PetriNet models using EMG

pre {
  var id = 0;
  var num_nets = 1;
  // Two random numbers 0..total
  var quant = nextAddTo(2, total).sortBy(q | q);
  var num_p = 1 + quant.at(0);  // Min 2 Places
  // For each transition we need two arcs
  var num_t = (quant.at(1)/3).ceiling();

$instances num_nets
@list net
operation PetriNet create() {
  self.name = "RandomActions";

$instances num_p
operation Place create() {
  self.name = nextFromList("nouns") + " " + nextFromList("places");

$instances num_t
operation Transition create() {
  self.name = nextFromList("nouns") + " " + nextFromList("transitions");

// Create an arc to connect the transition to 2 places, make sure the places and transitions use the same noun
$probability 1/num_nets
pattern Transition
    from: net.transitions
    onmatch {
      var size = 0;
      var nound = tra.name.split(" ").at(0);
      var matchingPlaces = Place.all().select(p | nound.isSubstringOf(p.name));var freeSources = matchingPlaces.select(p | p.incoming.size() == size);
      while (freeSources.isEmpty()) {
        size += 1;
        freeSources = matchingPlaces.select(p | p.incoming.size() == size);
      size = 0;
      var freeTarget = matchingPlaces.select(p | p.incoming.size() == size);
      while (freeTarget.isEmpty()) {
        size += 1;
        freeTarget = matchingPlaces.select(p | p.incoming.size() == size);
      var source = nextFromCollection(freeSources);
      var target = nextFromCollection(freeTarget);
      var a1:Arc = new PlaceToTransArc();
      a1.weight = nextInteger(10);
      a1.source = source;
      a1.target = tra;
      var a2:Arc = new TransToPlaceArc();
      a1.weight = nextInteger(10);
      a2.source = tra;
      a2.target = target;

post {
@namespace(uri="http://www.york.ac.uk/qvt/examples/0.1/PetriNet", prefix="petrinet")
package PetriNet;

abstract class Element {
  !ordered attr String[1] name;

class PetriNet extends Element {
  val Place[+] places;
  val Transition[*] transitions;
  val Arc[*] arcs;

class Place extends Element {
  !ordered ref TransToPlaceArc[*]#target incoming;
  !ordered ref PlaceToTransArc[*]#source outgoing;

class Transition extends Element {
  !ordered ref PlaceToTransArc[+]#target incoming;
  !ordered ref TransToPlaceArc[+]#source outgoing;

class Arc {
  !ordered attr int[1] weight;

class PlaceToTransArc extends Arc {
  !ordered ref Place[1]#outgoing source;
  !ordered ref Transition[1]#incoming target;

class TransToPlaceArc extends Arc {
  !ordered ref Transition[1]#outgoing source;
  !ordered ref Place[1]#incoming target;

Clone Epsilon's Git repository and then:

Once you have checked out/imported the code, to run the example you need to go through the following steps:

  1. register all .ecore metamodels in the org.eclipse.epsilon.examples.metamodels project (select all of them and then right click and select Register EPackages)
  2. register any .ecore metamodels in the org.eclipse.epsilon.examples.emg.petrinet project
  3. right click the .launch file in the org.eclipse.epsilon.examples.emg.petrinet project
  4. select Run as... and click the first item in the menu that pops up

What's this?

In this example we demonstrate how to generate PetriNet elements and how to define relations between them.

What are .emf files?

.emf files are Ecore metamodels expressed using the Emfatic textual syntax.

More examples...

Epsilon Object Language
Epsilon Transformation Language
Epsilon Generation Language
Epsilon Validation Language
Epsilon Merging Language
Epsilon Flock
Epsilon Model Generation Language
Epsilon Pattern Language
Combining the Epsilon Languages

Even more examples...

More examples are available in the examples folder of the Git repository.