Lars Helander, författare på Prover - Engineering a Safer World Interlocking Design Automation to meet demand for complex digital train control Wed, 08 Jan 2025 15:23:16 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 Floating point model checking https://www.prover.com/formal-methods/floating-point-model-checking/ Mon, 04 Nov 2019 09:55:48 +0000 https://www.prover.com/?p=3628 We at Prover are very happy to announce the release of version 4.0 of our model checker Prover SL CE (PSL). The most interesting new feature is support for IEEE 754 floating point calculations, so I will dedicate this technical blog post to floats with a concrete example of a floating point system which we [...]

Inlägget Floating point model checking dök först upp på Prover - Engineering a Safer World.

]]>
We at Prover are very happy to announce the release of version 4.0 of our model checker Prover SL CE (PSL). The most interesting new feature is support for IEEE 754 floating point calculations, so I will dedicate this technical blog post to floats with a concrete example of a floating point system which we analyze using PSL.

Floating point example – an exotic investment

To illustrate the usefulness of floats inside our model checker, we will define a non-trivial investment game, formalize it in an extension of HLL (the input language of PSL), and check some properties of the investment using PSL. The rules of the investment are as follows:

  1. The initial investment is 100.0 of our favorite currency (let’s call it “satcoins”).
  2. A year of normal return, our investment grows with 5 %.
  3. A good year, which happens at least once every 5 years, the investment grows with 20 % plus an extra bonus of 0 to 100 satcoins.
  4. A bad year, which also happens at least once every 5 years, the investment is halved.
  5. An excellent year, which happens at least once every 7 years, the invested amount is squared (multiplied by itself).
  6. Finally, a disastrous year, which happens at least once every 8 years, cancels the result of an excellent year: the new amount is the quotient of the current amount and that of the previous year.
  7. The first year is a normal year.
  8. An excellent or disastrous year is always followed by a bad year.
  9. The calculations shall be performed according to the international floating point standard IEEE 754 using 32-bit binary floats (known as the type “float” in the C programming language).

This informal specification of the investment rules can be straightforwardly translated into extended HLL. We will omit some of the details. However, the part relating to the actual floating point calculations could be formalized into the following code:

@ include FP_8_23
Namespaces:
FP_8_23 {
 Types:
  enum {normal, good, bad, excellent, disastrous} Year;
 Declarations:
  Year year;
  int [0, 100] bonus;
  float amount;
 Definitions:
  rne := Rounding::rne;     // Round to nearest tie to even
  I(amount) := 100.0;
  X(amount) := (year
               |normal     => mul(rne, amount, 1.05)
               |good       => add(rne, mul(rne, amount, 1.2),
                                       of_int(rne, bonus))
	       |bad        => div(rne, amount, 2.0)
	       |excellent  => mul(rne, amount, amount)
	       |disastrous => div(rne, amount, pre(amount)));
}

Checking properties of our investment

The kind of properties of floating point calculations that we are interested in checking using our model checker, is typically properties such as “the calculation does not overflow our 32-bit representation (no infinities)” and “divisions by zero does not happen (no NaN values appear)”. Indeed, PSL is able to prove the absence of overflow and NaN for the first 80 years of our investment over night. Note that properties such as “the expected average return on investment” is outside of the realm of model checking, and so will not be considered here. Instead, we will ask PSL if our investment can generate (if we’re lucky) at least a billion satcoins. We do this, as usual, by trying to prove that the amount on our account is always less than a billion. If the tool disproves (or falsifies) this property, then it will provide a counterexample to the proof as a solution:

Proof Obligations:
 lt(amount, 1.0e9);

In a matter of minutes, in single thread on an average laptop, PSL tells us that after at least 13 years, there exists a scenario in which we become satcoin billionaires. (In this time, PSL has also proved that there are no scenarios shorter than 13 years.) Below is one out of many scenarios found by PSL. The table should be read by combining the “year”, “bonus” and “amount” on the same line to determine the “amount” on the next line. As usual when dealing with automatic provers, the scenario may surprise at first, but is nevertheless valid and easily verified.

year bonus amount  (opening balance)
0 normal 100.0
1 bad 104.99999237060546875
2 disastrous 52.499996185302734375
3 bad 0.5
4 good 0 0.25
5 excellent 0.300000011920928955078125
6 bad 0.0900000035762786865234375
7 excellent 0.04500000178813934326171875
8 bad 0.00202500005252659320831298828125
9 good 100 0.001012500026263296604156494140625
10 disastrous 100.00121307373046875
11 bad 98766.625
12 excellent 49383.3125
13 [2438711552.0]

Summary

We have shown how a non-trivial floating point calculation, in the guise of an investment game, can be successfully checked by PSL 4.0. It should be noted, however, that automatic verification of floating point arithmetic is notoriously hard, and there are numerous pitfalls, so it is important to have realistic expectations. PSL uses underlying techniques known as bitblasting and SAT-solving, which are extremely precise (down to the last bit), but of course come with an attached cost. For example, if we double the precision from 32-bit to 64-bit floats in our investment game, runtimes approximately quadruple. Fortunately, PSL provides very efficient support for parallel computing, which means that such effects on runtime can be compensated by the use of more processor cores.

We conclude by observing that for complex safety-critical reactive systems with a little bit of floating point arithmetic, automatic reasoning tools such as PSL can be very useful, especially for finding unexpected scenarios such as the generation of NaN, infinities and other values out of the expected range.

Inlägget Floating point model checking dök först upp på Prover - Engineering a Safer World.

]]>
Using HLL to solve Sudoku puzzles https://www.prover.com/modeling/using-hll-to-solve-sudoku-puzzles/ Wed, 10 Jul 2019 09:37:45 +0000 https://www.prover.com/?p=2532 Using HLL to solve Sudoku puzzles

Inlägget Using HLL to solve Sudoku puzzles dök först upp på Prover - Engineering a Safer World.

]]>

In a recent post we celebrated the 10th anniversary of the declarative, formal language HLL. The language is used extensively in the railway signaling domain for the formal verification of interlocking logic and CBTC subsystems (such as zone controllers). In this more technical post we will familiarize the reader further with HLL, by formalizing the famous Sudoku problem in the language, and using an off-the-shelf proof engine to solve Sudoku puzzles.

The Sudoku problem is a very easy problem for modern proof engines (such as SAT solvers), but it will serve us well in introducing the reader to HLL. To be sure, we will only be able to illustrate a relatively small subset of HLL, a language which has grown quite a bit over the years. To formalize and solve Sudoku problems we will mainly need integers, arrays and quantifiers.

Creating the grid

We start by representing a partially filled Sudoku grid using a 9×9 matrix where each element is an integer in the range 0 to 9. Empty slots are filled with zeroes. The problem itself was in the "Very Difficult" category over at 7sudoku.

Declarations:
 int partialGrid[9][9];
Definitions:
 partialGrid := ;

Then, we will define our problem grid by replacing the zeroes in the partial grid with unknown integers in the range 1 to 9. Creating unknown (or free) variables in HLL is very simple: we just need to declare them.

Declarations:
 int [1,9] unknown[9][9];
 int [1,9] grid[9][9];
Definitions:
 grid[i][j] := if partialGrid[i][j] == 0 then unknown[i][j] 
                                         else partialGrid[i][j];

Expressing the Sudoku problem

Now, we will express the Sudoku problem itself over our grid, by using quantification. Remember that the objective of a Sudoku is to fill the grid so that all rows, all columns and all of the nine 3×3 subgrids each contains all the digits from 1 to 9. In HLL, array-indexing is 0-based, yielding the below formulation of our Sudoku-objective.

Definitions:
 objective := ALL digit:[1,9] (
    ALL row:[0,8] SOME col:[0,8] (grid[row][col] == digit)
  & ALL col:[0,8] SOME row:[0,8] (grid[row][col] == digit)
  & ALL subgridRow:[0,2], subgridCol:[0,2]
      SOME sRow:[0,2], sCol:[0,2]
    (grid[subgridRow * 3 + sRow]
         [subgridCol * 3 + sCol] == digit));

Finally, we will ask a proof engine whether our objective is attainable (or satisfiable) or not. We do that by trying to prove that there is no solution (by negating the problem). If there is a solution (i.e. a counterexample to our proof), the proof engine will provide us with it.

Proof Obligations:
 ~objective;

Using a modern proof engine (such as Prover SL Certifier Edition) we will be provided with a solution in a fraction of a second.

$1*: grid[0][0] is [1]
$2: grid[0][1] is [7]
$3: grid[0][2] is [6]
$4: grid[0][3] is [4]
$5: grid[0][4] is [5]
$6: grid[0][5] is [3]
$7: grid[0][6] is [8]
$8: grid[0][7] is [9]
$9: grid[0][8] is [2]
    ...
$80: grid[8][7] is [2]
$81: grid[8][8] is [9]

Improving the presentation

To improve the presentation a bit, we will use the temporal dimension of HLL (cf. LTL). HLL is a language based on streams, which are just infinite sequences of values, one for each discrete time step. The idea is to transform the 9×9 grid into 9 streams (representing the rows), of which we will inspect only the 9 first values. Doing this is a bit technical. We need to 1) redefine the grid as a memory that keeps its value in each time step, and 2) define a counter that counts time steps modulo 9 (starting at 0), before we can create our 9 "stream rows".

Declarations:
 int [0,8] counter;
 int [1,9] rows[9];
Definitions:
 grid[i][j] := if partialGrid[i][j] == 0 then unknown[i][j] 
                                         else partialGrid[i][j],
               grid[i][j]; // Keep value in next time step
 counter := 0, (counter + 1) % 9;
 rows[i] := grid[i][counter];

Finally, when asked to extend the solution up to the 9th time step, the proof engine provides us with a prettier view of the Sudoku-solution (without any measurable time penalty by the way).

$1*: rows[0] is 1 7 6 4 5 3 8 9 [2]
$2: rows[1] is 9 4 2 7 8 1 3 6 [5]
$3: rows[2] is 5 8 3 6 2 9 7 4 [1]
$4: rows[3] is 3 9 1 5 4 6 2 8 [7]
$5: rows[4] is 6 2 7 9 1 8 5 3 [4]
$6: rows[5] is 4 5 8 2 3 7 9 1 [6]
$7: rows[6] is 2 1 4 8 9 5 6 7 [3]
$8: rows[7] is 7 3 9 1 6 2 4 5 [8]
$9: rows[8] is 8 6 5 3 7 4 1 2 [9]

Note that this is the raw, unedited, output given by the proof engine's "Why"-module, which can be used to interactively explore counterexamples.

Summary

To summarize, we have shown how the well-known Sudoku problem can be formalized in HLL and solved using a general purpose proof engine (don't hesitate to contact sales@prover.com to buy your own license!). The output has been optimized using prefixes of length 9 of streams (sequences of values), so that it looks almost like what one would expect from a purpose-built Sudoku solver.

How safe and efficient are your rail control systems? Let’s find out!

Inlägget Using HLL to solve Sudoku puzzles dök först upp på Prover - Engineering a Safer World.

]]>
HLL formal language celebrates 10 years https://www.prover.com/verification-validation/hll-formal-language/ Sat, 30 Jun 2018 17:03:00 +0000 https://www.prover.com/?p=2409 The formal language HLL (High Level Language) has emerged in recent years as a quite popular language for formal verification of safety-critical systems, especially in the railway signaling domain. This year marks the 10th anniversary of its conception. The history of HLL The language has its roots in the proof engine technologies developed by Prover in the 1980s (Stålmarck's [...]

Inlägget HLL formal language celebrates 10 years dök först upp på Prover - Engineering a Safer World.

]]>
The formal language HLL (High Level Language) has emerged in recent years as a quite popular language for formal verification of safety-critical systems, especially in the railway signaling domain. This year marks the 10th anniversary of its conception.

The history of HLL

The language has its roots in the proof engine technologies developed by Prover in the 1980s (Stålmarck’s method), 1990s (temporal induction) and early 2000s (higher level theories) and its development was prompted by a need for trusted (or certifiable) formal verification.

HLL is a declarative language with a broad panel of types and operators and is suitable for modelling discrete-time sequential behaviors and expressing properties of these behaviors.

Or to put it differently: if you have a reactive system (such as an interlocking or a CBTC subsystem) with some inputs, outputs and internal state (memory), and you want to formally prove that some present or future conditions on the outputs shall follow from some past or present conditions on the inputs, then HLL may be the right language for you. The language, with its associated tools, can be used for applications such as invariant checking, sequential equivalence checking, test case generation or static code analysis (detection of runtime errors such as overflows or divisions by zero).

Version 1.0 of HLL was released in 2008 and the language is being continually developed. The latest version includes, in addition to the basic core of Boolean logic and integer arithmetic, features such as enums, arrays, tuples, structs, recursive functions, quantifiers, polymorphism, namespaces and blocks. The imperative dialect of HLL also supports statements such as assignments, if-then-else, loops and procedures.

The HLL formal language success

The success of HLL can possibly be attributed to its ease of use (flexible and intuitive) coupled with the support by formal verification tools that both scale up in practice for a wide variety of systems, and provide certifiable results based on diversification and proof logging/checking.

Find out more about HLL here.
You can also check out our HLL Forum – The community for those who use HLL

Inlägget HLL formal language celebrates 10 years dök först upp på Prover - Engineering a Safer World.

]]>