Skip to main content
Jump to: navigation, search

VIATRA/DSE/UserGuide/API

< VIATRA‎ | DSE
Revision as of 14:47, 29 September 2014 by Nasz013.gmail.com (Talk | contribs) (Created page with "= Usage of the VIATRA-DSE API = This page presents the basic API based on an example. After reading this you will be able to define a DSE problem including transformation rul...")

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Usage of the VIATRA-DSE API

This page presents the basic API based on an example. After reading this you will be able to define a DSE problem including transformation rules and goals and run it with different built in strategies.

It is highly recommended to get familiar with the EMF and EMF-IncQuery frameworks first as they are essential for using VIATRA-DSE.

API

VIATRA-DSE depends on the Eclipse platform thus using it one should create a plugin project and add the org.eclipse.viatra.dse.base plugin as a dependency for the plugin project. To start using the framework type this line of code:

DesignSpaceExplorer dse = new DesignSpaceExplorer();

Defining the domain

The first thing required is a metamodel or ecore model created with EMF and an initial model. See the code below.

EObject root = createInitialModel();
dse.setStartingModel(root);
 
// You can also define the metamodel however it is not obligatory
dse.addMetaModel(MetamodelEPackage.eINSTANCE);

Transformation rules

Rules tells the engine how the initial model can be modified and treated as atomic steps. They consist of a left hand side (LHS or condition) and a right hand side (RHS) . The LHS is always an IncQuery pattern (or a model query) while the RHS is simple Java code. To define such a rule an instance of the TransformationRule class must be created.

Let's say a pattern named myPattern with two parameters is already available and can be used as a LHS.

TransformationRule<MyPatternMatch> rule = 
new TransformationRule<MyPatternMatch>(MyPatternQuerySpecification.instance(), new MyPatternMatchProcessor() {
    @Override
    public void process(ExampleEObject p1, ExampleEObject p2) {
        // RHS manipulates the EMF model
        p1.setFriend(p2);
    }
});
 
dse.addTransformation(rule);

Note 1: A rule can also have a name via the "setName(String)" method.

Note 2: It's forbidden to apply two rules with same LHS to be able to distinguish them based on the pattern. Using the IncQuery keyword find can avoid code duplication.

Note 3: It's a good practice to use static factory methods in separate class for creating rules.

Goals

Goals are simple IncQuery patterns and can be added to the problem with a simple method call:

dse.addGoalPattern(new PatternWithCardinality(MyGoalPatternQuerySpecifiaction.instance()));

The default behavior of the framework is checking all goals and if they are all fulfilled (have at least one match in the current model) model state is marked as a solution state.

State coding

A state coder is also necessary for the engine to start the exploration. For any more detail about this please see the state coding section of this wiki.

ArrayList<EPackage> metaModelPackages = new ArrayList<EPackage>();
metaModelPackages.add(MetamodelEPackage.eINSTANCE);
dse.setSerializerFactory(new IncrementalGraphHasherFactory(metaModelPackages));

Starting the exploration

To start the exploration a strategy must also be defined. Static methods of the "Strategies" class can be used to create a built in strategy like depth first search. The exploration runs in separate threads hence there is a boolean parameter whether to wait for the exploration process.

boolean waitForTermination = true;
dse.startExploration(Strategies.createDFSStrategy(), waitForTermination);

The second parameter can also be an integer for timeout, which if elapses the exploration will stop as soon as possible.

Using the results

A solution of the exploration is a trajectory, a sequence of rules which if applied to the initial model, it satisfies the goals. It's important that the same goal state can be reached by different trajectories and this is also represented by the results: an instance of "Solution" class can have multiple "SolutionTrajectory" instances. A solution has at least one solution trajectory, but nothing more can be expected, as it is heavily depends on the traversal strategy and the actual traversal of the state space. The "SolutionTrajectory" can be used to transform the given model (should be the initial model) based on the trajectory.

Collection<Solution> solutions = dse.getAllSolutions();
if (!solutions.isEmpty()) {
    Solution solution = dse.getAllSolutions().iterator().next();
    SolutionTrajectory solutionTrajectory = solution.getArbitraryTrajectory();
    // Transform the model
    solutionTrajectory.setModel(theInitialModel);
    solutionTrajectory.doTransformation();
}


Other functions of the API

Global constraints

If there are any global constraints added they must be satisfied in all of the intermediate model state of trajectory. If a global constraint is not satisfied the engine won't allow the exploration to go further from that state. It can be useful to reduce the state space, but it can also be a goal of the problem. Defining a global constraint is very similar to defining a goal patter.

dse.addConstraint(new PatternWithCardinality(MyGlobalConstraintQuerySpecifiaction.instance()));

Parallel execution

The engine allows the traversal strategy to explore the state space with multiple threads. By default it allows a number of threads equal to the number of logical cores in the processor. It can be overridden with the following code:

dse.setMaxNumberOfThreads(1);

Examples

Coming soon.

Back to the top