Create automaton#

This section illustrates how to create and populate automaton using the Python API. One can start by creating a new project, an operator, a diagram, then automaton, states, transitions, forks with their branch transitions.

Create a new project#

Using the ScadeOne class, one can create a new project:

from ansys.scadeone.core import ScadeOne

project_path = Path(r"project1\project1.sproj")

app = ScadeOne()

project = app.new_project(project_path)

Once the project is created, add a new module:

# create a module body

And an operator with its inputs in this module:

# add an operator with inputs
operator_def = module.add_operator_definition("operator_def")
operator_def.add_input("c", "bool")
operator_def.add_input("u", "bool")
operator_def.add_input("d", "bool")
operator_def.add_input("r", "bool")
operator_def.add_input("l", "bool")

Create a new diagram#

Using the OperatorDefinition class, add a new diagram to the operator previously created:

# Diagram with automaton

Create a new automaton#

Automata can be created in the scope of Diagram class.

diagram = operator_def.add_diagram()

Populate an automaton#

The StateMachine class offers the necessary methods to populate an automaton. The order of creation is important. For instance, states must be created before transitions, and transitions before forks.

Start by creating all automaton states:

# states
stop = automaton.add_state("Stop", is_initial=True)
up = automaton.add_state("Up")
down = automaton.add_state("Down")
left = automaton.add_state("Left")
right = automaton.add_state("Right")

Once all states are created, transitions between them can be added:

# transitions
up_to_stop = automaton.add_strong_transition(up, stop, 1, "not u")
down_to_stop = automaton.add_strong_transition(down, stop, 1, "not d")
left_to_stop = automaton.add_strong_transition(left, stop, 1, "not l")
right_to_stop = automaton.add_strong_transition(right, stop, 1, "not r")
stop_to_up = automaton.add_strong_transition(stop, up, 1, "unlock")
stop_to_center = automaton.add_strong_transition(stop, center, 2, "c")

A Fork object can be created from one of the transitions previously created:

# fork

This function returns the created fork as well as the default outgoing transition created in the same time.

Outgoing transition kind is the same as the transition requesting the fork creation (that is to say weak or strong).

Once the fork is created, additional branches can be added:

fork, fork_to_up = stop_to_up.add_fork("u")
fork.add_fork_transition(down, 2, "d")
fork.add_fork_transition(left, 3, "l")

Note

Other forks can be created from any fork transition.

def fork_from_fork(automaton) -> None:
    fork, fork_to_up = stop_to_up.add_fork("u")
    # Another fork is added from the default outgoing transition
    other_fork, other_fork_to_up = fork_to_up.add_fork()

Finally, save the project, and look at the generated code:


project.save()

for m in project_path.parent.glob("assets/*.swan*"):
    print(f"{'=' * 20}\nModule: {m.name}\n{'=' * 20}")

Complete example#

This is the complete script presenting an automaton creation with its content.


import shutil
from pathlib import Path

from ansys.scadeone.core import ScadeOne

project_path = Path(r"project1\project1.sproj")

app = ScadeOne()

project = app.new_project(project_path)

# create a module body
module = project.add_module_body("m_automata")

# add an operator with inputs
operator_def = module.add_operator_definition("operator_def")
operator_def.add_input("c", "bool")
operator_def.add_input("u", "bool")
operator_def.add_input("d", "bool")
operator_def.add_input("r", "bool")
operator_def.add_input("l", "bool")
operator_def.add_input("unlock", "bool")

# Diagram with automaton
diagram = operator_def.add_diagram()
automaton = diagram.add_automaton("automaton0")

# states
stop = automaton.add_state("Stop", is_initial=True)
up = automaton.add_state("Up")
down = automaton.add_state("Down")
left = automaton.add_state("Left")
right = automaton.add_state("Right")
center = automaton.add_state("Center")

# transitions
up_to_stop = automaton.add_strong_transition(up, stop, 1, "not u")
down_to_stop = automaton.add_strong_transition(down, stop, 1, "not d")
left_to_stop = automaton.add_strong_transition(left, stop, 1, "not l")
right_to_stop = automaton.add_strong_transition(right, stop, 1, "not r")
stop_to_up = automaton.add_strong_transition(stop, up, 1, "unlock")
stop_to_center = automaton.add_strong_transition(stop, center, 2, "c")
center_to_stop = automaton.add_strong_transition(center, stop, 1, "not c")

# fork
fork, fork_to_up = stop_to_up.add_fork("u")
fork.add_fork_transition(down, 2, "d")
fork.add_fork_transition(left, 3, "l")
fork.add_fork_transition(right, 4, "r")

project.save()

for m in project_path.parent.glob("assets/*.swan*"):
    print(f"{'=' * 20}\nModule: {m.name}\n{'=' * 20}")

Overview#

In this example project, generated automaton looks like the following:

../../../_images/diagram.png