feat: lift runtime into language, start of zelus 2024 compatibility
This commit is contained in:
parent
dc8d941b84
commit
ffc583985a
37 changed files with 1154 additions and 143 deletions
|
|
@ -751,3 +751,20 @@ let hybrid ball () = y where
|
|||
and assert (y >= 0)
|
||||
```
|
||||
Is this an issue?
|
||||
|
||||
= Ideas
|
||||
|
||||
== Continuous assertions with lifted runtime
|
||||
|
||||
Given a synchronous node simulating a hybrid one :
|
||||
```zelus
|
||||
let hybrid sincos () = (sin, cos) where
|
||||
rec der sin = cos init 0.0
|
||||
and der cos = -. sin init 1.0
|
||||
|
||||
let node sincos_sim = Solve.solve_ode45 sincos
|
||||
```
|
||||
We could create a primitive `Solve.assert_continuous` which would take as input
|
||||
an `'a value` and a function `'a -> Solve.cond`, where `Solve.cond` is a
|
||||
zero-crossing expression, for instance `fun v -> Solve.up(-. v)`. This could be
|
||||
passed along to a zero-crossing solver during continuous phases.
|
||||
|
|
|
|||
115
doc/rep.typ
115
doc/rep.typ
|
|
@ -11,10 +11,12 @@
|
|||
#let simulink = smallcaps[Simulink]
|
||||
#let sundials = smallcaps[Sundials CVODE]
|
||||
#let zelus = smallcaps[Zélus]
|
||||
#let TODO(..what) = {
|
||||
#let note(color, prefix, ..what) = {
|
||||
let msg = if what.pos().len() == 0 { "" } else { ": " + what.pos().join("") }
|
||||
block(fill: red, width: 100%, inset: 5pt, align(center, raw("TODO" + msg)))
|
||||
block(fill: color, width: 100%, inset: 5pt, align(center, raw(prefix + msg)))
|
||||
}
|
||||
#let TODO(..what) = note(red, "TODO", ..what)
|
||||
#let MENTION(..what) = note(gray, "MENTION", ..what)
|
||||
#let adot(s) = $accent(#s, dot)$
|
||||
#let addot(s) = $accent(#s, dot.double)$
|
||||
|
||||
|
|
@ -97,14 +99,14 @@ physical systems. Continuous phases are described using ordinary differential
|
|||
equations (ODEs), while discrete phases can be represented as a reactive
|
||||
program in a synchronous language such as #lustre or #esterel.
|
||||
|
||||
As a first example, say we wish to model a bouncing ball. We could start by
|
||||
describing its distance from the ground $y$ with a second-order differential
|
||||
equation
|
||||
$ addot(y) = -9.81 $
|
||||
As an illustration, say we wished to model an extensively studied system: a
|
||||
bouncing ball. We could start by describing its distance from the ground $y$ as
|
||||
a function of time, with a second-order differential equation
|
||||
$ addot(y) = -9.81, $
|
||||
where $addot(y)$ denotes the second order derivative of $y$ with
|
||||
respect to time (the acceleration of the ball), and $9.81$ is the gravitational
|
||||
constant $g$: the acceleration of the ball is its negation. We now give the
|
||||
initial position and speed of the ball:
|
||||
respect to time $(d^2y)/(d t^2)$ (the acceleration of the ball), and $9.81$ is
|
||||
the gravitational constant $g$: the acceleration of the ball is its negation. We
|
||||
now give the initial position and speed of the ball:
|
||||
$ y(0) = 50 space space space adot(y)(0) = 0 $
|
||||
We have just described an initial value problem: given an ODE and an initial
|
||||
value for its dependent variable, its solution is a function $y(t)$ returning
|
||||
|
|
@ -113,17 +115,20 @@ this function using an ODE solver, such as #sundials.
|
|||
|
||||
As of right now, our ball will fall until the end of time; we have not said
|
||||
anything about how it bounces when it hits the floor. To do so, we need a notion
|
||||
of discrete _events_. These are modelled by zero-crossings: we monitor a certain
|
||||
value and stop when it goes from strictly negative to positive or null. For our
|
||||
purposes, we choose $-y$ as the monitored value, and call the zero-crossing
|
||||
event $z$. When $z$ occurs (i.e., when the ball touches the ground), we set the
|
||||
speed $adot(y)$ to $-k dot "last"(adot(y))$, where $"last"(y)$ denotes the left
|
||||
limit of $y$ (we cannot specify $adot(y)$ in terms of itself), and $k$ is a
|
||||
factor modelling the loss of inertia due to the collision (say, $0.8$). We can
|
||||
then resume the approximation of the solution.
|
||||
of _events_: we need to identify exactly when the ball hits the ground, so that
|
||||
we may take action to make it bounce. These events are modelled by
|
||||
zero-crossings: we monitor a certain value and stop when it goes from strictly
|
||||
negative to positive or null. For our purposes, we choose $-y$ as the monitored
|
||||
value, and call the zero-crossing event $z$. When $z$ occurs (i.e., when the
|
||||
ball touches the ground), we set the speed $adot(y)$ to
|
||||
$-k dot #raw(lang: "zelus", "last")\(adot(y))$, where
|
||||
$#raw(lang: "zelus", "last")\(y)$ denotes the left limit of $y$ (we cannot
|
||||
specify $adot(y)$ in terms of itself), and $k$ is a factor modelling the loss of
|
||||
inertia due to the collision (say, $0.8$). We can then resume the approximation
|
||||
of the solution.
|
||||
|
||||
@lst:ball.zls shows how such a model might be expressed in the concrete syntax
|
||||
of #zelus.
|
||||
of #zelus @cit:zelus_sync_lng_with_ode.
|
||||
|
||||
#figure(placement: top, gap: 2em,
|
||||
```zelus
|
||||
|
|
@ -135,22 +140,68 @@ of #zelus.
|
|||
caption: [The bouncing ball in #zelus]
|
||||
) <lst:ball.zls>
|
||||
|
||||
More formally, a hybrid system can be described as an automaton
|
||||
More formally, and as done in @cit:alg_ana_hyb_sys, a hybrid system $cal(H)$ can
|
||||
be defined as a graph whose nodes represent continuous behaviour, and whose
|
||||
edges represent discrete transitions:
|
||||
$ cal(H) = (L o c, V a r, E d g, A c t, I n v, I n i) $
|
||||
where:
|
||||
- $L o c$ is a finite set of _locations_;
|
||||
- $V a r$ is a finite set of _variables_;
|
||||
- $E d g subset.eq L o c times F times L o c$ is a finite set of _transitions_
|
||||
|
||||
|
||||
== Executing models
|
||||
|
||||
Executing such a model is quite simple. There are two modes of execution:
|
||||
discrete and continuous. In continuous mode, we call the ODE solver in order to
|
||||
obtain an approximation of the variables defined through ODEs, and monitor for
|
||||
zero-crossings. If a zero-crossing occurs, we enter the discrete mode, in which
|
||||
we perform computation steps as needed, until no other zero-crossing occurs, in
|
||||
which case we go back to the continuous mode, and repeat, as seen in @automaton.
|
||||
To execute such a model, we first compile it into a synchronous function, as
|
||||
described in @cit:sync_based_codegen_hyb_sys_lng. The details of this
|
||||
compilation step are not particularly relevant to our purposes, and can be
|
||||
ignored. What is more interesting is the output of this compilation step: a
|
||||
single synchronous function. The simulation loop is then itself described as a
|
||||
synchronous function operating on
|
||||
|
||||
#figure(finite.automaton(
|
||||
(D: (D: "cascade", C: "no cascade"),
|
||||
C: (C: "no zero-crossing", D: "zero-crossing")),
|
||||
initial: "D", final: (), layout: finite.layout.linear.with(spacing: 3)
|
||||
), caption: [High-level overview of the runtime], placement: top) <automaton>
|
||||
#MENTION("Use of a single solver")
|
||||
|
||||
#pagebreak()
|
||||
|
||||
// The compilation of a hybrid model into a synchronous function is described in
|
||||
// detail in @cit:sync_based_codegen_hyb_sys_lng, but can be summarized quite
|
||||
// succintly as follows. By pairing this synchronous function with an
|
||||
// off-the-shelf ODE solver like #sundials, we can then simulate the dynamics of
|
||||
// the system. This is done by repeatedly performing execution steps according to
|
||||
// two different modes: discrete and continuous.
|
||||
|
||||
// The continuous mode operates as follows: we first call the ODE solver in order
|
||||
// to approximate the dynamics of the model's continuous state.
|
||||
|
||||
// Continuous steps first call the ODE solver to approximate the dynamics of the
|
||||
// model's continuous variables. The solver will return a function defined on a
|
||||
// time interval, which we then provide as input to the zero-crossing solver, which
|
||||
// will monitor the evolution of zero-crossing values along this interval. After
|
||||
// both solvers have been called, we choose what the next step's mode will be:
|
||||
// - if no zero-crossings have been detected, we output the entire solution
|
||||
// provided by the ODE solver, and the next step remains continuous;
|
||||
// - if a zero-crossing occurs, we return the solution provided by the ODE solver
|
||||
// up to the zero-crossing instant, and the next step becomes a discrete step.
|
||||
|
||||
// Discrete steps perform state changes and side effects. We first call the model's
|
||||
// step function, which updates the state and outputs a value. We then decide what
|
||||
// the next step is. If a zero-crossing event occured due to the current step, the
|
||||
// next step is another discrete step. If no new event occured, we perform a
|
||||
// continuous step.
|
||||
|
||||
// Executing such a model is quite simple. There are two modes of execution:
|
||||
// discrete and continuous. In continuous mode, we call the ODE solver in order
|
||||
// to obtain an approximation of the variables defined through ODEs, and monitor
|
||||
// for zero-crossings. If a zero-crossing occurs, we enter the discrete mode, in
|
||||
// which we perform computation steps as needed, until no other zero-crossing
|
||||
// occurs, in which case we go back to the continuous mode, and repeat, as seen
|
||||
// in @automaton.
|
||||
|
||||
// #figure(finite.automaton(
|
||||
// (D: (D: "cascade", C: "no cascade"),
|
||||
// C: (C: "no zero-crossing", D: "zero-crossing")),
|
||||
// initial: "D", final: (), layout: finite.layout.linear.with(spacing: 3)
|
||||
// ), caption: [High-level overview of the runtime], placement: top) <automaton>
|
||||
|
||||
= Runtime
|
||||
To solve this issue, we need to redefine what the runtime of our hybrid system
|
||||
|
|
@ -180,10 +231,10 @@ required by the assertion becomes a state variable.
|
|||
|
||||
== Solvers as synchronous nodes
|
||||
== Simulations as synchronous nodes
|
||||
#TODO("talk about the new runtime")
|
||||
#MENTION("the new runtime")
|
||||
|
||||
= Assertions
|
||||
#TODO("talk about how assertions are done")
|
||||
#MENTION("how assertions are done")
|
||||
|
||||
#pagebreak()
|
||||
= Annex
|
||||
|
|
|
|||
149
doc/sources.bib
149
doc/sources.bib
|
|
@ -1,16 +1,137 @@
|
|||
@article{
|
||||
ns_sem_benveniste_bourke_caillaud_pouzet,
|
||||
title={Non-Standard Semantics of Hybrid Systems Modelers},
|
||||
author={Benveniste, Albert and Bourke, Timothy and
|
||||
Caillaud, Benoıt and Pouzet, Marc},
|
||||
year={2011},
|
||||
language={en}
|
||||
@article{cit:nonstd_sem_hyb_sys_mod,
|
||||
title = {Non-standard semantics of hybrid systems modelers},
|
||||
journal = {Journal of Computer and System Sciences},
|
||||
volume = {78},
|
||||
number = {3},
|
||||
pages = {877-910},
|
||||
year = {2012},
|
||||
note = {In Commemoration of Amir Pnueli},
|
||||
issn = {0022-0000},
|
||||
doi = {https://doi.org/10.1016/j.jcss.2011.08.009},
|
||||
url = {https://www.sciencedirect.com/science/article/pii/S0022000011001061},
|
||||
author = {Albert Benveniste and Timothy Bourke and Benoît Caillaud and Marc
|
||||
Pouzet},
|
||||
keywords = {Hybrid systems, Hybrid systems modelers, Non-standard analysis,
|
||||
Non-standard semantics, Constructive semantics, Kahn process
|
||||
networks, Compilation of hybrid systems},
|
||||
abstract = {Hybrid system modelers have become a corner stone of complex
|
||||
embedded system development. Embedded systems include not only
|
||||
control components and software, but also physical devices. In
|
||||
this area, Simulink is a de facto standard design framework, and
|
||||
Modelica a new player. However, such tools raise several issues
|
||||
related to the lack of reproducibility of simulations
|
||||
(sensitivity to simulation parameters and to the choice of a
|
||||
simulation engine). In this paper we propose using techniques
|
||||
from non-standard analysis to define a semantic domain for hybrid
|
||||
systems. Non-standard analysis is an extension of classical
|
||||
analysis in which infinitesimal (the ε and η in the celebrated
|
||||
generic sentence ∀ε∃η… of college maths) can be manipulated as
|
||||
first class citizens. This approach allows us to define both a
|
||||
denotational semantics, a constructive semantics, and a Kahn
|
||||
Process Network semantics for hybrid systems, thus establishing
|
||||
simulation engines on a sound but flexible mathematical
|
||||
foundation. These semantics offer a clear distinction between the
|
||||
concerns of the numerical analyst (solving differential
|
||||
equations) and those of the computer scientist (generating
|
||||
execution schemes). We also discuss a number of practical and
|
||||
fundamental issues in hybrid system modelers that give rise to
|
||||
non-reproducibility of results, non-determinism, and undesirable
|
||||
side effects. Of particular importance are cascaded mode changes
|
||||
(also called “zero-crossings” in the context of hybrid systems
|
||||
modelers).},
|
||||
}
|
||||
@inbook{
|
||||
opsem_lee_zheng,
|
||||
title={Operational Semantics of Hybrid Systems},
|
||||
ISBN={978-3-540-25108-8},
|
||||
author={Lee, Edward A. and Zheng, Haiyang},
|
||||
year={2005},
|
||||
language={en}
|
||||
@inbook{cit:op_sem_hyb_sys,
|
||||
address = {Berlin, Heidelberg},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
title = {Operational Semantics of Hybrid Systems},
|
||||
volume = {3414},
|
||||
ISBN = {978-3-540-25108-8},
|
||||
url = {http://link.springer.com/10.1007/978-3-540-31954-2_2},
|
||||
DOI = {10.1007/978-3-540-31954-2_2},
|
||||
abstractNote = {This paper discusses an interpretation of hybrid systems as
|
||||
executable models. A specification of a hybrid system for this
|
||||
purpose can be viewed as a program in a domain-specific
|
||||
programming language. We describe the semantics of HyVisual,
|
||||
which is such a domain-specific programming language. The
|
||||
semantic properties of such a language affect our ability to
|
||||
understand, execute, and analyze a model. We discuss several
|
||||
semantic issues that come in defining such a programming
|
||||
language, such as the interpretation of discontinuities in
|
||||
continuous-time signals, and the interpretation of
|
||||
discrete-event signals in hybrid systems, and the
|
||||
consequences of numerical ODE solver techniques. We describe
|
||||
the solution in HyVisual by giving its operational semantics.
|
||||
},
|
||||
booktitle = {Hybrid Systems: Computation and Control},
|
||||
publisher = {Springer Berlin Heidelberg},
|
||||
author = {Lee, Edward A. and Zheng, Haiyang},
|
||||
editor = {Morari, Manfred and Thiele, Lothar},
|
||||
year = {2005},
|
||||
pages = {25–53},
|
||||
collection = {Lecture Notes in Computer Science},
|
||||
language = {en},
|
||||
}
|
||||
@inproceedings{cit:zelus_sync_lng_with_ode,
|
||||
address = {Philadelphia Pennsylvania USA},
|
||||
title = {Zélus: a synchronous language with ODEs},
|
||||
ISBN = {978-1-4503-1567-8},
|
||||
url = {https://dl.acm.org/doi/10.1145/2461328.2461348},
|
||||
DOI = {10.1145/2461328.2461348},
|
||||
abstractNote = { Z´elus is a new programming language for modeling systems
|
||||
that mix discrete logical time and continuous time behaviors.
|
||||
From a user’s perspective, its main originality is to extend
|
||||
an existing Lustre-like synchronous language with Ordinary
|
||||
Differential Equations (ODEs). The extension is conservative:
|
||||
any synchronous program expressed as dataflow equations and
|
||||
hierarchical automata can be composed arbitrarily with ODEs
|
||||
in the same source code. },
|
||||
booktitle = { Proceedings of the 16th international conference on Hybrid
|
||||
systems: computation and control },
|
||||
publisher = {ACM},
|
||||
author = {Bourke, Timothy and Pouzet, Marc},
|
||||
year = {2013},
|
||||
month = apr,
|
||||
pages = {113–118},
|
||||
language = {en},
|
||||
}
|
||||
@inbook{cit:sync_based_codegen_hyb_sys_lng,
|
||||
address = {Berlin, Heidelberg},
|
||||
series = {Lecture Notes in Computer Science},
|
||||
title = {A Synchronous-Based Code Generator for Explicit Hybrid Systems
|
||||
Languages},
|
||||
volume = {9031},
|
||||
rights = {http://www.springer.com/tdm},
|
||||
ISBN = {978-3-662-46662-9},
|
||||
url = {http://link.springer.com/10.1007/978-3-662-46663-6_4},
|
||||
DOI = {10.1007/978-3-662-46663-6_4},
|
||||
abstractNote = {Modeling languages for hybrid systems are cornerstones of
|
||||
embedded systems development in which software interacts with
|
||||
a physical environment. Sequential code generation from such
|
||||
languages is important for simulation efficiency and for
|
||||
producing code for embedded targets. Despite being routinely
|
||||
used in industrial compilers, code generation is rarely, if
|
||||
ever, described in full detail, much less formalized. Yet
|
||||
formalization is an essential step in building trustable
|
||||
compilers for critical embedded software development.},
|
||||
booktitle = {Compiler Construction},
|
||||
publisher = {Springer Berlin Heidelberg},
|
||||
author = {Bourke, Timothy and Colaço, Jean-Louis and Pagano, Bruno and
|
||||
Pasteur, Cédric and Pouzet, Marc},
|
||||
editor = {Franke, Björn},
|
||||
year = {2015},
|
||||
pages = {69–88},
|
||||
collection = {Lecture Notes in Computer Science},
|
||||
language = {en},
|
||||
}
|
||||
@article{cit:alg_ana_hyb_sys,
|
||||
title = {The algorithmic analysis of hybrid systems},
|
||||
author = {Alur, Rajeev and Courcoubetis, Costas and Halbwachs, Nicolas and
|
||||
Henzinger, Thomas A and Ho, P-H and Nicollin, Xavier and Olivero,
|
||||
Alfredo and Sifakis, Joseph and Yovine, Sergio},
|
||||
journal = {Theoretical computer science},
|
||||
volume = {138},
|
||||
number = {1},
|
||||
pages = {3--34},
|
||||
year = {1995},
|
||||
publisher = {Elsevier},
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue