Getting Started with BRSs
This guide provides a complete walkthrough on how to simulate bigraphical reactive systems (BRS). The following aspects are covered:
- Specification of the signature
- Specification of the initial state
- Specification of the reaction rules
This is done using a running example.
Scenario Description​
The running example describes a "system", where a user can put a fruit into a basket.
The environment of this "system" comprises a Table
, a Basket
, some generic Fruit
entities and a User
.
Only one high-level action exists, namely, picking a fruit and placing it into the available Basket
.
This simple system description might sound simple but when more users and baskets are introduced the problem becomes more challenging to manage.
This type of problem involves concurrent behavior and dynamic allocation and arises from a category of complex problems in the field of computer science that are generally hard to solve.
In the following, we are going to translate this scenario description into a BRS-based specification and simulate its behavior. That allows us to observe the overall behavior of the system and also take snapshots of the states over time.
The Signature​
public static DefaultDynamicSignature createSignature() {
DynamicSignatureBuilder defaultBuilder = pureSignatureBuilder();
defaultBuilder
.addControl("User", 1, ControlStatus.ATOMIC)
.addControl("Basket", 1)
.addControl("Fruit", 1, ControlStatus.ATOMIC)
.addControl("Table", 0)
;
return defaultBuilder.create();
}
Because the User
, Basket
and Fruit
entities will have to synchronize during the pick and place task, they all have arity 1.
That is, they can connect to a link (also called channel) to indicate a synchronisation action on distributed locations.
The property ATOMIC
indicates that this entities cannot contain any children.
The Initial State of the System​
The User
and Basket
are not connected to any link. Their ports are idle.
tip
Bigraphs can be exported using the Visualization Module of Bigraph Framework. See, for example, Exporting Bigraphs as Images on how to export a bigraph as PNG using the DOT format.
public static PureBigraph createAgent() throws InvalidConnectionException {
return pureBuilder(createSignature()).createRoot()
.addChild("User")
.addChild("Table").down()
.addChild("Basket")
.addChild("Fruit", "f")
.addChild("Fruit", "f")
.addChild("Fruit", "f")
.createBigraph();
}
Reaction Rules​
The high-level pick and place action of our system under consideration has to be decomposed into four smaller "interlocking" steps.
Each step ensures that the entire action can actually be executed.
This is done by acquiring a connection first to the Fruit
entities (if one is available), and afterward also to the Basket
entity as long as nothing is connected to it.
This can also be thought as a "locking" mechanism to handle concurrency.
The last rule finally transfers a Fruit
entity to the Basket
entity.
Since all Fruit
s share the same link f, any fruit will be picked as long one is available.
It can be thought of an m:1 queue (input size m, output size 1).
The role of the User
in this system is to provide an indication of who has performed the action.
The fruit transfer rule could have been written also without the user.
The last rule simply releases all "locks" so that the procedure can be repeated with any other User
and Fruit
in the system.
note
The amount of details of a specification is domain-specific and depends on the specific use case.
Reaction Rule 1: Lock the Fruit​
A "lock" is acquired on any Fruit
on the Table
by a "free" User
:
public static ParametricReactionRule<PureBigraph> createRR1() throws InvalidReactionRuleException, InvalidConnectionException {
PureBigraphBuilder<DefaultDynamicSignature> b1 = pureBuilder(createSignature());
PureBigraphBuilder<DefaultDynamicSignature> b2 = pureBuilder(createSignature());
b1.createRoot()
.addChild("User")
.addChild("Table").down()
.addChild("Fruit", "f").addSite()
;
b2.createRoot()
.addChild("User", "f")
.addChild("Table").down()
.addChild("Fruit", "f").addSite()
;
PureBigraph redex = b1.createBigraph();
PureBigraph reactum = b2.createBigraph();
ParametricReactionRule<PureBigraph> rr = new ParametricReactionRule<>(redex, reactum).withLabel("rr1");
return rr;
}
A User
is "free" as long as its single port is not connected to any open link. The right-hand side assigns a Fruit
to a User
.
Reaction Rule 2: Lock the Basket​
A "lock" is acquired on the Basket
if a User
has already ensured to receive a Fruit
:
public static ParametricReactionRule<PureBigraph> createRR2() throws InvalidReactionRuleException, InvalidConnectionException {
PureBigraphBuilder<DefaultDynamicSignature> b1 = pureBuilder(createSignature());
PureBigraphBuilder<DefaultDynamicSignature> b2 = pureBuilder(createSignature());
b1.createRoot()
.addChild("User", "f")
.addChild("Table").down()
.addChild("Fruit", "f").addSite()
.addChild("Basket").down().addSite()
;
b2.createRoot()
.addChild("User", "f")
.addChild("Table").down()
.addChild("Fruit", "f").addSite()
.addChild("Basket", "f").down().addSite()
;
PureBigraph redex = b1.createBigraph();
PureBigraph reactum = b2.createBigraph();
ParametricReactionRule<PureBigraph> rr = new ParametricReactionRule<>(redex, reactum).withLabel("rr2");
return rr;
}
If this rule matches the setup is complete.
Reaction Rule 3: Transfer the Fruit​
The following rule describes the actual pick and place task of the system.
A Fruit
on the Table
is transferred to the Basket
of the Table
:
public static ParametricReactionRule<PureBigraph> createRR3() throws InvalidReactionRuleException, InvalidConnectionException {
PureBigraphBuilder<DefaultDynamicSignature> b1 = pureBuilder(createSignature());
PureBigraphBuilder<DefaultDynamicSignature> b2 = pureBuilder(createSignature());
b1.createRoot()
.addChild("User", "f")
.addChild("Table").down()
.addChild("Fruit", "f").addSite()
.addChild("Basket", "f").down().addSite()
;
b2.createRoot()
.addChild("User", "f")
.addChild("Table").down()
.addSite()
.addChild("Basket", "f").down().addChild("Fruit", "f").addSite()
;
PureBigraph redex = b1.createBigraph();
PureBigraph reactum = b2.createBigraph();
ParametricReactionRule<PureBigraph> rr = new ParametricReactionRule<>(redex, reactum).withLabel("rr3");
return rr;
}
The Fruit
is transferred from the Table
to the Basket
still keeping the reference.
Reaction Rule 4: Release Locks​
The transferred Fruit
looses the reference to the other Fruit
s on the Table
.
Specifically, it is not connected anymore to the link named f.
Also, the User
and Basket
are now "free" to connect again after the rule was fired.
public static ParametricReactionRule<PureBigraph> createRR4() throws InvalidReactionRuleException, InvalidConnectionException {
PureBigraphBuilder<DefaultDynamicSignature> b1 = pureBuilder(createSignature());
PureBigraphBuilder<DefaultDynamicSignature> b2 = pureBuilder(createSignature());
b1.createRoot()
.addChild("User", "f")
.addChild("Table").down().addSite()
.addChild("Basket", "f").down().addChild("Fruit", "f").addSite()
;
b2.createOuterName("f");
b2.createRoot()
.addChild("User")
.addChild("Table").down().addSite()
.addChild("Basket").down().addChild("Fruit").addSite()
;
PureBigraph redex = b1.createBigraph();
PureBigraph reactum = b2.createBigraph();
ParametricReactionRule<PureBigraph> rr = new ParametricReactionRule<>(redex, reactum).withLabel("rr4");
return rr;
}
Interfaces of Reaction Rules
It is important to note that the redex and reactum of a rule are required to have the same outer faces. Thus, the idle outer name f is still needed in the reactum. (Their inner face, i.e., sites, can be different.)
Release all "locks".
Bigraphical Reactive System Specification​
The agent and the rules are collected to form a reactive system:
Declaration​
PureReactiveSystem rs = new PureReactiveSystem();
rs.setAgent(createAgent());
rs.addReactionRule(createRR1());
rs.addReactionRule(createRR2());
rs.addReactionRule(createRR3());
rs.addReactionRule(createRR4());
assert rs.isSimple();
Execution via Model Checking​
This specification can be executed by the model checker class org.bigraphs.framework.simulation.modelchecking.PureBigraphModelChecker
, which basically performs an exhaustive breadth-first search on the initial state.
Correctness properties via bigraphical predicates can simply be omitted.
BRS Model Checking
Refer to Verification to get to know more about how to use a BRS specification for model checking.
ModelCheckingOptions opts = ModelCheckingOptions.create();
opts
.and(transitionOpts()
.setMaximumTransitions(100)
.setMaximumTime(60)
.create()
)
.and(ModelCheckingOptions.exportOpts()
.setReactionGraphFile(Paths.get(TARGET_DUMP_PATH, "transition_graph.png").toFile())
.setPrintCanonicalStateLabel(false)
.setOutputStatesFolder(Paths.get(TARGET_DUMP_PATH, "states/").toFile())
.create()
)
;
PureBigraphModelChecker modelChecker = new PureBigraphModelChecker(
rs,
BigraphModelChecker.SimulationStrategy.Type.BFS,
opts);
modelChecker.execute();
Termination​
info
The model checking procedure automatically finishes when the system's behavior is finite, or the overall system's behavior is a cycle.
Convergence Criteria
Note that the model checking process may not terminate if the system has infinite behavior. Therefore, it is advised to set constraints such as the maximum allowed duration or maximum number of transitions to explore.
Debugging the Transition System​
The output path of the transition system can be specified in the model checking options object (see above). The transition system is a PNG graphic file and shows all possible states and actions for visual exploration and debugging:
The system has three final states and five solutions. Each final state is the same: All Fruit
s are in the Basket
. However, how to reach this solution is different as can be seen by the different paths. The shortest path provides a solution where all Fruit
s are placed into the Basket
one-by-one without calling the release action in-between but only once before the final state. This solution is, however, unfair if multiple User
s are involved.
Reaction Graph Object​
Another way is by using the reaction graph instance of type ReactionGraph
of the model checker object:
ReactionGraph<PureBigraph> reactionGraph = modelChecker.getReactionGraph();
The class ReactionGraph
inherits from AbstractTransitionSystem
and implements the standard methods for transition systems.
The concrete implementation, however, defines the actual data structure of the transition system.
Internally, the reaction graph manages an instance of org.jgrapht.Graph
with LabeledNode
as states and LabeledEdge
as transition relations.
It is a simple directed graph (allowing multiple edges, allowing self loops).
Both the LabeledNode
and LabeledEdge
class provide getter-methods that return string labels, which denote the name of the bigraph state and rule, respectively, added to the reactive system container.
Programmatic Execution​
By acquiring a bigraph matcher instance, arbitrary rule execution logic can be implemented:
ParametricReactionRule<PureBigraph> rr11 = createRR1();
AbstractBigraphMatcher<PureBigraph> matcher = AbstractBigraphMatcher.create(PureBigraph.class);
MatchIterable<BigraphMatch<PureBigraph>> match = matcher.match(agent, rr11);
Iterator<BigraphMatch<PureBigraph>> iterator = match.iterator();
while (iterator.hasNext()) {
BigraphMatch<PureBigraph> next = iterator.next();
PureBigraph result = rs.buildParametricReaction(agent, next, rr11);
// do something with `result`
}
The rewrite functionality is provided by the concrete org.bigraphs.framework.core.reactivesystem.ReactiveSystem
instance.