1 Introduction

Modeling and simulation are used by engineers to design, probe and verify their systems before construction, thereby reducing design flaws and increasing the development speed. From large monolithic installations such as oil platforms to wide, distributed networks (e.g. electrical power grids), to intricate robotic designs for medical applications, the use of these modeling techniques is indispensable. To aid the process of model creation, system engineers rely on a broad set of formalisms, languages and tools. The ever-growing diversity allows expert modellers to choose the most appropriate formalism for their particular system, and even use a combination of different languages to model the various aspects of their system. Modern modeling platforms therefore often support the choice between different formalisms and languages (e.g. Matlab Simulink [58]) or even encourage the use of several modeling paradigms in concert (e.g. Ptolemy II [70]). These developments enable the creation of large-scale and high-performance models but require a lot of experience with the individual languages and a good knowledge of the underlying modeling principles. The required knowledge, the steep learning curves and the often significant financial investment are major deterrents for the adoption of modern systems engineering best practices by non-expert application creators and developers of small-scale installations.

In recent years, consciousness of this problem led to an increased interest in domain-specific modeling solutions. Thus, existing products are modified to more closely represent the needed system features, rather than generic concepts. The semantic gap describes this “distance” between a model and the original installation. Wide gaps are often the result of using tools or languages that cannot properly represent the system’s features and frequently demand elaborate workarounds. One common approach is the use of DSLs, languages dedicated to creating models at an abstraction level where domain users are able to model their systems themselves without having to learn another language.

In this article we describe the development of the Continuous REactive SysTems language (CREST), a domain-specific modeling language (DSML) [69] for the hybrid modeling of cyber-physical systems (CPSs). The language targets the creation of CPS models of small-scale, custom systems such as smarthome applications, automated gardening setups and office automation installations. Usually, these CPSs are compositions of off-the-shelve components that interact through the transfer of physical resources such as electricity, heat and water. CREST supports creators of such systems by putting a focus on usability and simplicity. Its target audience includes novice modellers, private developers as well as system creators and maintainers who want to add trust into their existing applications. For this purpose, the DSL joins a system’s behavioural and structural concerns inside the same concrete syntax, which lowers its entry-barrier and allows systems engineering newcomers to quickly take advantage of the benefits of simulation and verification. Throughout the paper, we elaborate on our language development methodology, starting from the requirements analysis and evaluation of existing solutions, to the definition of the language’s abstract syntax and formal semantics, to the implementation of the language itself. In the process, we describe particular design choices such as the reuse and combination of well-known concepts from existing formalisms into a coherent language. This method builds upon a vital formal syntax and semantics description that asserts a sound combination of the various language aspects, without which, it would be much more difficult to perform advanced modeling tasks such as simulation and verification. The DSL’s formalisation itself is provided as an appendix to this article. CREST ’s pragmatism is manifested in the form of crestdsl, an internal DSL implementation based on the Python general-purpose programming language (GPPL). Employing a widespread programming language increases CREST ’s usability by allowing modellers to rely on popular development environments and established execution platforms that they are already familiar with. This lowers the entry bar to modeling, as users prefer to continue working with the tools they already know [73]. Even though it will probably not be required for most audiences, crestdsl ’s GPPL-basis additionally allows power-users to extend the DSL using scripting application programming interfaces (APIs), interact with common data analysis packages and create object libraries to increase development speed and reusability.

The rest of this paper is organised as follows: Sect. 2 provides the scientific background on the use of DSLs, highlights examples and provides detailed comparisons of different approaches. Section 3 dives into the methodology that we followed for the creation of CREST, a formalism for the specification of hybrid CPS models. First, Sect. 3.1 analyses the target domain requirements towards CREST. Section 3.2 outlines the components of the CREST formalism, and highlights the concepts that were borrowed from existing languages to create a coherent formalism. Sections 3.3 and 3.4 introduce CREST diagrams, CREST ’s graphical syntax, and crestdsl, its implementation as pragmatic internal DSL, respectively. Section 4 describes CREST ’s operational semantics and its use for simulation and verification. Both aspects are introduced from a CREST-based view, followed by their practical description in crestdsl. The section also includes a brief outline of crestdsl ’s satisfiability modulo theories (SMT) approach to discover the points in time where discrete behaviour changes, i.e. state transitions, occur. This is a vital concept for our DSL’s implementation. Section 5 reviews our method and discusses valuable insights into the development process, lessons learned and critically evaluates potential pitfalls that should be avoided. Section 6 compares our approach to related research efforts. Section 7 outlines future developments of our project, and Sect. 8 concludes.

2 Background—from modeling to domain-specific languages

Systems modeling is widely accepted as a standard item in the engineering toolbox. The models facilitate system conceptualisation, design and verification by reducing complexity and hiding unimportant implementation details [55], and often allow simulation and analysis even before the actual system is being built. In many cases, different models are created, each focused on a particular viewpoint such as system architecture, safety, concurrency or performance. Depending on the specific task at hand, engineers choose a suitable modeling formalism (or language) for the appropriate representation of the particular system aspect [16]. Nonetheless, abstract mathematical system descriptions are conceptually distant from the actual system. For instance, formalisms such as Discrete Event System Specification (DEVS)  [81], Petri nets [68] or Bond graphs [15] are designed to be generic and application agnostic, but oftentimes so abstract that it is difficult to recognise the original system within the actual model. This leads to an often-criticised lack of practicability and applicability [43]. Sometimes it is even necessary to develop workarounds to assert that the actual system behaviour can be expressed using formalism’s semantics. A common example is the discretisation of models to be able to use languages and tools that do not support continuous evolution. Such a divergence between the system and its model, where system behaviour has to be approximated or modelled using inappropriate means is commonly known as semantic gap [30]. Wide semantic gaps, often created by operation on the wrong abstraction level, lead to confusion and problems not related to the actual system itself. The results are understandability issues and risks of introducing hidden bugs [74]. To overcome the complexity, domain experts require the help of professional system modellers who first need to learn about the system’s behaviour and then correctly translate the system to the formalism’s semantic domain. Obviously, misunderstandings and communication problems are common.

2.1 Modeling languages and tools

An alternative approach to employing expert modellers is to allow domain users to model their systems themselves. To do so, they require means that are understandable even without extensive systems engineering training, experience or modeling knowledge. As displayed in Fig. 1, these approaches still operate on a generic level, but usually provide helpful features for the representation of system engineering concerns. Modeling languages such as the Unified Modeling Language (UML) [64], the Specification and Description Language (SDL) [48] or Modelica [34] raise the abstraction level and bring models closer to the system domains. They allow convenient abstractions to improve system design and reasoning, while still offering translation to various low-level formalisms or directly to software source code. However, even though these languages allow systems to be modelled at an abstraction level that is closer to the original, they tend to be still very generic and involve steep learning curves. For instance, users usually require several months of continuous exposure before they become proficient with UML [33]. This means that the main users of these languages tend to be professional system developers, rather than domain end-users, i.e. the people who will actually build and use the system on a daily basis. In fact, to enable domain users to also model their own systems, it is necessary to provide them with the capability to use modeling tools that operate in the system domain level, using the concepts, terminology and tools that the users are already familiar with. This approach removes steep learning curves and avoids the risk of confusion and misconceptions.

Fig. 1
figure 1

Levels of domain adaptation in systems modeling

2.2 Domain-specific approaches

In the last few decades, this final domain-adaptation step has evolved in several forms, as shown in Fig. 1. A common approach is to adapt an existing modeling language by altering its concrete syntax (and sometimes its semantics) to more closely represent the features found in the actual system domain. Business process management models [78], for example, are inspired by Petri nets and allow the modeling and analysis of business workflows. The matching BPMN [62] language offers a graphical interface for simplified representation. In a similar way, the Architecture Analysis and Design Language (AADL) [75] can be extended using the AADL annex mechanism. Such annexes can be used to add discrete behaviour [29], continuous behaviour [2] or error modeling capabilities [23] to the language. UML can be adapted to various domains using UML profiles [36], a UML-native means to extend and adapt the language. The UML Profile for Modeling and Analysis of Real Time and Embedded systems (MARTE) [63] for instance, is an extension of standard UML that offers concepts for the modeling of real-time applications. The Systems Modeling Language (SysML) [65] is a well-known adaptation of UML that alters and extends a specific subset of UML to allow dedicated systems engineering. However, both SysML and MARTE can be seen as generic languages themselves, as they are not applicable to a specific target domain. A more concrete experience report of using UML profiles for implementing domain-specific modeling is described in [25], where the authors adapt the language specifically for robotic applications.

Another approach to incorporate domain knowledge into a modeling tool or language is the use of tool libraries. Especially when using versatile modeling platforms such as Simulink or Ptolemy II, it is possible to create domain libraries that aid users by providing reusable APIs or objects. The Modelica language is well-known for its large number of object libraries,Footnote 1 that add capabilities to model specific domains such as chemical processes, hydraulic flows or power systems.

2.3 Domain-specific languages

A third method to close the semantic gap between model and domain is to create a dedicated modeling language for a specific target domain or application [69]. DSLs [80] raise the abstraction level of system models to facilitate model creation and reasoning, while at the same time hiding the underlying complexity of the modeling process. Ideally, this leads to DSLs that allow domain users to easily perform all their tasks using pre-existing knowledge and without the need to newly familiarise themselves with a tool or language. This increases productivity and makes the language easier to comprehend [39]. Language engineering experts work in concert with domain users to learn about their needs and trim the DSL according to these requirements. Hidden behind the DSL, the data are then executed using purpose-built tools or translated to other, well-established modeling languages in order to use already existing execution software. The recent popularity of DSLs is manifested in the numerous conferences and workshops organised on the topic, and seminal books such as [80] and  [28] show that the field is reaching maturity, with established best practices, available experience reports and educational resources. Despite all the benefits that they bring, the classical language engineering approach comes with a hefty price tag [79]. DSLs require a significant upfront investment into the initial creation and subsequent maintenance of their infrastructure [24]. Even small DSLs need at least the provision of a parser, a text editor and an execution engine or code generator (i.e. a translator to another language). Larger projects often require further development of a textual or graphical integrated development environment (IDE), auto-completion engines, static and dynamic code analysis tools, language and IDE versioning and version migration, interfaces to GPPLs, library support, etc. These needs and the popularity of DSLs led to the creation of language workbenches [27] such as Xtext [11], MetaEdit+ [77] and MPS [17], that promise help throughout the language design phase, but also convince through automatic out-of-the-box generation of many of the aforementioned artefacts. For instance, Xtext can generate a full-fledged IDE including parser, auto-suggestions and code analyser based on a DSL grammar alone. Its tight integration into the Eclipse Modeling Framework (EMF) [76] allows the facilitated development of code generators, model transformation engines or graphical editors for these languages. Nonetheless, even after the use of language workbenches, DSLs often require further customisation and subsequent maintenance effort that can easily become very costly in terms of time and development effort.

Internal DSLs [39] are an alternative to the creation of standalone languages where DSLs are embedded inside another, usually more generic language (e.g. a GPPL). This approach is related to the creation of tool libraries, so that it is hard to clearly distinguish between domain-specific libraries and internal DSLs. Generally, it can be said that—in contrast to tool libraries—internal DSLs tend to embed advanced features such as their own semantics inside their host languages, allowing for sound execution and verification. Further, internal DSLs often “use, and abuse, the host language” [31] by using metaprogramming, reflection and clever language tricks to implement domain-specific behaviour. Next to the reduced initial DSL development time and cost, users can rely on their pre-existing familiarity with compilers, IDE, code analysis frameworks and development best practices. Internal DSLs are usually easily extensible and integrate better into existing language infrastructure and tooling [20]. This is also reflected in their increased interoperability with other tools and third-party libraries. Depending on the particular host language, numerous software packages are available to further extend the DSL’s capabilities.

A well-known example of an internal DSLs is SystemC [12], a hardware description language that is implemented in C++and distributed as a software library. Models are created using regular C++source code that instantiates library classes and executes macros. SystemC’s semantics are implemented in a simulator module that is shipped alongside the library. Other wide-spread examples for internal DSLs include various testing frameworks (e.g. jMock [31], XUnit [8], ChaiFootnote 2) and extensions for programming languages such as Ruby [32] (e.g. Ruby on Rails [4]), Groovy and Scala [39].

Internal vs. External DSLs The clear advantage of using internal DSLs lies evidently in the reuse of the host language’s syntax and execution environment [38]. One disadvantage of this reuse, however, is the lack of static checking support. Internal DSLs often require models to be setup in a certain manner, use specific properties (e.g. inherit from specific base classes) or prohibit the use of some host language features (e.g. introspection, certain libraries, etc). While the lack of static checking is a DSL problem in general [44], external DSLs can benefit from static type and syntax checking offered by language workbenches. This means, that external languages can be defined to natively enforce these rules inside the parser or interpreter and display the results directly in the IDE. Internal languages on the other hand have to build these features outside of the GPPL’s infrastructure, such that users have to manually trigger syntactic and semantic sanity checks. In the best case, they might use language reflection and introspection APIs to create validation scripts and thereby inform the user of potential problems. However, typically manual execution of these scripts is required, which delays the feedback and might even cause frustration if the suggestions are incomprehensible.

Another issue might arise from choosing the wrong host language. The benefit of reusing the syntax also means that the host language’s syntax cannot be adapted or extended. For instance, Matlab requires an ellipsis (“...”) to be written at the end of each line of multi-line expressions. This feature can become problematic when designing so-called fluent interfaces that chain many method calls as described in [73]. In such situations, external DSLs show more flexibility, as they can support a highly customised syntax. The disadvantage here however often lies in the need to define the entire language and interpretation from scratch. Especially when it comes to adding “basic building blocks” such as mathematical expressions, operators, character string manipulations and type systems, the development process can easily become tedious. Modern language workbenches attempt to provide reusable blocks of syntax and grammar (e.g. Xtext’s support for Mixins and Traits [71]), but still require the execution environment to be defined and adapted for the newly created language.

Summarising, one can see that external DSLs provide more powerful, flexible and customisable features, that require time and effort to be created. Internal DSLs on the other hand take advantage of the out-of-the box features, but are limited by the host language’s syntax, execution platform and IDEs. In the end, it depends on the language developer’s insights to decide whether the benefit of a familiar GPPL syntax and cheap reuse of existing execution platforms outweighs the flexibility of external DSLs.

3 Methodology

Our project focuses on the modeling of CPSs whose behaviour is strongly influenced by the flow of physical resources such as light, electricity, water and heat. In this section, we describe the evaluation of modeling requirements towards a language for our systems, our search for an appropriate candidate and the reasons that led us to develop our own formalism and two modeling languages building upon this formal basis.Footnote 3

3.1 Language requirements

The approach we followed for this project is driven by the practical need of a tool or language, that brings the benefits of modeling and simulation to smaller-scale systems. While the research effort of the last few decades has produced a plethora of modeling formalisms, languages and tools that have been applied to various projects in industries such as transportation, avionics, manufacturing, heavy industry and safety-critical systems, very little effort has been made to transfer these developments to the end-user market. In particular, our target user group are creators of CPSs such as smarthomes, office automation installations and automated plant growing applications. Even though such systems usually are not classically safety-critical, i.e. do not pose harm to health or life, their correct functionality is nonetheless important. A plant watering setup that is assembled by a private end-user might cause to water spillage and break wooden floors or electrical devices, thereby creating significant financial damages. Similarly, a misconfigured office automation system that was installed by a non-expert building manager might lead to high bills if e.g. the lights and heating are run even if no employees are present. In the current situation, such users might shy away from creating their applications as the risk of faulty installations is high and they lack the time, capacity and financial means to use existing modeling and verification solutions.

Before starting the development, we first designed three case study systems that allowed us to evaluate the main requirements of resource-flow CPSs. Attention was paid to choose applications that represent the heterogeneity of our target domain. While a full description of each would exceed the scope of this article, we still provide a brief outline. A complete description of the individual case studies can be found in [50]. The three systems were designed as follows:

  1. 1.

    A smarthome system that connects appliances and Internet of Things (IoT) devices such as automated vacuum cleaners, televisions, a “smart” dishwasher and remote controlled lights. Additionally, the house features a solar power system and battery that produces electricity during periods of sunshine. The system also has control over the electric hot water boiler, which provides water to the shower and dishwasher. The modeling aim is to reduce resource consumption by performing tasks when cheap solar electricity is available. Additionally, the user’s schedule is considered to e.g. do the noisy vacuum cleaning when the user is at work.

  2. 2.

    Our second system is an office automation system whose purpose is to monitor the temperature and lights in a small office environment. The goal is to automatically maintain a productive work environment. Depending on the environmental observations (e.g. temperature, brightness), the system controls window blinds, ceiling lamps and air condition units. A constraint of the system is that the emergency exit path is always lit when employees are present.

  3. 3.

    The third system is an automated indoor gardening application. It uses soil moisture and light sensors to measure the environment conditions and control lamps, heaters and water pumps to assert ideal conditions that lead to maximum harvest, while at the same time reducing resource consumption. Figure 2 shows a schematic representation of the system.

Fig. 2
figure 2

Schema of the plant system’s components

A comparison of these systems resulted in the discovery of two important similarities. First, the types of systems we target in our study are commonly composed of off-the-shelf components. This means, it is highly unusual that system creators use custom components. Instead, they buy devices (e.g. lamps, home appliances, IoT gadgets) according to their needs and connect them to compose their system. Second, despite modern communication interfaces, the influences between the individual components are in the physical domain. For example, a dishwasher consumes hot water and electricity, a vacuum cleaner uses electricity to clean the floor and creates noise in exchange, and plants require sunshine or artificial light on a daily basis.

Next to these two principal paradigms, we identified ten aspects that have to be supported by a modeling language or tool, in order to be able to address all necessary system concerns. These aspects can be split into two groups, such that the first seven describe “functional” properties that can be objectively analysed:


allows systems to adapt to changes in their environment. For instance, all three case study systems need to react to daylight changes and activate the lamps when it becomes dark.


allows to model the immediate influences between system components and the momentary, discrete CPS behaviour changes. This is necessary, as virtually all physical effects are instantaneous, such as e.g. the flow of water when the shower is turned on or the spreading of light.


is a vital concept in systems modeling, as many effects can take place at the same time. In our smarthome for example, the use of a shower draws water from the hot water boiler, which causes it to be replenished with cold water and the heating rod to activate at the same time. In turn, the heating process consumes electricity from the solar panels or the electricity mains. All these actions need to be executed at the same time and update the system state concurrently.


is required since our systems are built from individual components. A clear and coherent composition mechanism facilitates system assembly. For instance, despite the water boiler’s external influences (water in and out flows, electricity), the water temperature inside is locally determined and modified, and not set from the outside.

Continuous Time:

is necessary to express physical effects, such as continuous resource flows which are usually described by differential equations.


is omnipresent in the real world due to unforeseeable behaviour of various components. Thus, it should also be expressible in our models. As an example, we can look at a light bulb. When the electricity starts flowing, it can either produce light, or alternatively break and cause a fuse to trip due to the power surge. Since both effects can occur in the real system, it is important to also model both.

A Formal Basis:

is required for advanced modeling tasks such as simulation and formal verification. Without a clear operational semantics, the models become imprecise and potentially invalidate verification results.

The remaining three language criteria largely depend on the target users, their pre-existing knowledge and preferences. This means that while they first seven key aspects, can be objectively evaluated, the additional criteria result from the proper integration of the key aspects and their good correspondence from a syntactic and semantic point of view. Evidently, a sound, formal language definition supports this integration.


describes how easily a modeling tool can be learned and used. It depends on the users’ knowledge and capabilities. For instance, novice modellers usually require clear instructions, whereas experts tend to prefer extended configurability and adaptability.


is a property that states whether a language or tool is apt for the use in a given task. A lack of suitability often results in a wide semantic gap.


describes whether a modeling means is capable of expressing all required domain concepts.

Table 1 Modeling language evaluation for resource flow CPSs

Equipped with these ten criteria, we set out to find a suitable language for the modeling of our case study systems. However, to the best of our knowledge, we did not find any language or tool that supports all our key properties, is usable by non-experts and novice system engineers and suitable for the modeling of smaller-scale resource-flow CPSs. Existing languages and tools that offer physical resources modeling usually target expert engineers from financially potent enterprises in the industrial sector. Their typical application domains include large scale systems such as oil rigs and power plants. Other, academic tools lack usability and therefore also require a long training phase. The tools that we selected for closer evaluation represent a range of different modeing languages that are actively being used in the domain of CPS modeling. We aimed to cover a broad spectrum of approaches, covering general purpose languages (e.g. MARTE, SDL), architecture description languages (e.g. AADL [75], MontiArcAutomaton [72]), hardware description languages, synchronous programming languages (e.g. Esterel [10], Lustre [42], Zélus [13]), event-based approaches (e.g. the quantised state [54] extension of PowerDEVS [9]) and modeling platforms such as Simulink/Stateflow and Modelica. The selection is based on an informal upfront evaluation and feature comparison. For languages that are very similar, we chose the more promising candidate. Table 1 shows our evaluation based on the previously obtained requirements. It can be seen that most languages lack at least one of the key requirements. MARTE and Modelica appear to be favourable candidates, although both of them are inapt in terms of usability and suitability. MARTE for instance builds upon UML’s fourteen diagram types and requires the knowledge of even more languages such as the Object Constraint Language (OCL).Footnote 4 This significantly expands the language’s learning phase. Furthermore, the language adds timing annotations to the system which can be (ab-)used to describe continuous variable evolution, but does not provide dedicated concepts. Modelica on the other hand provides this possibility, but requires the creation of a domain library to augment its usability for our target domain, which is a non-trivial task. Furthermore, its textual syntax is difficult to understand for newcomers and requires a lot of experience for proficiency. A more complete and detailed description of our evaluation, including discussion of the other languages and formalisms is provided in [50] and [52].

3.2 CREST—concept

Based on the previous evaluation and the lack of an appropriate modeling language for the CPSs and system creators targeted by our research, we decided to develop CREST as a standalone project, rather than an extension or adaptation of an existing product. CREST ’s goal is to provide an easily comprehensible and usable solution to CPS modeling. Thus, for instance, from a user’s perspective, CREST should be easy to learn and use, but flexible enough to model the broad range of devices that are installed in modern smarthome and office automation projects. On the development side, we decided to reuse well-known abstractions and parts from established modeling formalisms and languages. This allows us to rely on a large body of knowledge, build on existing tools by transforming CREST models and cater to the knowledge of users with pre-existing modeling skills.

CREST ’s main purpose is to support its users through three principal modeling tasks namely, the modeling, i.e. the creation of a system model, simulation, i.e. the evaluation of dynamic runtime behaviour and verification, i.e. the formally sound evaluation whether a model can reach certain beneficial or malicious states at all.

For the modeling itself, developers require a tool or language that helps in the rapid prototyping and subsequent refinement of their system and components. The provided modeling means has to be both easy to handle and also serve as an understandable resource for discussion. During the aforementioned evaluation of other modeling languages, we observed that these two requirements are often opposing. Graphical modeling languages such as UML or SDL encode data using easily understood information such as shape, size, colour and position. Their advantage over textual languages is the facilitated comprehensibility and the quick identification of required modifications [59]. The problematic however lies behind the scene. A clear graphical syntax has to be carefully engineered [67] and the creation of complex graphical models often requires the use of cumbersome graphical editors [18] which demand manual positioning and sizing of components, drawing of connection edges and frequent switching between keyboard and mouse. Especially in the prototyping phase, where models have to be edited and redrawn frequently, the creation of graphical models can quickly become a tedious task. Figure 3 shows a screenshot of the wide-spread Papyrus Modeling Editor, a common tool for UML modeling. Note, how several views need to be used in combination for navigation and model creation.

Fig. 3
figure 3

Source: Eclipse (Neon) Help—Papyrus guide

Papyrus modeling editor

Textual modeling languages such as Modelica and SystemC overcome these problems by using well-structured text to express system architecture and behaviour. Models encode relationships between components and subcomponents using keywords, similar to programming languages. The advantage of these types of modeling languages is the quick model creation and manipulation, since the focus remains on the actual model, rather than positioning, shape or size of its representation. They also tend to be more powerful in terms of “intelligent editors and copy&paste support” [1]. Further, they often benefit from advanced features such as IDEs, static analysis, code suggestions, as they are more easily created for textual than graphical languages. On the other hand, it is clear that textual models usually are not self-explanatory and thus require secondary notions such as accompanying documents or code comments to carry additional information for developers and users [67].

In the CREST project, we follow a pragmatic approach that resulted in the creation of a textual and a graphical language, such that their respective concrete syntax implements the same formalism. Thus they share the same abstract syntax and operational semantics. CREST diagrams, the graphical language, reuses abstractions and concrete syntax from other widespread languages to increase comprehensibility and usability. To build upon pre-existing knowledge, CREST diagrams reuse notational conventions from well-known formalisms such as automata and architecture description languages. Evidently, the language suffers from the same drawbacks as other graphical languages, in that the positioning and resizing of elements is intricate and time consuming. Thus, to increase the development speed and add the benefits from textual modeling, we created crestdsl, an internal DSL in Python. It offers the same expressive modeling power as CREST diagrams and adds reusability to the modeling by supporting classic programming concepts such as inheritance and shared code. crestdsl further poses as a flexible bridge to the implementation of advanced modeling tasks such as simulation and verification. The DSL facilitates the model creation and invites the development object and domain libraries, providing scripting APIs that also support user-developed language extensions and tooling. Due to their expressive equivalence, CREST diagrams and crestdsl models can be transformed from one representation into the other, and, crestdsl does in fact provide functionality to create interactive CREST diagrams based on its models. A discussion of the translation functionality is provided in Sect. 5. The next two sections introduce both CREST diagrams and crestdsl, and highlight our design choices.

3.3 CREST diagrams

CREST diagrams [50, 53] are a graphical modeling language geared towards usability. Its purpose is the modeling of physical resource flows between the components of CPSs. Thus, it contains dedicated features to address concerns such as continuous flows and component hierarchies. The language implements a formal syntax and structure specification that clearly states requirements and constraints of CREST models (see Appendix 1). In this section, we use CREST diagrams to introduce the structure of a typical CREST model. Note, that the CREST diagram syntax reuses modeling notions known from other modeling languages to increase familiarity.

Fig. 4
figure 4

An air conditioning unit modelled as a CREST diagram

For simplicity, CREST diagrams combine architectural and behavioural system aspects within the same language. The advantage of this approach is that especially novice modellers have all information directly displayed to them, without the need to switch between different viewpoints.

Architecturally, CREST models are primarily defined through a system structure whose components (entities) are arranged strictly hierarchically. Thus, each entity only has one parent and a CREST system has only one, single root entity that defines the system’s scope. CREST ’s behaviour description is inspired by finite state machines (FSMs) and hybrid automata. This means, that every entity defines a state-automaton that represents its behaviour modes. In each state, the system can expose different behaviour, such that a device might produce other output when it is turned on than when it is turned off, for instance.

Entities enforce CREST ’s locality requirement and hide their internal structure from the outside. Hence, an entity’s automaton states cannot be read from another entity and it is not possible that one entity’s state automaton directly influences the output of another entity. Another advantage is that within the entity hierarchy, a subentity can be treated as coherent “black box”, whose system state is always up to date and does not have pending state updates. This concept is very important for CREST ’s semantics (see Sect. 4.1), which revolve around the creation of such “stable” system states, by locally searching for fixpoints on the lowest entity levels and recursively ascending in the entity hierarchy and stabilising until the entire system is stable.

An entity’s black box view also exposes its communication interface, consisting of input ( ) and output ( ) ports. Similar to some common architecture description languages (e.g. MontiArc [40]), CREST ’s ports define which type of value they accept. These types (called resources) consist of a unit (e.g. Celsius or Lumen) and a value domain such as natural numbers \(\mathbb {N}\), real numbers \(\mathbb {R}\) or discrete sets (e.g. \(\{\text {on},\text {off}\}\)). Next to its name and resource, a port also defines its current valuation. Inputs and outputs are complemented by a third type of port: locals ( ). This port type is not part of the communication interface, but rather serves as internal storage of data.

CREST ’s behaviour definition is inspired by FSMs. Thus, each entity defines a set of states and guarded transitions (e.g. ). Transitions relate two states and a guard function, such that the automaton switches to the new state if the transition is enabled, i.e. if its guard condition holds. Usually, guard functions will access the entity’s port values for their evaluation. Note, that the locality principle is enforced here as well. Thus, to preserve consistency, transition guards can only use their own entity’s ports and the output ports of subentities for the computation.

Continuous behaviour, i.e. the flow of resources, can be modelled in several forms. The most fundamental way are update functions ( ). Updates extend the automaton behaviour in a similar way to hybrid automata (HA). However, instead of defining each variable’s rate in each state (as in HA), updates only modify specific port values. Specifically, an update relates a function to an automaton state and a target port, such that the function is continuously executed while the automaton is in its related state and the result is written to the port. For instance, a device might define that an update modifies the value of a specific output port while it is in state on. To add timing behaviour to the language, an update function also has access to \(\delta t \in \mathbb {R}_{\ge 0}\), the amount of time that has passed since it was last executed. This means that in theory, updates are executed in infinitesimal intervals (\(\delta t = \varepsilon \)) to produce continuous behaviour. Practically though, CREST ’s implementation is responsible to execute updates as often as needed and often very coarse time steps can be achieved.

CREST further offers influences ( ) to statically link two ports. Each influence relates two ports and a function in a way, such that the function is executed with the source port’s value as parameter and the result is written to the target port. Actions ( ) are similar to updates, except that they are executed at the exact point when a transition is triggered. This also means that they do not have access to a \(\delta t\) value. Note that influences and actions are purely syntactic extensions of CREST to increase the DSL’s usability. When required (e.g. for static analysis purposes) influences can be replaced by sets of updates, actions by introducing additional automaton states and transitions.Footnote 5

Note, that neither the CREST formalism (i.e. the abstract syntax), nor CREST diagrams prescribe a specific definition language for update and influence functions. This makes the language flexible and adjustable to the knowledge of its users. For instance, in the example in Fig. 4 we use a mathematical notation for updates that uses \(\delta t\) to explicitly highlight timing behaviour in updates and use \(\textit{value} - 5 * \delta t\). However, due to CREST ’s flexibility it would be possible to adopt an ordinary differential equation notation by e.g. writing \(\textit{value}' = -5\) instead. One problem of such genericity is that in principle any kind of functions and notations can be used and defined, causing potential risks to the calculability of CREST systems. To restrict the situation, CREST ’s formalisation defines limitations by specifying the formal update/influence functions’ signatures and the enforced function return value, to assert it matches the target port’s value type. Additionally, there are limitations as to which ports’ values can be used for the return value calculation, so as to not infringe upon CREST ’s locality principle.

Figure 4 depicts the CREST diagram of a simple air conditioning unit with an automatic timer. Its functionality depends largely on the values provided by the two input ports for temperature and switch, which influence the two output ports for cooling power and statuslight. Internally, the local port ontime measures how long the AC has been in the On state. Due to the shown abstraction level, the entire component can be modelled as a single entity, although we could imagine a refined version that uses sub-entities to e.g. model separate heating and cooling elements. Such a refined system would however exceed the purpose of this article.

The working principle of the AC unit is rather straightforward: Provided that the temperature input reads more than 22 degrees and the switch is on, the AC unit will run for 30 time units, or until the temperature or switch conditions are invalid. This is expressed using the condition \((\textit{switch} = \textit{off})\) \(\wedge \) \((\textit{ontime} \ge 30)\) \(\wedge \) \((\textit{temperature} \le 22)\). After a maximum of 30 time units, the device switches back to the Off state and remains there until the timer reaches zero again. The timer functionality is modelled using two updates that modify the ontime port. When in state On, the port’s value is continuously increased according to the time that passes. This means, that the update calculates the result of \(\textit{ontime} + \delta t\) and writes that value to ontime. In state Off, the value is decreased towards zero by five times that rate (i.e. \(\mathrm {max}(0, \text {ontime} - 5* \delta t)\)) until it reaches zero.Footnote 6 Two more updates are used to modify the coolingpower output, depending on the automaton state. When Off, the AC produces 0 Watt, when On, the power increases by 50 Watt for every degree over 22C. Finally, an influence is used to set the statuslight’s colour: green when the switch is on, red otherwise.

The CREST diagram in Fig. 4 uses mathematical notation for updates and transition guards, and pseudo-code for the influence’s functionality specification. As introduced above, the notational form can be easily adapted to the modeller’s knowledge and preferences. For instance, for more practical projects a programming language could be used specify each function’s behaviour. This approach is followed in crestdsl, CREST ’s implementation in the Python GPPL, as introduced in the next section.

Note, that the ports of Fig. 4 display the initial values of the system (including its initial inputs). Though these values are theoretically part of the model’s environmental embedding, we allow their definition. This (rather operational) view, is founded in the fact that similarly sensors often output a default value (e.g. 24C) or special value (e.g. None, undefined) before the first, actual reading.

3.4 crestdsl

In many cases, system developers prefer the use of textual over graphical languages. Even though graphical representations can be more easily understandable when used correctly [67], in recent years numerous tools were developed that allow textual modeling, followed by a conversion to a graphical representation.Footnote 7 Inspired by these tools, we aimed to create a textual DSL that is both simple to learn and write for programmers, but also offers a native conversion to CREST diagrams for system developers who prefer graphical models.

Before developing the DSL, we evaluated the pros and cons of external DSLs against those of embedded languages and decided against the use of language workbenches. An often-used argument for the development of external DSLs is their integration with many existing products. Languages that are based on Xtext for example, promise to seamlessly integrate with many expert model transformation, model analysis and model execution platforms. In our project, however, the model translation to other formalisms and integration into meta-modeling frameworks are not primary goals and we do not expect large parts of our user base to require them for their purposes. Thus, the adaptation to new simulation engines and translation of models are not considered as primary requirements. The following sections will show however, that our approach is capable of interfacing with libraries and programs, which is beneficial for DSL-development on the one hand, but also allows experienced power-users to address potential advanced use cases on the other. Another reason to avoid the workbench-based DSL development method is our experience with the arising problems when it comes to the iterative development of DSLs and the problematic of changing grammars and their underlying meta-models. We therefore decided for the more lightweight approach and reuse a GPPL as the foundation for our language. As programming is nowadays widespread skill that is even taught at high-school level, we rely on the assumption that even non-professional and private CPS creators will have the familiarity and capacity to write simple scripting tasks. Thus the target users of crestdsl include professional and private CPS creators with (at least some) existing scripting and program development knowledge. They might for instance also include building managers that aim to increase the safety of their (small-scale) installations. Our method also allows us to reuse a wide-spread host language’s syntax and semantics for the specification of transition guards, updates and influences. This approach is also well-known in modern data analysis and machine learning frameworks, that offer low-entry-barrier solutions for novices, but powerful programming APIs for advanced purposes.

crestdsl uses Python as host language for several reasons. First, it is easy to learn and use, and experiences growing popularity. This fact is also manifested in a large number of third-party libraries, numerous tutorials and a helpful online community. From a DSL development view, Python offers many attractive features such as a flexible meta-class system that allows customisation of object creation, function and class annotations (so-called decorators), and the availability of a powerful reflection API. Furthermore, many external tools such as SMT solvers, theorem provers and formal verification engines offer Python bindings and thus a native integration. The latter is a vital advantage for implementing the DSL and its execution engine.

During the development of crestdsl we paid attention to make its use as simple as possible, while at the same time support common Python development best practices. The software is available through the Python package indexFootnote 8 and can be installed through Python’s pip program. Thereafter, crestdsl can be used by importing, just as any other Python library.

crestdsl entities are modelled as instances of the class. Features that belong to that entity (e.g. its ports, states, transitions, updates) are modelled as entity attributes. To simplify the creation of several similar entities, crestdsl provides entity types. These types are classes that inherit from the class. The type’s structure is then defined using class attributes and methods. Listing 1 shows an entity type that models the architectural parts of our air conditioning unit. It features two inputs, two outputs and two states. Note that just as CREST diagrams, crestdsl also requires every port to have a resource and current value specified. Similarly, every entity has to have one state designated as state.

figure m
figure n

Upon instantiation, the class’s constructor and metaclass work to provide a correctly instantiated object. crestdsl supports class inheritance to create specialised or extended versions of an entity type. This feature is not a general CREST concept, but significantly increases crestdsl ’s usability. Listing 2 for instance, shows the extension of by adding transitions, updates and an influence to the class. Note, that the listing shows two ways to specify transitions and updates. The first one is similar to the definition of ports and states: A object is created and assigned as class attribute. The required transition guard is specified either as a lambda-expression or using a function. Alternatively, it is possible to define the transition guard as a class method. By using the decorator, it is then possible to convert the method into a transition. The listing also shows the specification of updates via object and decorator, and the creation of an influence using .

Class inheritance is a powerful concept, as it can also be used to adjust entity behaviour. Python’s multiple inheritance functionality allows class fragments (a.k.a. mixins) to be added to the language. This enables modular development and the separation of specific concerns (e.g. reusable component fragments for adding value inspection or signal probing) into individual classes, that can then be reused where required. If used correctly, this feature permits advanced users to create reusable component fragments and thereby even add aspect-oriented system design to the DSL. The inheritance design principle invites code reuse and the creation of object libraries. For this purpose, crestdsl also provides parametrisable entity types using class constructors.

Without the provision of a separate example, we want to highlight that system composition follows the same DSL design, where subentities are defined by assigning entity objects as class attributes.

To test whether the system model was correctly assembled, a class can be used. This static system analysis performs a number of sanity checks such as testing the entity hierarchy and asserting that each entity defines a current state. Its purpose is to help crestdsl users debug their model quickly and find potential causes for misbehaviour. If necessary, users can also extend the class and implement their own static analysis routines that assert certain system setups (e.g. testing for specific architecture setups, port type conformance, etc.).

4 Simulation and verification

Usually, model creation serves as stepping stone for further, advanced modeling tasks such as model-based analysis, simulation and verification. Above, we introduced as an example for simple, static analysis. Due to its formally defined semantics, CREST also supports sound simulation and verification.

Fig. 5
figure 5

An excerpt of a CREST diagram highlighting dependencies between subentities. Note, that for clarity the port types and values were omitted

4.1 CREST semantics

To support the combination of aspects from several formalisms (FSM, architecture descriptions, hybrid systems), it is necessary to pay careful attention to the precise meaning of each element. For this reason, CREST ’s semantics have been formally defined to assert consistency with the key principles that we obtained in the requirements evaluation. Thus, it is paramount, that the operational semantics uphold the reactivity, synchronism, parallelism, locality, continuity and non-determinism that are essential for the expression of our systems. In this section, we outline CREST ’s semantics and highlight the relation to other languages and formalisms, such as data-flow languages and hybrid automata. Note, that this section focuses on providing a high-level description of the semantics and its effects in the simulation of CREST. The actual formalisation, including its structured operational semantics (SOS) rules, is provided in Appendix 1. A more elaborate description, that exceeds the scope of this publication can be found in [50].

CREST foresees two ways of model interaction. First, the change of the root entity’s input port values, and second, the advance of time. After each of these, the model has to be stabilised until a “fixpoint” is reached. Fixpoints are system states where the model is stable and will not change without another interaction.

Fig. 6
figure 6

Schematic representation of the stabilisation semantics as UML 2.0 Activity diagram

Input value change The external modification of input port values represents changes in the system’s environment to which it should react. Thus, such a modification can only occur at the hierarchical top level. This is due to CREST ’s locality principle, which requires every entity—hence also the root—to be treated as coherent black box that only exposes its communication interface (input and output ports). Once a port value change is observed, the semantics require the stabilisation to be triggered, which then propagates the updated information throughout the system. The process starts by performing the stabilisation first on the system’s root-entity, which then recursively calls stabilisation on its subentities. Evidently, modifiers (i.e. influences, updates and subentities) within an entity can depend on each other. For instance, Fig. 5 shows an excerpt of such a CREST system. It is clear, that sub2 depends on the output value of sub1. Thus, to assert a correct system state, it is necessary to first make sure that sub1 has been stabilised and reached a fixpoint, before executing influence\(_1\) to propagate the value of sub1-output to sub2-input\(_1\).

This brief example illustrates the need to establish a modifier execution order. The creation of this execution order is closely related to the use of Kahn process networks [49] and commonly used for the execution of data-flow languages such as e.g. Lustre [42]. The ordered modifiers are then executed one by one. This means that in this order, each update function is evaluated and the result written to its target port, and subentities are recursively stabilised (see Fig. 6).

Only after all modifiers have been executed, the transitions from the current state are tested whether they are enabled. If no transition can be triggered, the process ends and the entity is stabilised. Otherwise, one transition is chosen and executed. CREST does not prescribe a resolution strategy in case multiple transitions are enabled at the same time. This means, that any enabled transition can be triggered, which is CREST ’s way of introducing non-deterministic behaviour—a vital concept and one of CREST ’s key aspects. After a transition is executed, the stabilisation process has to recursively call itself again, to assert that updates that are related to the new automaton state—and are thus newly active—are executed.

Note, that the semantics in Fig. 6 do not mention influences and actions, as these are syntactic sugar and can be expressed through updates and states alone, as described in Sect. 3. This trait both simplifies the formal semantics and CREST ’s system analysis.

It is also of interest to mention that generally, the reaching of a fixpoint cannot be guaranteed. Especially in the presence of Zeno behaviour (i.e. an infinite number of transitions in finite time [82]) or cycles of continuously enabled transitions it can happen that infinitely many actions are executed without ever reaching a stable state. Even though CREST ’s implementation provides a few configurable heuristics to detect these kinds of situations, it is up to the system designer to avoid the modeling of such problematic behaviour.

Advancing time The notion of time is an important aspect of CREST. It allows the modeling of continuous effects, such as the filling of a water tank without the need of introducing artificial discretisation. Since CREST implements must semantics (as known from e.g. hybrid automata), this introduces an interesting challenge, as it is necessary to find the precise moment in time when a transition becomes enabled.

For instance, when looking at the time-based behaviour of the air condition, we observe that—provided the input values do not change—the model will alternate between on and off states, so that it is 30 time units in state on, followed by 6 time units in state off, before switching to on again. Figure 7 shows a trace of this behaviour. Evidently, when simulating continuous time systems, it is important to choose the right step-size for the current system behaviour. Advancing in too small time intervals might cause a high calculation overhead and perhaps even render the simulator unusable. Too coarse step sizes can lead to “missing” an important point in time, which either requires the simulator to step back and retry with a smaller step size, or, if undiscovered, might even lead to wrong simulation results. CREST ’s semantics assume the existence of a next transition time function, that calculates the precise amount of time until a behaviour change (i.e. a state transition) occurs. This means, that calling the function when the air condition system is in state on and ontime has a value of 18.7, should return the exact value of 11.3 time units, since at this time the port’s value reaches 30 and thus a transition should be triggered (see Fig. 8).

Fig. 7
figure 7

A trace showing the air condition model’s automaton state over time

Fig. 8
figure 8

Locating the next transition time, assuming that ontime = 18.7 at the beginning

crestdsl implements next transition time using an SMT approach. Whenever it is necessary to calculate the time until a transition event, the simulation engine translates the update functions and influences that potentially affect the value of a transition guard into a set of SMT constraints (see details in the next section). This constraint set is then handed to Microsoft’s Z3 Theorem Prover [22], which either calculates a value for \(\delta t\) that solves these constraints and hence enables the transition, or alternatively signals that the constraint set cannot be solved and therefore the transition cannot be enabled by the advance of time alone.

Once the simulator obtains the knowledge at what point in time the next transition becomes enabled, advancing time is merely a matter of iteratively stepping forward to the next transition point and triggering the stabilisation process after every step. Note, that in this case the stabilisation process has to trigger updates with the correct \(\delta t\)-value, to consider the timing behaviour when calculating the updates’ target port values.

CREST ’s formal semantics (see Appendix 1) do not specify how the next transition time should be calculated. Thus, CREST can be used for any type of system. The implementation’s SMT approach however relies on the use of Z3, which is not capable of solving nonlinear optimisation problems. This means, that even though crestdsl produces a nonlinear constraint set, it cannot be solved and the simulation is likely to run into issues in the presence of nonlinear dynamics. At the moment, we are aiming to extend crestdsl to add support for nonlinear systems by using theorem provers with nonlinear optimisation capabilities such as dReal [37].

4.1.1 Next Transition Time Calculation

As stated above, CREST ’s semantics require the calculation of the nearest point in time when a transition will occur. crestdsl implements this functionality by creating a constraint set for each transition, which expresses the value change of its guard condition over time. These constraints are then handed to the SMT solver to find a minimal solution to these constraints.

The challenge of this approach is the creation of a constraint set that captures the dependencies between the ports. For instance, we see that the input sub2-input\(_1\) of Fig. 5 is influenced by sub1-output, whose value might in turn depend on other ports. crestdsl automatically converts these modifier-dependencies into constraint sets, so that any time-based updates of predecessor-ports are also considered, as these might indirectly enable transitions.

figure x

Listing 3 shows one of the air condition’s transitions. It states that the device should turn off when either the switch is off, ontime reaches 30 or the temperature drops below 22 degrees. Thus, the first constraint \(c_1\) captures the guard condition.

$$\begin{aligned} c_1 ~:=&(\textit{temperature} < 22) \vee (\textit{switch} = ``{} \textit{off}'') \\&\vee (\textit{ontime} >= 30) \end{aligned}$$

From the CREST diagram in Fig. 4, we see that the three sub-expressions are based on the values of two input ports ( and ) and one local port ( ). Since AirCondition is the root entity, its input port values cannot be changed by any system modifier (neither by updates, nor influences, nor subentities). on the other hand is continuously modified by the update function. It is therefore necessary to add its functionality to the constraint set. From the update function’s source code we can see that when executing, the function reads the current ontimer value and adds , i.e. the amount of time since the update’s last execution, to it. Therefore, the next constraint to add is

$$\begin{aligned} c_2 ~:= ~ \textit{ontime} = \textit{ontime}_0 + \delta t \end{aligned}$$

where \(\textit{ontime}_0\) and \(\textit{ontime}\) are the port’s values before and after ’s execution, respectively.

As the air condition has no other dependencies, the system input ports have to be linked to their current port values, since otherwise the SMT solver might assign any value that solve the constraint. Our analysis aims at time-based changes alone. We thus have to set the values of these ports, so that \(\delta t\) is the only assignable variable in the constraint set. The constraints \(c_3\) to \(c_5\) express this by linking \(\textit{temperature}\), \(\textit{switch}\) and \(\textit{ontime}_0\) to the values shown in Fig. 4. \(c_6\) asserts that \(\delta t\) is positive. The final constraint set contains all equations necessary to discover when the transition becomes enabled:

$$\begin{aligned} c_3 ~:=&~ \textit{switch} = ``{} \textit{on}'' \\ c_4 ~:=&~ \textit{temperature} = 24 \\ c_5 ~:=&~ \textit{ontime}_0 = 0 \\ c_6 ~:=&~ \delta t \geqslant 0 \end{aligned}$$

When handing these six constraints to an SMT solver, it will not directly return the nearest transition time, as any \(\delta t \geqslant 30\) is a solution to the problem. Therefore, we use Z3’s optimization functionality to find a minimal \(\delta t\), which in the example above is 30.

4.2 crestdsl simulation

Using CREST ’s formal semantics and crestdsl it is possible to create a simulation engine that helps answering “What happens if...?” questions. Users can try out system interactions and observe possible usage scenarios. Listing 4 shows the example code of a simulation scenario. The listing uses the standard that follows CREST ’s semantics and implements non-determinism. However, crestdsl provides two other simulation engines that allow slightly altered usage. The first one, , prompts the user to choose an enabled transition anytime a non-deterministic situation is encountered. This allows users to explore specific scenarios despite non-deterministic models. Finally, can be used to define strategies on how to deal with non-determinism. This scenario can be used to model controllers that, given a range of similar transition choices, will choose one according to a pre-defined policy. The can also be used to follow a specific execution trace that is e.g. discovered by state space exploration or similar verification techniques, as described further below.

figure al

4.3 Verification

CREST ’s semantics allow the construction of state spaces and the use of formal verification techniques, such as model checking, thereon. Based on existing approaches, logic formulas can be defined and their truth-value examined on a model’s state space. Since CREST is a hybrid formalism, it is however necessary to extend the classical temporal logics (e.g. LTL, CTL) to incorporate timing aspects in their language. Given CREST ’s non-determinism, and thus its branching behaviour, we use the timed computation tree logic (TCTL) [45], a timed extension of CTL, and its operators and formulas for the specification of system behaviour. We will not elaborate on the foundations of classic and temporal model checking, but instead refer the interested reader to seminal works such as [3] and [14]. In general, TCTL formulas are composed of a set of operators, which are inductively defined:

$$\begin{aligned} \phi = ~ \texttt {True} ~| ~ p ~| ~ \lnot ~\phi ~| ~ \phi \wedge \phi ~| ~ \phi EU_{I}~\phi ~| ~ \phi AU_{I}~\phi \end{aligned}$$

where \(p \in AP\) is an atomic proposition, and I is an interval in CREST ’s time base that defines the timing aspect of the \(EU_I\) and \(AU_I\) operators. Based on these operators, further abbreviation operators can be defined, such as \(EF_{I}\,\phi \,=\,\texttt {True}\,EU_{I}\,\phi \) and \(AG_{I}\,\phi \,=\,\lnot \,EF_{I}\,\lnot \,\phi \). Note, that in comparison to classical CTL, there is no X (“next”) operator, since in continuous formalisms there is no “next point in time”.

Subsequently, we can test these formulas on timed Kripke structures [57]. Timed Kripke structures are graph-based encodings of a system’s state space, whose nodes represent discrete system states and edges are timed transitions between them. Each node is annotated with a set of APs that represent certain behaviour (e.g. “the AC is on” or “the coolingpower output is above 100 Watt”). CREST ’s continuous semantics demand that the transitions be annotated with the amount of time it takes to pass from one state to another. Figure 9 shows an example of a timed Kripke structure.

Fig. 9
figure 9

A timed Kripke structure with five system states \(S=\{ s_0, \dots , s_4 \}\). Nodes labels are the APs \(\{p,q\}\)

Following some minor adaptation of the timed Kripke structure, the TCTL formulas can then be evaluated using graph search algorithms that are inspired by classical CTL model checking approaches. Details on these algorithms are provided in [57] and an elaborated description of the creation and adaptation of timed Kripke structures for CREST models is described in [50].

4.4 crestdsl verification

crestdsl implements a Python-native subpackage that provides APIs for the specification of system configurations, the creation of a model’s state space and the search of that behaviour within that state space. System states are specified as checks, which can be used to either define that an entity is in a given automaton state (e.g. ), or to compare a port against a constant or another port value (e.g. ). crestdsl also allows to create composed checks as conjunctions, disjunctions and negations of other checks.

Checks can then either be evaluated directly on a system state using by calling its method. Alternatively, they can be used for the formal verification of a crestdsl model’s state space. To do so, crestdsl provides two APIs. The first is crestdsl ’s convenience verification API. It provides interfaces for users that are unfamiliar with model checking and formal verification. Modellers are provided with a set of functions that can be executed for common verification tasks. For instance, the function, verifies that a given condition can never be invalid. Similarly, asserts that it is possible to reach a given state and asserts that a given system configuration can never be reached. Table 2 shows some convenience API functions and their TCTL equivalent formulas, Listing 5 shows their programmatic usage.

Table 2 Verification API and TCTL equivalents
figure bd

crestdsl also implements an expert API, that allows to manually create complex TCTL formulas and obtain direct control over the model checking process. By directly creating and using the object, it is possible to gradually explore a state space. This allows crestdsl ’s routines to be used in some infinite state spaces. The API groups implementations of all TCTL operators, so that experienced modellers can create complex formulas to be evaluated. Listing 6 provides an example of the expert verification API.

figure bg

5 Discussion

DSL Development Process Our experiences throughout the CREST project were mostly positive. Although our aim to cut the development effort for the creation of a new modeling formalism drove us to reduce some of the typical modeling overhead (e.g. syntax definition), we still had to invest into defining a coherent language semantics. Furthermore, our internal discussions often resulted in debates about the tradeoff between the need for the creation of independent, dedicated modeling concepts and the effort of adopting well-known aspects from other languages. For instance, there are many different types of component composition described in research, and indeed there is evidently a possibility to invent new ones if needed. However, our reusage goal led us to adapt the hierarchical modeling aspect known from architecture description languages (ADLs) and their reported experiences in using ports for composition. Similarly, we managed to reuse abstractions and concepts from hybrid automata, synchronous data-flow languages, and combined visual and textual modeling approaches within the same language. Their joint use in CREST is based on a formalisation that thoroughly combines the syntactic and semantic aspects of the individual language parts. The success of the SystemC hardware description language inspired us to implement CREST as internal DSL, so we can rely on existing IDEs, execution environments and programming aids.

Indeed, by implementing crestdsl in Python, we quickly noticed the advantages of its large developer community. It also allows us to integrate the language with third-party developments, such as the Project JupyterFootnote 9 runtime. This interactive platform allows code to be defined in so-called cells that are executed at command, inviting iterative and fine-grained development approaches and thereby increasing usability and user experience. Jupyter’s user interface is browser-based, can be easily installed via Docker images or hosted on external servers. Cells are housed in notebooks and also provide a means to write text in e.g. using Markdown format right next to executable code, which merges documentation and executable code in one document.

Through our integration of crestdsl into Jupyter, models can be plotted directly using a combination of HTML and JavaScript code. This results in an interactive output (see Fig. 10) that can be explored, zoomed in and out and interacted with. Through popups and mouse-over events, it is possible to access and view live data from the model, as well as to manipulate the display itself (e.g. move and resize entities).

Fig. 10
figure 10

Interactive CREST diagram plot and simulation trace of a crestdsl model

Python’s many third-party-libraries can also be used for other aspects of CREST. For instance, it is possible to use the PandasFootnote 10 data analysis package to query and analyse system traces, or the PlotlyFootnote 11 library to create an interactive representation thereof, as shown in Fig. 10. We invite readers to visit the crestdsl webpage at https://crestdsl.readthedocs.io/ for more details on our work and crestdsl ’s online documentation. You can also find a demo that can be launched online inside your browser at https://github.com/crestdsl/sosym-aircondition.

Translation between Languages We found a major advantage of CREST to be the combination of both, the textual and graphical modeling environment. crestdsl ’s module for the automatic translation of its models to interactive CREST diagrams proved to be a useful commodity at model creation time. As a result, developers create a system model using an efficient textual programming style, but also benefit from the perks of a visual language for discussion and brainstorming. Additionally, as the languages share the same abstract syntax and operational semantics (see Appendix 1), it is possible to first draw a graphical diagram model and then implement it in crestdsl for simulation and verification. At the moment, our tool implementation only supports the textual-to-graphical translation though, as we initially believed that our users’ workflow would typically start in crestdsl and move to CREST diagrams for enabling visual inspection and discussion. However, we noticed that our users often “think in CREST diagrams” and actually start the modeling process by sketching out system models as CREST diagrams using pen and paper, before switching to implementing individual components in crestdsl. This insight is an important insight and big encouragement for the creation of a parser that enables automatic translation from CREST diagrams to crestdsl models, to enable creation of an outline in CREST diagrams and switching to crestdsl for the detailed model creation. We are currently in the process of evaluating the requirements to such an interactive graphical development environment and evaluating likely development workflows to find out which tasks can be more efficiently executed in which syntax. This analysis should also help us answer the question for which phases the user will switch between languages. A point of concern is that a translation from CREST diagrams to crestdsl necessitates the parsing of transition guards, update functions, etc, whose syntax is currently not limited by CREST. Thus, a graphical-to-textual translation mandates a limitation of the supported syntax, which could for instance be Python for integration with crestdsl or some dedicated, embedded DSL. Though the benefits of this extension appear evident, we consider a thorough evaluation of the complete, required feature scope (e.g. a graphical editor, parser, etc) and the analysis of development and maintenance costs for the (interactive) bidirectional translation as future work.

User feedback Since our project aims at the use by non-expert modellers, throughout the project we sought the input of people from outside the modeling research domain. Given our academic background, we therefore asked our students (Bachelor’s and Master’s level) to use CREST and crestdsl, in order to gather feedback and improve the usability. The conclusions drawn from these evaluations are largely positive and show that both, the CREST formalism as well as the crestdsl implementation can be easily learned. Even though the users neither had a background in modeling nor any training in CPS design, they rapidly acquired the necessary knowledge to model our case study systems and were even able to create object libraries.

These experience reports provide us with valuable feedback and confirm that our method is promising, although we admit the necessity of a more formal evaluation. Thus, we are currently in the process of designing a DSL usability study based on the principles found in works such as [5] and [6].

Lessons learned Throughout the project, we relied on our experience with semantic definitions and language formalisation. Our methodology is based on the thorough formal definition of all required syntactic and semantic concepts before their implementation in CREST diagrams and crestdsl. This increased our trust in the DSL’s correctness and helped us identify potential problems that we otherwise may have overlooked. We see this part of our method as vital for the success of this project and a creation of a usable language. It is still important to clarify that the formal definition did not follow a “one-shot” approach, as we had to go through several iterations before all required features were implemented. Compared to other approaches to DSL creation by reuse of existing design concepts (see Sect. 6), our approach proved to be dynamic and flexible, as our focus was not placed on a direct combination of existing formalisms and languages. Instead, our goal was to increase CREST ’s usability as much as possible and, although we aimed to maintain “the spirit” of the original formalisms (e.g. automata, ADLs), we valued a concise product over their direct reuse. Our design method helped us to iteratively select the best concept from various options. For instance, we chose state automata for the definition of entity modes over a Petri net-based approach, which would have simplified the modeling of concurrent behaviour and certain parts of the semantics, but increased complexity and reduced intuitive usage. Similarly, we evaluated various forms of component composition and different formalisations of ports that exist in literature. Nonetheless, it is important mentioning that our approach is not meant for algorithmic or (semi-)automatic DSL composition. It appears that such a composition is in many cases opposing the coherent integration of language features. Resulting language compositions typically require adapters (or some form of “glue”) to enable the interaction between the domains of the existing languages [41].

The availability of the three case study systems also facilitated DSL design, increased development speed and helped us identify which language aspects should be implemented. One noteworthy point is that even after identifying the DSL’s requirements and necessary system features, the formalisation caused discussions about tradeoffs. For instance, as mentioned above, CREST ’s influences and actions are treated as syntactic sugar and translated to their corresponding update representations. Before this definition, we initially developed an equivalent semantics that treated the former separately. It was only after another iteration and application study, that we decided to simplify the operational semantics to their final state.

Tool Implementation A more practical problem arises when it comes to the use of crestdsl. Even though the language offers much flexibility, one caveat of using an internal DSL is that the available host language syntax is not limited. This can lead to problematic situations, as the user does not receive any feedback when they try to use illegal concepts. For instance, in crestdsl updates and influences are not allowed to model nonlinear behaviour, as the simulation engine relies on the use of Microsoft’s Z3 Theorem Prover which is restricted in that sense. An extension to a more powerful SMT solver (e.g. dReal [37]) could greatly increase the applicability of crestdsl. In a similar way, modulo operations are not supported and the use of string datatypes is limited. If modellers use these constructs in their system models, however, they will not be informed of their wrongdoing until the simulation or an explicit system check is triggered. This delay in feedback can easily lead to frustration. crestdsl provides a class that aims to discover and inform the user of illegal models using reflection APIs. Nonetheless, users have to explicitly execute this functionality for feedback. We see this behaviour as less powerful when comparing to external DSLs, which tend to have an explicit grammar and abstract syntax tree (AST) checks built into editors and IDEs and provide imminent feedback during model creation and editing.

When developing internal DSLs, it is also important to invest into properly informing users of the activity that is performed in the background. Many times certain modeling tasks need a significant amount of time to perform, and thus, users require feedback when calculations are performed in the background. For instance, during model checking the creation of a state space and the search of the resulting timed Kripke structure take a long time. Here, it is especially important to provide the user with feedback about the exploration state.

Target systems We found that, as intended, our DSL provides a convenient means for the modeling of smaller systems. However, we noticed that CREST can also be used to elegantly describe larger, more complex systems, at higher abstraction levels, although its crestdsl implementation quickly reaches acceptable performance limits for simulation and verification times in its current implementation. For instance, some of our benchmark implementations modelled the above mentioned case study systems at various levels of detail. Though these studies are preliminary and warrant for further exploration, they show that crestdsl can be effectively used for the modeling and simulation of systems with 50 to 70 non-trivial components. As another benchmark, we included a linear approximation of the heating process inside a water boiler into one of these systems. The component’s linearisation splits the water volume into several interconnected “heating zones”Footnote 12 which expose mutual temperature influences among each other. Though crestdsl has not been implemented for modeling of such complex nonlinear processes or their linear approximations, the system shows that for small numbers of heating zones (up to 7), the system can provide valid simulation results in acceptable performance. Nonetheless, for larger numbers of zones (and thus finer model granularity), crestdsl ’s performance exceeds acceptable limits. Similarly, due to the large state space an efficient verification of such systems is not efficiently possible at the moment.

CREST joins the architectural and behaviour system aspects into one, coherent language. The creation of models as a team of multiple modellers is a necessity for large projects, but has not been foreseen in CREST and certainly poses inconvenience. Similarly, the use of Python as a host language leads to significant performance bottlenecks that cannot be resolved easily. Especially when it comes to verification of complex TCTL formulas on large model spaces, for example, Python and crestdsl reach their limits.

6 Related works

The approach presented in this paper is related to several current research directions. Next to the generic background work described in Sect. 2, we aim to highlight several works that tackle similar gaps as our research, namely the modeling of CPSs using DSLs on the one hand, and creation of new DSLs through combination and integration of aspects and design of existing ones on the other.

In the recent past, the employment of DSLs in modeling has become a widely popular means to manage complexity, especially in elaborated domains. Nordmann et al. [61] survey the vast landscape of DSL use in robotics, a CPS domain closely related to ours. To not exceed the scope of this article, we focus in this section on research that is closely related to our work, namely the creation of internal DSLs. Notable advances in this subdomain includes the work of De Laet et al. [21], which provides insights into the differences of a DSL that was both implemented internally (in Prolog) and externally using the Xtext framework. In their discussion, the authors note amongst other points the enhanced readability of the internal DSL. Functional programming languages pose a popular choice for host environments due to their readability, as shown in [26, 46, 66]. The authors of the former use F# to implement a DSL for the synthesis of programs by a learning system. Readability is of vital interest, as humans are required to verify the generated programs. Recently, Sadati et al. [73] created an internal DSL within Matlab that is based on fluent interfaces.Footnote 13 This research is of particular interest, as the authors’ motivation lies in the experience that users are hesitant of employing new tools and prefer using familiar development environments—an observation that similarly drove the design of crestdsl. Their publication describes the efficient use of Matlab’s specific language features and also highlight some unavoidable caveats introduced by the Matlab language syntax. Another internal DSL that uses similar concepts to crestdsl is presented in Fryer and McKee [35]. Their language is implemented in C++and —similar to crestdsl—uses to specify additional model semantics and to extend the model class definitions.

Generally, it appears that though other languages and (internal) DSMLs integrate existing modeling formalisms and languages to extend their capabilities (see also e.g. MontiArcAutomaton [72], AADL’s Behavioral Annex [29]), it appears that these languages’ target audience remains to be modeling experts, such that their usage is often very difficult for newcomers or non-experts (see Sect. 3.1). On the other hand, various DSLs exist e.g. in the domain of “smart” end-user electronics that allow the simplified assembly of systems and creation of workflows using pre-defined building blocks and object libraries.Footnote 14 These languages, often created by the gadgets’ manufacturers are an easy means to system configuration, but often closed-source and limited in capabilities and without clear syntax and semantics. As a result, users cannot easily—often not at all—extend the language, define custom behaviour or add own components. In comparison, CREST aims to fill the gap between these two sides by providing an open, versatile approach that allows the precise definition of system behaviour, model simulation and formal verification, while still aiming for ease of use. Thus CREST features the reuse of formally sound concepts (e.g. automata, ports) that are well-known by expert system creators, and combines them to form a coherent language that is also easy to learn and comprehend by novice users and private smarthome creators.

The domain of reusing and combining various aspects of modeling languages has similarly been approached using different methods. Lacoste et al. [56] describe the creation of a hybrid language by combining the Event Scheduling formalism with ODEs. They implement their language in the ATOM\(^{3}\) platform, which is the basis of creating a graphic editor. Similarly [7] describes the syntactic and semantic composition of DSLs for testing purposes.

Mustafiz et al. [60] follow a similar research, combining Timed Finite State Automata and Causal Block Diagrams to a hybrid language. Their approach is novel in that it relies on the extraction of language specification fragments (LSF), which represent modular, formal extracts of language features that allow the flexible combination on syntactic and semantic level. They then combine these LSFs by embedding one into another. In comparison, CREST operates on a more integrated level. Instead of extracting individual language features as LSFs, it combines syntactic and semantic concepts of different languages coherently. Mustafiz et al.’s approach on the other hand it is possible to distinguish the features that belong to each LSF, and the newly added concepts that “glue” the LSFs together.

Modularity and reuse of language design are also treated from a Software Product Line (SPL) methodology (e.g.  [47]), where DSLs can be dynamically created based on product line models such as feature diagrams. A similar approach is followed by the Neverlang project [19], which aims to capture language features in so-called slices (parts of syntax and semantics), that can easily be combined. Compared to the SPL method, Neverlang aims to provide flexibility throughout the evolution of a DSLs and its components. These approaches are very powerful when it comes to the creation and adaptation of DSLs, as individual language features and slices can be easily added or removed to achieve a high level of customisability. Nonetheless, for CREST ’s purposes the initial cost of extracting such features and slices for later combination is too high, especially when taking into consideration that we do not have any concrete plans for the creation of a family of similar DSLs.

7 Future directions

The development of CREST not only provided valuable insights into the creation of DSLs from existing formalisms and hands-on experience in the development of internal DSLs, but also resulted in a powerful basis for continued research in this area. So far, we identified several directions in which we want to extend our method.

CREST Improvements and Extensions CREST ’s current state can be adapted and extended in several ways. First, we noticed certain difficulties when it comes to the verification of models with large state spaces. Due to the use of Python as a host language, we attribute a lot of performance loss to the interpreted execution environment. To overcome the performance bottleneck, we are investigating several possibilities. On the one hand, we might translate CREST models into other formalisms (e.g. hybrid automata, Petri nets, DEVS) for which performant tools already exist. Alternatively, we are looking into adapting verification heuristics (e.g. symbolic model checking) to CREST ’s specific semantics, in order to reduce the state space size.

Another project we are working on aims to use CREST in concert with modern machine learning and artificial intelligence approaches. For instance, we are working actively on a means to allow CREST systems to synthesise the behaviour of individual update functions and transition guards. Initial results of this research have already been presented at dedicated workshops [51].

We are also looking into the use of reinforcement learning approaches for the automated generation of system controllers for CREST models. The aim is to create software models of controller entities that will provide valid system inputs and assert that beneficial behaviour is enforced and unfavourable behaviour avoided. Usually a manual controller creation process is time-intensive and error-prone, and highly complex for hybrid systems specifically. Thus, automated generation techniques will allow to strongly improve this system engineering task.

Embedding a Behaviour DSLs It appears, that for some user groups (e.g. non-programmers) the implicit restrictions on the Python code that can be used inside transition guards and update functions outweigh the advantages of using an internal DSL. While a completely external DSL would certainly solve this issue, one of our future developments investigates the embedding of a dedicated DSL into crestdsl. For instance, it would be possible to use the crestdsl to define the basic system structure, but enforce another (restricted) DSL for the specification of transition guards and behaviour functions. This way, it is more easily possible to guide the users’ behaviour and avoid frustration by incomprehensible statements. In the background, the embedded behaviour DSL could then be transpiled to Python code to rely on the existing language implementation.

Similar DSLs We intentionally designed CREST and crestdsl for a specific type of CPSs. In these systems, each component has one behaviour and parallel activities are separated in individual subentities. However, there are numerous industrial installations where the component behaviour is highly dynamic and dependent on many factors. Petri nets have been successfully used to model parallel and concurrent behaviour. Currently, we are investigating an adapted version of CREST, where the entity automata are replaced with Petri nets. Evidently, this modification also requires an alteration of the operational semantics, such as an adaptation of the synchronism concern. Similarly, other system requirements demand different extensions. Digital communication can be introduced by reusing concepts from e.g. communication diagrams.

8 Summary

CREST is a hybrid domain-specific language (DSL) specifically created for the modeling of cyber-physical system (CPS) whose components primarily interact through the exchange of physical resource flows such as water, heat or electricity. The language reuses well-known concepts from existing formalisms to create a coherent language with aim on usability and simplicity. Through its formal basis, CREST concisely combines the syntactic and semantic features from several languages to support vital modeling tasks such as sound model creation, well-defined simulation and formal verification. In this article, we elaborate on the development of CREST and provide details on the language requirements of the DSL. CREST ’s graphical syntax is inspired by common modeling formalisms such as automata notations and architecture description languages. Its carefully formalised operational semantics assert the thorough combination of the languages’ features into an executable formalism that focuses on the implementation of key aspects such as reactivity, locality, synchronism, parallelism and non-determinism. These principles have been identified as necessities for the correct modeling of our target systems, prior to the definition of the DSL. CREST is implemented in the form of crestdsl, an internal DSL that is based on the foundations of the Python programming language. Its aim is to provide a convenient means to CPS modeling, with the advantage of reusing a widespread programming language syntax. The use of Python as host language also has the advantage that existing language infrastructure such as familiar IDEs, established best practices and well-tested execution environments can be reused. Both CREST and crestdsl were developed with pragmatism in mind, so as to avoid recreating and redeveloping modeling concepts that are already broadly available.