<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://prob.hhu.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Joshua+Schmidt</id>
	<title>ProB Documentation - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://prob.hhu.de/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Joshua+Schmidt"/>
	<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=Special:Contributions/Joshua_Schmidt"/>
	<updated>2026-05-27T09:02:01Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=Using_ProB_with_Z3&amp;diff=5473</id>
		<title>Using ProB with Z3</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=Using_ProB_with_Z3&amp;diff=5473"/>
		<updated>2023-06-06T07:39:07Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* More details */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:User Manual]]&lt;br /&gt;
&lt;br /&gt;
The current nightly versions of ProB can make use of [https://github.com/Z3Prover/z3 Z3] as an alternate way of solving constraints.&lt;br /&gt;
&lt;br /&gt;
= How to use Z3 within ProB =&lt;br /&gt;
&lt;br /&gt;
One can start a REPL (Read-Eval-Print-Loop) by starting probcli with the &#039;-repl&#039; command line option. Any predicate preceded with :z3 will be solved by Z3 considering the current machine&#039;s state. The command :z3-free can be used to solve a constraint without considering the current machine&#039;s state. The full integration of Z3 and ProB’s kernel can be enabled by setting the corresponding preference by passing&lt;br /&gt;
&lt;br /&gt;
-p SMT SUPPORTED INTERPRETER TRUE&lt;br /&gt;
&lt;br /&gt;
on the command line.&lt;br /&gt;
&lt;br /&gt;
= How to install Z3 for ProB =&lt;br /&gt;
For Linux and Mac OS, the extension is built on our infrastructure and ships with the regular ProB download. You don&#039;t need to install Z3 on your system.&lt;br /&gt;
&lt;br /&gt;
= What can be translated =&lt;br /&gt;
Currently, the Z3 translation is unable to cope with the following constructs:&lt;br /&gt;
* Generalised concatenation&lt;br /&gt;
* Permutation&lt;br /&gt;
* Iteration and Closure&lt;br /&gt;
&lt;br /&gt;
When using Z3 alone, the solver will report &amp;quot;unsupported_type_or_expression&amp;quot; if it can not handle parts of a constraint.&lt;br /&gt;
&lt;br /&gt;
When used together with ProB, everything Z3 can not be coped with will be handled by ProB alone automatically.&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
Using the repl, one can try out different examples.&lt;br /&gt;
&lt;br /&gt;
First an example which can be solved by Z3 and not by ProB:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; X&amp;lt;Y &amp;amp; Y&amp;lt;X &amp;amp; X:INTEGER&lt;br /&gt;
 % Timeout when posting constraint:&lt;br /&gt;
 % kernel_objects:(_981727#&amp;gt;0)&lt;br /&gt;
 ### Warning: enumerating X : INTEGER : inf:sup ---&amp;gt; -1:3&lt;br /&gt;
 Existentially Quantified Predicate over X,Y is UNKNOWN&lt;br /&gt;
 [FALSE with ** ENUMERATION WARNING **]&lt;br /&gt;
&lt;br /&gt;
Using the Z3 translation it can be solved:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 X&amp;lt;Y &amp;amp; Y&amp;lt;X &amp;amp; X:INTEGER&lt;br /&gt;
 PREDICATE is FALSE&lt;br /&gt;
&lt;br /&gt;
Here an example that shows that Z3 can be used to solve constraints and obtain solutions for the open variables:&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 {x} /\ {y} /= {} &amp;amp; x:1000000..20000000 &amp;amp; y&amp;gt;=0 &amp;amp; y&amp;lt;2000000&lt;br /&gt;
 PREDICATE is TRUE&lt;br /&gt;
 Solution:&lt;br /&gt;
       x = 1000000&lt;br /&gt;
       y = 1000000&lt;br /&gt;
&lt;br /&gt;
As of version 1.10.0-beta4 you can also issue the &amp;lt;t&amp;gt;:z3-version&amp;lt;/t&amp;gt; command in the REPL to obtain version information.&lt;br /&gt;
&lt;br /&gt;
= More details =&lt;br /&gt;
&lt;br /&gt;
A [https://doi.org/10.1007/978-3-319-33693-0_23 paper describing the integration of ProB and Z3] has been published at iFM 2016. You can download the&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/rawdata raw data] from our benchmarks including the R scripts to generate the&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/output resulting graphs].&lt;br /&gt;
&lt;br /&gt;
A [https://link.springer.com/article/10.1007/s10009-022-00682-y journal paper] describing an extended interface to Z3 and alternative translation from B to SMT-LIB using Lambda functions has been published in the International Journal on Software Tools for Technology Transfer in 2022.&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=Using_ProB_with_Z3&amp;diff=5472</id>
		<title>Using ProB with Z3</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=Using_ProB_with_Z3&amp;diff=5472"/>
		<updated>2023-06-06T07:36:47Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Examples */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:User Manual]]&lt;br /&gt;
&lt;br /&gt;
The current nightly versions of ProB can make use of [https://github.com/Z3Prover/z3 Z3] as an alternate way of solving constraints.&lt;br /&gt;
&lt;br /&gt;
= How to use Z3 within ProB =&lt;br /&gt;
&lt;br /&gt;
One can start a REPL (Read-Eval-Print-Loop) by starting probcli with the &#039;-repl&#039; command line option. Any predicate preceded with :z3 will be solved by Z3 considering the current machine&#039;s state. The command :z3-free can be used to solve a constraint without considering the current machine&#039;s state. The full integration of Z3 and ProB’s kernel can be enabled by setting the corresponding preference by passing&lt;br /&gt;
&lt;br /&gt;
-p SMT SUPPORTED INTERPRETER TRUE&lt;br /&gt;
&lt;br /&gt;
on the command line.&lt;br /&gt;
&lt;br /&gt;
= How to install Z3 for ProB =&lt;br /&gt;
For Linux and Mac OS, the extension is built on our infrastructure and ships with the regular ProB download. You don&#039;t need to install Z3 on your system.&lt;br /&gt;
&lt;br /&gt;
= What can be translated =&lt;br /&gt;
Currently, the Z3 translation is unable to cope with the following constructs:&lt;br /&gt;
* Generalised concatenation&lt;br /&gt;
* Permutation&lt;br /&gt;
* Iteration and Closure&lt;br /&gt;
&lt;br /&gt;
When using Z3 alone, the solver will report &amp;quot;unsupported_type_or_expression&amp;quot; if it can not handle parts of a constraint.&lt;br /&gt;
&lt;br /&gt;
When used together with ProB, everything Z3 can not be coped with will be handled by ProB alone automatically.&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
Using the repl, one can try out different examples.&lt;br /&gt;
&lt;br /&gt;
First an example which can be solved by Z3 and not by ProB:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; X&amp;lt;Y &amp;amp; Y&amp;lt;X &amp;amp; X:INTEGER&lt;br /&gt;
 % Timeout when posting constraint:&lt;br /&gt;
 % kernel_objects:(_981727#&amp;gt;0)&lt;br /&gt;
 ### Warning: enumerating X : INTEGER : inf:sup ---&amp;gt; -1:3&lt;br /&gt;
 Existentially Quantified Predicate over X,Y is UNKNOWN&lt;br /&gt;
 [FALSE with ** ENUMERATION WARNING **]&lt;br /&gt;
&lt;br /&gt;
Using the Z3 translation it can be solved:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 X&amp;lt;Y &amp;amp; Y&amp;lt;X &amp;amp; X:INTEGER&lt;br /&gt;
 PREDICATE is FALSE&lt;br /&gt;
&lt;br /&gt;
Here an example that shows that Z3 can be used to solve constraints and obtain solutions for the open variables:&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 {x} /\ {y} /= {} &amp;amp; x:1000000..20000000 &amp;amp; y&amp;gt;=0 &amp;amp; y&amp;lt;2000000&lt;br /&gt;
 PREDICATE is TRUE&lt;br /&gt;
 Solution:&lt;br /&gt;
       x = 1000000&lt;br /&gt;
       y = 1000000&lt;br /&gt;
&lt;br /&gt;
As of version 1.10.0-beta4 you can also issue the &amp;lt;t&amp;gt;:z3-version&amp;lt;/t&amp;gt; command in the REPL to obtain version information.&lt;br /&gt;
&lt;br /&gt;
= More details =&lt;br /&gt;
&lt;br /&gt;
A [https://doi.org/10.1007/978-3-319-33693-0_23 paper describing the integration of ProB and Z3] has been published at iFM 2016. You can download the&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/rawdata raw data] from our benchmarks including the R scripts to generate the&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/output resulting graphs].&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=Using_ProB_with_Z3&amp;diff=5471</id>
		<title>Using ProB with Z3</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=Using_ProB_with_Z3&amp;diff=5471"/>
		<updated>2023-06-06T07:34:44Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* What can be translated */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:User Manual]]&lt;br /&gt;
&lt;br /&gt;
The current nightly versions of ProB can make use of [https://github.com/Z3Prover/z3 Z3] as an alternate way of solving constraints.&lt;br /&gt;
&lt;br /&gt;
= How to use Z3 within ProB =&lt;br /&gt;
&lt;br /&gt;
One can start a REPL (Read-Eval-Print-Loop) by starting probcli with the &#039;-repl&#039; command line option. Any predicate preceded with :z3 will be solved by Z3 considering the current machine&#039;s state. The command :z3-free can be used to solve a constraint without considering the current machine&#039;s state. The full integration of Z3 and ProB’s kernel can be enabled by setting the corresponding preference by passing&lt;br /&gt;
&lt;br /&gt;
-p SMT SUPPORTED INTERPRETER TRUE&lt;br /&gt;
&lt;br /&gt;
on the command line.&lt;br /&gt;
&lt;br /&gt;
= How to install Z3 for ProB =&lt;br /&gt;
For Linux and Mac OS, the extension is built on our infrastructure and ships with the regular ProB download. You don&#039;t need to install Z3 on your system.&lt;br /&gt;
&lt;br /&gt;
= What can be translated =&lt;br /&gt;
Currently, the Z3 translation is unable to cope with the following constructs:&lt;br /&gt;
* Generalised concatenation&lt;br /&gt;
* Permutation&lt;br /&gt;
* Iteration and Closure&lt;br /&gt;
&lt;br /&gt;
When using Z3 alone, the solver will report &amp;quot;unsupported_type_or_expression&amp;quot; if it can not handle parts of a constraint.&lt;br /&gt;
&lt;br /&gt;
When used together with ProB, everything Z3 can not be coped with will be handled by ProB alone automatically.&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
Using the repl, one can try out different examples.&lt;br /&gt;
&lt;br /&gt;
First an example which can be solved by Z3 and not by ProB:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; X&amp;lt;Y &amp;amp; Y&amp;lt;X &amp;amp; X:INTEGER&lt;br /&gt;
 % Timeout when posting constraint:&lt;br /&gt;
 % kernel_objects:(_981727#&amp;gt;0)&lt;br /&gt;
 ### Warning: enumerating X : INTEGER : inf:sup ---&amp;gt; -1:3&lt;br /&gt;
 Existentially Quantified Predicate over X,Y is UNKNOWN&lt;br /&gt;
 [FALSE with ** ENUMERATION WARNING **]&lt;br /&gt;
&lt;br /&gt;
Using the Z3 translation it can be solved:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 X&amp;lt;Y &amp;amp; Y&amp;lt;X &amp;amp; X:INTEGER&lt;br /&gt;
 PREDICATE is FALSE&lt;br /&gt;
&lt;br /&gt;
Now an example which can be solved by ProB’s own solver:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; (2|-&amp;gt;4):{y|#x.(y=(x|-&amp;gt;x+2))}&lt;br /&gt;
 PREDICATE is TRUE&lt;br /&gt;
&lt;br /&gt;
This one cannot be solved by earlier versions of Z3 and ProB (but can now be solved in the latest nightly release):&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 (2|-&amp;gt;4):{y|#x.(y=(x|-&amp;gt;x+2))}&lt;br /&gt;
 PREDICATE is UNKNOWN: solver_answered_unknown&lt;br /&gt;
&lt;br /&gt;
Here an example that shows that Z3 can be used to solve constraints and obtain solutions for the open variables:&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 {x} /\ {y} /= {} &amp;amp; x:1000000..20000000 &amp;amp; y&amp;gt;=0 &amp;amp; y&amp;lt;2000000&lt;br /&gt;
 PREDICATE is TRUE&lt;br /&gt;
 Solution:&lt;br /&gt;
       x = 1000000&lt;br /&gt;
       y = 1000000&lt;br /&gt;
&lt;br /&gt;
As of version 1.10.0-beta4 you can also issue the &amp;lt;t&amp;gt;:z3-version&amp;lt;/t&amp;gt; command in the REPL to obtain version information.&lt;br /&gt;
&lt;br /&gt;
= More details =&lt;br /&gt;
&lt;br /&gt;
A [https://doi.org/10.1007/978-3-319-33693-0_23 paper describing the integration of ProB and Z3] has been published at iFM 2016. You can download the&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/rawdata raw data] from our benchmarks including the R scripts to generate the&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/output resulting graphs].&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=Using_ProB_with_Z3&amp;diff=5470</id>
		<title>Using ProB with Z3</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=Using_ProB_with_Z3&amp;diff=5470"/>
		<updated>2023-06-06T07:31:30Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* How to install Z3 for ProB */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:User Manual]]&lt;br /&gt;
&lt;br /&gt;
The current nightly versions of ProB can make use of [https://github.com/Z3Prover/z3 Z3] as an alternate way of solving constraints.&lt;br /&gt;
&lt;br /&gt;
= How to use Z3 within ProB =&lt;br /&gt;
&lt;br /&gt;
One can start a REPL (Read-Eval-Print-Loop) by starting probcli with the &#039;-repl&#039; command line option. Any predicate preceded with :z3 will be solved by Z3 considering the current machine&#039;s state. The command :z3-free can be used to solve a constraint without considering the current machine&#039;s state. The full integration of Z3 and ProB’s kernel can be enabled by setting the corresponding preference by passing&lt;br /&gt;
&lt;br /&gt;
-p SMT SUPPORTED INTERPRETER TRUE&lt;br /&gt;
&lt;br /&gt;
on the command line.&lt;br /&gt;
&lt;br /&gt;
= How to install Z3 for ProB =&lt;br /&gt;
For Linux and Mac OS, the extension is built on our infrastructure and ships with the regular ProB download. You don&#039;t need to install Z3 on your system.&lt;br /&gt;
&lt;br /&gt;
= What can be translated =&lt;br /&gt;
Currently, the Z3 translation is unable to cope with the following constructs:&lt;br /&gt;
* Strings&lt;br /&gt;
* Generalised union, generalised intersection&lt;br /&gt;
* Generalised concatenation&lt;br /&gt;
* Permutation&lt;br /&gt;
* Iteration and Closure&lt;br /&gt;
* Projection&lt;br /&gt;
&lt;br /&gt;
When using Z3 alone, the solver will report &amp;quot;unsupported_type_or_expression&amp;quot; if it can not handle parts of a constraint.&lt;br /&gt;
&lt;br /&gt;
When used together with ProB, everything Z3 can not be coped with will be handled by ProB alone automatically.&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
Using the repl, one can try out different examples.&lt;br /&gt;
&lt;br /&gt;
First an example which can be solved by Z3 and not by ProB:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; X&amp;lt;Y &amp;amp; Y&amp;lt;X &amp;amp; X:INTEGER&lt;br /&gt;
 % Timeout when posting constraint:&lt;br /&gt;
 % kernel_objects:(_981727#&amp;gt;0)&lt;br /&gt;
 ### Warning: enumerating X : INTEGER : inf:sup ---&amp;gt; -1:3&lt;br /&gt;
 Existentially Quantified Predicate over X,Y is UNKNOWN&lt;br /&gt;
 [FALSE with ** ENUMERATION WARNING **]&lt;br /&gt;
&lt;br /&gt;
Using the Z3 translation it can be solved:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 X&amp;lt;Y &amp;amp; Y&amp;lt;X &amp;amp; X:INTEGER&lt;br /&gt;
 PREDICATE is FALSE&lt;br /&gt;
&lt;br /&gt;
Now an example which can be solved by ProB’s own solver:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; (2|-&amp;gt;4):{y|#x.(y=(x|-&amp;gt;x+2))}&lt;br /&gt;
 PREDICATE is TRUE&lt;br /&gt;
&lt;br /&gt;
This one cannot be solved by earlier versions of Z3 and ProB (but can now be solved in the latest nightly release):&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 (2|-&amp;gt;4):{y|#x.(y=(x|-&amp;gt;x+2))}&lt;br /&gt;
 PREDICATE is UNKNOWN: solver_answered_unknown&lt;br /&gt;
&lt;br /&gt;
Here an example that shows that Z3 can be used to solve constraints and obtain solutions for the open variables:&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 {x} /\ {y} /= {} &amp;amp; x:1000000..20000000 &amp;amp; y&amp;gt;=0 &amp;amp; y&amp;lt;2000000&lt;br /&gt;
 PREDICATE is TRUE&lt;br /&gt;
 Solution:&lt;br /&gt;
       x = 1000000&lt;br /&gt;
       y = 1000000&lt;br /&gt;
&lt;br /&gt;
As of version 1.10.0-beta4 you can also issue the &amp;lt;t&amp;gt;:z3-version&amp;lt;/t&amp;gt; command in the REPL to obtain version information.&lt;br /&gt;
&lt;br /&gt;
= More details =&lt;br /&gt;
&lt;br /&gt;
A [https://doi.org/10.1007/978-3-319-33693-0_23 paper describing the integration of ProB and Z3] has been published at iFM 2016. You can download the&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/rawdata raw data] from our benchmarks including the R scripts to generate the&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/output resulting graphs].&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=Using_ProB_with_Z3&amp;diff=5469</id>
		<title>Using ProB with Z3</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=Using_ProB_with_Z3&amp;diff=5469"/>
		<updated>2023-06-06T07:24:54Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* How to use Z3 within ProB */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:User Manual]]&lt;br /&gt;
&lt;br /&gt;
The current nightly versions of ProB can make use of [https://github.com/Z3Prover/z3 Z3] as an alternate way of solving constraints.&lt;br /&gt;
&lt;br /&gt;
= How to use Z3 within ProB =&lt;br /&gt;
&lt;br /&gt;
One can start a REPL (Read-Eval-Print-Loop) by starting probcli with the &#039;-repl&#039; command line option. Any predicate preceded with :z3 will be solved by Z3 considering the current machine&#039;s state. The command :z3-free can be used to solve a constraint without considering the current machine&#039;s state. The full integration of Z3 and ProB’s kernel can be enabled by setting the corresponding preference by passing&lt;br /&gt;
&lt;br /&gt;
-p SMT SUPPORTED INTERPRETER TRUE&lt;br /&gt;
&lt;br /&gt;
on the command line.&lt;br /&gt;
&lt;br /&gt;
= How to install Z3 for ProB =&lt;br /&gt;
First of all, download a nightly build of ProB from the [[Download|Downloads]] page. To connect Z3 to ProB you also need the proper extension.&lt;br /&gt;
For Linux and Mac OS, the extension is built by on our infrastructure and ships with the regular ProB download.&lt;br /&gt;
For Windows, you can download it from the following URLs:&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/windows32/z3interface.dll 32bit]&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/windows64/z3interface.dll 64bit]&lt;br /&gt;
and place it in the &amp;quot;lib&amp;quot; folder of the ProB nightly build.&lt;br /&gt;
&lt;br /&gt;
In addition to ProB, you need to install Z3 by downloading it from [https://github.com/Z3Prover Z3&#039;s GitHub page]. Previously, ProB 1.6 was linked against the stable release 4.4.1 of Z3. Current nightly builds of ProB work with version 4.8.7 of Z3.&lt;br /&gt;
Inside the zip file of Z3 you will find a folder called &amp;quot;bin&amp;quot; with the z3 binary and the belonging libraries inside.&lt;br /&gt;
&lt;br /&gt;
These Z3 libraries have to be made available to ProB. On Linux or Mac, this can either be done by placing them in an appropriate folder (like /usr/lib or /usr/local/lib) or by setting an environmental variable (like LD_LIBRARY_PATH on Linux or DYLD_LIBRARY_PATH on Mac).&lt;br /&gt;
On Windows, you can place z3.dll in the main folder of the ProB distribution, i. e., on the same level as the lib directory, not inside it.&lt;br /&gt;
If the libraries can not be loaded, ProB will answer with &amp;quot;solver_not_available&amp;quot; when Z3 is queried.&lt;br /&gt;
&lt;br /&gt;
* Versions 4.8.8 and 4.8.9 of Z3 are currently not recommended for use with ProB. An [https://github.com/Z3Prover/z3/issues/4699 issue in the model extraction] can lead to erroneous models.&lt;br /&gt;
&lt;br /&gt;
= What can be translated =&lt;br /&gt;
Currently, the Z3 translation is unable to cope with the following constructs:&lt;br /&gt;
* Strings&lt;br /&gt;
* Generalised union, generalised intersection&lt;br /&gt;
* Generalised concatenation&lt;br /&gt;
* Permutation&lt;br /&gt;
* Iteration and Closure&lt;br /&gt;
* Projection&lt;br /&gt;
&lt;br /&gt;
When using Z3 alone, the solver will report &amp;quot;unsupported_type_or_expression&amp;quot; if it can not handle parts of a constraint.&lt;br /&gt;
&lt;br /&gt;
When used together with ProB, everything Z3 can not be coped with will be handled by ProB alone automatically.&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
Using the repl, one can try out different examples.&lt;br /&gt;
&lt;br /&gt;
First an example which can be solved by Z3 and not by ProB:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; X&amp;lt;Y &amp;amp; Y&amp;lt;X &amp;amp; X:INTEGER&lt;br /&gt;
 % Timeout when posting constraint:&lt;br /&gt;
 % kernel_objects:(_981727#&amp;gt;0)&lt;br /&gt;
 ### Warning: enumerating X : INTEGER : inf:sup ---&amp;gt; -1:3&lt;br /&gt;
 Existentially Quantified Predicate over X,Y is UNKNOWN&lt;br /&gt;
 [FALSE with ** ENUMERATION WARNING **]&lt;br /&gt;
&lt;br /&gt;
Using the Z3 translation it can be solved:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 X&amp;lt;Y &amp;amp; Y&amp;lt;X &amp;amp; X:INTEGER&lt;br /&gt;
 PREDICATE is FALSE&lt;br /&gt;
&lt;br /&gt;
Now an example which can be solved by ProB’s own solver:&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; (2|-&amp;gt;4):{y|#x.(y=(x|-&amp;gt;x+2))}&lt;br /&gt;
 PREDICATE is TRUE&lt;br /&gt;
&lt;br /&gt;
This one cannot be solved by earlier versions of Z3 and ProB (but can now be solved in the latest nightly release):&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 (2|-&amp;gt;4):{y|#x.(y=(x|-&amp;gt;x+2))}&lt;br /&gt;
 PREDICATE is UNKNOWN: solver_answered_unknown&lt;br /&gt;
&lt;br /&gt;
Here an example that shows that Z3 can be used to solve constraints and obtain solutions for the open variables:&lt;br /&gt;
&lt;br /&gt;
 &amp;gt;&amp;gt;&amp;gt; :z3 {x} /\ {y} /= {} &amp;amp; x:1000000..20000000 &amp;amp; y&amp;gt;=0 &amp;amp; y&amp;lt;2000000&lt;br /&gt;
 PREDICATE is TRUE&lt;br /&gt;
 Solution:&lt;br /&gt;
       x = 1000000&lt;br /&gt;
       y = 1000000&lt;br /&gt;
&lt;br /&gt;
As of version 1.10.0-beta4 you can also issue the &amp;lt;t&amp;gt;:z3-version&amp;lt;/t&amp;gt; command in the REPL to obtain version information.&lt;br /&gt;
&lt;br /&gt;
= More details =&lt;br /&gt;
&lt;br /&gt;
A [https://doi.org/10.1007/978-3-319-33693-0_23 paper describing the integration of ProB and Z3] has been published at iFM 2016. You can download the&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/rawdata raw data] from our benchmarks including the R scripts to generate the&lt;br /&gt;
* [https://www3.hhu.de/stups/downloads/z3interface/output resulting graphs].&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4700</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4700"/>
		<updated>2021-01-27T17:55:40Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;FIRST_SOLUTION&amp;lt;/b&amp;gt;: Return the first solution found.&lt;br /&gt;
* &amp;lt;b&amp;gt;INTERACTIVE&amp;lt;/b&amp;gt;: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
** If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
** If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
** If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The method &amp;lt;b&amp;gt;addf()&amp;lt;/b&amp;gt; is just a wrapper for a Java set&#039;s &amp;lt;b&amp;gt;add()&amp;lt;/b&amp;gt; method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A &amp;lt;b&amp;gt;BSynthesisResult&amp;lt;/b&amp;gt; is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class &amp;lt;b&amp;gt;BLibrary&amp;lt;/b&amp;gt; to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum &amp;lt;b&amp;gt;LibraryComponentName&amp;lt;/b&amp;gt; provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considering the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt; respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use &amp;lt;b&amp;gt;addLibraryComponent(LibraryComponentName) &amp;lt;/b&amp;gt;several times.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;updateComponentAmount(LibraryComponentName,AddAmount)&amp;lt;/b&amp;gt; adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;setComponentAmount(LibraryComponentName,Amount)&amp;lt;/b&amp;gt; explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method &amp;lt;b&amp;gt;setEnumerateConstants()&amp;lt;/b&amp;gt;. If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum &amp;lt;b&amp;gt;ConsiderIfType&amp;lt;/b&amp;gt;. There are three possibilities:&lt;br /&gt;
* &amp;lt;b&amp;gt;NONE&amp;lt;/b&amp;gt;: Do not consider if-statements.&lt;br /&gt;
* &amp;lt;b&amp;gt;EXPLICIT&amp;lt;/b&amp;gt;: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* &amp;lt;b&amp;gt;IMPLICIT&amp;lt;/b&amp;gt;: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;br /&gt;
&lt;br /&gt;
The described example&#039;s code can be found here: [https://github.com/Joshua27/ProBramSynthesis ProBramSynthesis]&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4699</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4699"/>
		<updated>2021-01-27T17:54:19Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;FIRST_SOLUTION&amp;lt;/b&amp;gt;: Return the first solution found.&lt;br /&gt;
* &amp;lt;b&amp;gt;INTERACTIVE&amp;lt;/b&amp;gt;: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
** If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
** If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
** If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The method &amp;lt;b&amp;gt;addf()&amp;lt;/b&amp;gt; is just a wrapper for a Java set&#039;s &amp;lt;b&amp;gt;add()&amp;lt;/b&amp;gt; method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A &amp;lt;b&amp;gt;BSynthesisResult&amp;lt;/b&amp;gt; is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class &amp;lt;b&amp;gt;BLibrary&amp;lt;/b&amp;gt; to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum &amp;lt;b&amp;gt;LibraryComponentName&amp;lt;/b&amp;gt; provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considering the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt; respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use &amp;lt;b&amp;gt;addLibraryComponent(LibraryComponentName) &amp;lt;/b&amp;gt;several times.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;updateComponentAmount(LibraryComponentName,AddAmount)&amp;lt;/b&amp;gt; adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;setComponentAmount(LibraryComponentName,Amount)&amp;lt;/b&amp;gt; explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method &amp;lt;b&amp;gt;setEnumerateConstants()&amp;lt;/b&amp;gt;. If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum &amp;lt;b&amp;gt;ConsiderIfType&amp;lt;/b&amp;gt;. There are three possibilities:&lt;br /&gt;
* &amp;lt;b&amp;gt;NONE&amp;lt;/b&amp;gt;: Do not consider if-statements.&lt;br /&gt;
* &amp;lt;b&amp;gt;EXPLICIT&amp;lt;/b&amp;gt;: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* &amp;lt;b&amp;gt;IMPLICIT&amp;lt;/b&amp;gt;: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;br /&gt;
&lt;br /&gt;
The described example&#039;s code can be found here: [[https://github.com/Joshua27/ProBramSynthesis]]&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4698</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4698"/>
		<updated>2021-01-27T17:53:52Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;FIRST_SOLUTION&amp;lt;/b&amp;gt;: Return the first solution found.&lt;br /&gt;
* &amp;lt;b&amp;gt;INTERACTIVE&amp;lt;/b&amp;gt;: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
** If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
** If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
** If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The method &amp;lt;b&amp;gt;addf()&amp;lt;/b&amp;gt; is just a wrapper for a Java set&#039;s &amp;lt;b&amp;gt;add()&amp;lt;/b&amp;gt; method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A &amp;lt;b&amp;gt;BSynthesisResult&amp;lt;/b&amp;gt; is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class &amp;lt;b&amp;gt;BLibrary&amp;lt;/b&amp;gt; to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum &amp;lt;b&amp;gt;LibraryComponentName&amp;lt;/b&amp;gt; provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considering the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt; respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use &amp;lt;b&amp;gt;addLibraryComponent(LibraryComponentName) &amp;lt;/b&amp;gt;several times.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;updateComponentAmount(LibraryComponentName,AddAmount)&amp;lt;/b&amp;gt; adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;setComponentAmount(LibraryComponentName,Amount)&amp;lt;/b&amp;gt; explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method &amp;lt;b&amp;gt;setEnumerateConstants()&amp;lt;/b&amp;gt;. If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum &amp;lt;b&amp;gt;ConsiderIfType&amp;lt;/b&amp;gt;. There are three possibilities:&lt;br /&gt;
* &amp;lt;b&amp;gt;NONE&amp;lt;/b&amp;gt;: Do not consider if-statements.&lt;br /&gt;
* &amp;lt;b&amp;gt;EXPLICIT&amp;lt;/b&amp;gt;: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* &amp;lt;b&amp;gt;IMPLICIT&amp;lt;/b&amp;gt;: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;br /&gt;
&lt;br /&gt;
The described example&#039;s code can be found here: [https://github.com/Joshua27/ProBramSynthesis|ProBramSynthesis]&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4697</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4697"/>
		<updated>2021-01-27T17:52:43Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;FIRST_SOLUTION&amp;lt;/b&amp;gt;: Return the first solution found.&lt;br /&gt;
* &amp;lt;b&amp;gt;INTERACTIVE&amp;lt;/b&amp;gt;: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
** If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
** If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
** If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The method &amp;lt;b&amp;gt;addf()&amp;lt;/b&amp;gt; is just a wrapper for a Java set&#039;s &amp;lt;b&amp;gt;add()&amp;lt;/b&amp;gt; method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A &amp;lt;b&amp;gt;BSynthesisResult&amp;lt;/b&amp;gt; is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class &amp;lt;b&amp;gt;BLibrary&amp;lt;/b&amp;gt; to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum &amp;lt;b&amp;gt;LibraryComponentName&amp;lt;/b&amp;gt; provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considering the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt; respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use &amp;lt;b&amp;gt;addLibraryComponent(LibraryComponentName) &amp;lt;/b&amp;gt;several times.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;updateComponentAmount(LibraryComponentName,AddAmount)&amp;lt;/b&amp;gt; adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;setComponentAmount(LibraryComponentName,Amount)&amp;lt;/b&amp;gt; explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method &amp;lt;b&amp;gt;setEnumerateConstants()&amp;lt;/b&amp;gt;. If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum &amp;lt;b&amp;gt;ConsiderIfType&amp;lt;/b&amp;gt;. There are three possibilities:&lt;br /&gt;
* &amp;lt;b&amp;gt;NONE&amp;lt;/b&amp;gt;: Do not consider if-statements.&lt;br /&gt;
* &amp;lt;b&amp;gt;EXPLICIT&amp;lt;/b&amp;gt;: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* &amp;lt;b&amp;gt;IMPLICIT&amp;lt;/b&amp;gt;: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;br /&gt;
&lt;br /&gt;
The described example&#039;s code can be found here: [https://github.com/Joshua27/ProBramSynthesis]&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4696</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4696"/>
		<updated>2021-01-27T17:49:21Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;FIRST_SOLUTION&amp;lt;/b&amp;gt;: Return the first solution found.&lt;br /&gt;
* &amp;lt;b&amp;gt;INTERACTIVE&amp;lt;/b&amp;gt;: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
** If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
** If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
** If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The method &amp;lt;b&amp;gt;addf()&amp;lt;/b&amp;gt; is just a wrapper for a Java set&#039;s &amp;lt;b&amp;gt;add()&amp;lt;/b&amp;gt; method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A &amp;lt;b&amp;gt;BSynthesisResult&amp;lt;/b&amp;gt; is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class &amp;lt;b&amp;gt;BLibrary&amp;lt;/b&amp;gt; to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum &amp;lt;b&amp;gt;LibraryComponentName&amp;lt;/b&amp;gt; provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considering the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt; respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use &amp;lt;b&amp;gt;addLibraryComponent(LibraryComponentName) &amp;lt;/b&amp;gt;several times.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;updateComponentAmount(LibraryComponentName,AddAmount)&amp;lt;/b&amp;gt; adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;setComponentAmount(LibraryComponentName,Amount)&amp;lt;/b&amp;gt; explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method &amp;lt;b&amp;gt;setEnumerateConstants()&amp;lt;/b&amp;gt;. If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum &amp;lt;b&amp;gt;ConsiderIfType&amp;lt;/b&amp;gt;. There are three possibilities:&lt;br /&gt;
* &amp;lt;b&amp;gt;NONE&amp;lt;/b&amp;gt;: Do not consider if-statements.&lt;br /&gt;
* &amp;lt;b&amp;gt;EXPLICIT&amp;lt;/b&amp;gt;: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* &amp;lt;b&amp;gt;IMPLICIT&amp;lt;/b&amp;gt;: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4695</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4695"/>
		<updated>2021-01-27T17:48:41Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;FIRST_SOLUTION&amp;lt;/b&amp;gt;: Return the first solution found.&lt;br /&gt;
* &amp;lt;b&amp;gt;INTERACTIVE&amp;lt;/b&amp;gt;: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
** If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
** If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
** If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
The method &amp;lt;b&amp;gt;addf()&amp;lt;/b&amp;gt; is just a wrapper for a Java set&#039;s &amp;lt;b&amp;gt;add()&amp;lt;/b&amp;gt; method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A &amp;lt;b&amp;gt;BSynthesisResult&amp;lt;/b&amp;gt; is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note, we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class &amp;lt;b&amp;gt;BLibrary&amp;lt;/b&amp;gt; to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum &amp;lt;b&amp;gt;LibraryComponentName&amp;lt;/b&amp;gt; provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considering the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt; respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use &amp;lt;b&amp;gt;addLibraryComponent(LibraryComponentName) &amp;lt;/b&amp;gt;several times.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;updateComponentAmount(LibraryComponentName,AddAmount)&amp;lt;/b&amp;gt; adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;setComponentAmount(LibraryComponentName,Amount)&amp;lt;/b&amp;gt; explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method &amp;lt;b&amp;gt;setEnumerateConstants()&amp;lt;/b&amp;gt;. If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum &amp;lt;b&amp;gt;ConsiderIfType&amp;lt;/b&amp;gt;. There are three possibilities:&lt;br /&gt;
* &amp;lt;b&amp;gt;NONE&amp;lt;/b&amp;gt;: Do not consider if-statements.&lt;br /&gt;
* &amp;lt;b&amp;gt;EXPLICIT&amp;lt;/b&amp;gt;: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* &amp;lt;b&amp;gt;IMPLICIT&amp;lt;/b&amp;gt;: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4694</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4694"/>
		<updated>2021-01-27T17:48:23Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;FIRST_SOLUTION&amp;lt;/b&amp;gt;: Return the first solution found.&lt;br /&gt;
* &amp;lt;b&amp;gt;INTERACTIVE&amp;lt;/b&amp;gt;: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
** If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
** If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
** If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note that the method &amp;lt;b&amp;gt;addf()&amp;lt;/b&amp;gt; is just a wrapper for a Java set&#039;s &amp;lt;b&amp;gt;add()&amp;lt;/b&amp;gt; method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A &amp;lt;b&amp;gt;BSynthesisResult&amp;lt;/b&amp;gt; is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note, we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class &amp;lt;b&amp;gt;BLibrary&amp;lt;/b&amp;gt; to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum &amp;lt;b&amp;gt;LibraryComponentName&amp;lt;/b&amp;gt; provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considering the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt; respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use &amp;lt;b&amp;gt;addLibraryComponent(LibraryComponentName) &amp;lt;/b&amp;gt;several times.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;updateComponentAmount(LibraryComponentName,AddAmount)&amp;lt;/b&amp;gt; adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;setComponentAmount(LibraryComponentName,Amount)&amp;lt;/b&amp;gt; explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method &amp;lt;b&amp;gt;setEnumerateConstants()&amp;lt;/b&amp;gt;. If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum &amp;lt;b&amp;gt;ConsiderIfType&amp;lt;/b&amp;gt;. There are three possibilities:&lt;br /&gt;
* &amp;lt;b&amp;gt;NONE&amp;lt;/b&amp;gt;: Do not consider if-statements.&lt;br /&gt;
* &amp;lt;b&amp;gt;EXPLICIT&amp;lt;/b&amp;gt;: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* &amp;lt;b&amp;gt;IMPLICIT&amp;lt;/b&amp;gt;: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4693</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4693"/>
		<updated>2021-01-27T17:47:51Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;FIRST_SOLUTION&amp;lt;/b&amp;gt;: Return the first solution found.&lt;br /&gt;
* &amp;lt;b&amp;gt;INTERACTIVE&amp;lt;/b&amp;gt;: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
** If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
** If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
** If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note, the method &amp;lt;b&amp;gt;addf()&amp;lt;/b&amp;gt; is just a wrapper for a Java set&#039;s &amp;lt;b&amp;gt;add()&amp;lt;/b&amp;gt; method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A &amp;lt;b&amp;gt;BSynthesisResult&amp;lt;/b&amp;gt; is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note, we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class &amp;lt;b&amp;gt;BLibrary&amp;lt;/b&amp;gt; to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum &amp;lt;b&amp;gt;LibraryComponentName&amp;lt;/b&amp;gt; provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considering the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt; respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use &amp;lt;b&amp;gt;addLibraryComponent(LibraryComponentName) &amp;lt;/b&amp;gt;several times.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;updateComponentAmount(LibraryComponentName,AddAmount)&amp;lt;/b&amp;gt; adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use &amp;lt;b&amp;gt;setComponentAmount(LibraryComponentName,Amount)&amp;lt;/b&amp;gt; explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method &amp;lt;b&amp;gt;setEnumerateConstants()&amp;lt;/b&amp;gt;. If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum &amp;lt;b&amp;gt;ConsiderIfType&amp;lt;/b&amp;gt;. There are three possibilities:&lt;br /&gt;
* &amp;lt;b&amp;gt;NONE&amp;lt;/b&amp;gt;: Do not consider if-statements.&lt;br /&gt;
* &amp;lt;b&amp;gt;EXPLICIT&amp;lt;/b&amp;gt;: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* &amp;lt;b&amp;gt;IMPLICIT&amp;lt;/b&amp;gt;: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4692</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4692"/>
		<updated>2021-01-27T17:44:54Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;FIRST_SOLUTION&amp;lt;/b&amp;gt;: Return the first solution found.&lt;br /&gt;
* &amp;lt;b&amp;gt;INTERACTIVE&amp;lt;/b&amp;gt;: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
** If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
** If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
** If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note, the method addf() is just a wrapper for a Java set&#039;s add() method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using synthesizePredicate():&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A **BSynthesisResult** is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note, we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class **BLibrary** to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum LibraryComponentName provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considerings the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for synthesizePredicate() and synthesizeOperation() respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use addLibraryComponent(LibraryComponentName) several times.&lt;br /&gt;
* Use updateComponentAmount(LibraryComponentName,AddAmount) adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use setComponentAmount(LibraryComponentName,Amount) explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method setEnumerateConstants(). If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum **ConsiderIfType**. There are three possibilities:&lt;br /&gt;
* NONE: Do not consider if-statements.&lt;br /&gt;
* EXPLICIT: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* IMPLICIT: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4690</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4690"/>
		<updated>2021-01-27T17:36:52Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;b&amp;gt;FIRST_SOLUTION&amp;lt;/b&amp;gt;: Return the first solution found.&lt;br /&gt;
* &amp;lt;b&amp;gt;INTERACTIVE&amp;lt;/b&amp;gt;: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
** If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
** If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
** If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note, the method addf() is just a wrapper for a Java set&#039;s add() method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using synthesizePredicate():&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A **BSynthesisResult** is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note, we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class **BLibrary** to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum LibraryComponentName provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considerings the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for synthesizePredicate() and synthesizeOperation() respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use addLibraryComponent(LibraryComponentName) several times.&lt;br /&gt;
* Use updateComponentAmount(LibraryComponentName,AddAmount) adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use setComponentAmount(LibraryComponentName,Amount) explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method setEnumerateConstants(). If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum **ConsiderIfType**. There are three possibilities:&lt;br /&gt;
* NONE: Do not consider if-statements.&lt;br /&gt;
* EXPLICIT: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* IMPLICIT: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
	<entry>
		<id>https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4689</id>
		<title>BSynthesis</title>
		<link rel="alternate" type="text/html" href="https://prob.hhu.de/w/index.php?title=BSynthesis&amp;diff=4689"/>
		<updated>2021-01-27T17:35:21Z</updated>

		<summary type="html">&lt;p&gt;Joshua Schmidt: /* Program Synthesis */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Program Synthesis =&lt;br /&gt;
&lt;br /&gt;
Program synthesis is the task of generating executable programs from a given specification usually considering a domain specific language. There are many ways to specify the behavior of a program to be synthesized like logical or mathematical formulae (e.g., in the form of pre- and post-conditions) or explicit input-output examples.&lt;br /&gt;
The ProB Prolog core provides an implementation to synthesize B predicates or complete machine operations from explicit state input-output examples. The ProB2 Java API provides an interface to utilize the program synthesis backend.&lt;br /&gt;
The implemented synthesis technique is based on the work by Susmit Jha, Sumit Gulwani et al. [https://people.eecs.berkeley.edu/~sseshia/pubdir/icse10-TR.pdf]&lt;br /&gt;
A synthesis task is encoded as a constraint satisfaction problem in B using the ProB constraint solver and its available backends to find valid solutions.&lt;br /&gt;
&lt;br /&gt;
In order to use the synthesis backend we expect the B machine to be loaded for which B code should be synthesized. The input-output examples describing the behavior of a program to be synthesized then refer to a subset of machine variables.&lt;br /&gt;
In particular, synthesis expects a set of positive and negative examples. In case of synthesizing a B predicate, the synthesized predicate is true for the positive examples and false for the negative examples. Here, an example is a single machine state (input). In case of synthesizing a B machine operation, the positive examples are used to synthesize the B operation&#039;s substitution while both sets of examples are used to synthesize an appropriate precondition for the operation if necessary. Here, an example consists of inputs and outputs, i.e., before- and after-states.&lt;br /&gt;
&lt;br /&gt;
The main class is &amp;lt;b&amp;gt;BSynthesizer&amp;lt;/b&amp;gt; which expects the statespace of a currently loaded B machine on construction:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BSynthesizer synthesizer = new BSynthesizer(stateSpace);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using input-output examples to specify the behavior of a program is most comfortable for the user but most difficult for program synthesis itself. As input-output examples possibly describe ambiguous behavior we provide two modes for synthesis:&lt;br /&gt;
&lt;br /&gt;
* FIRST_SOLUTION: Return the first solution found.&lt;br /&gt;
* INTERACTIVE: Search for another non-equivalent program after finding a solution. There are three possible outcomes:&lt;br /&gt;
* If the constraint solver finds a contradiction, we have found a unique solution and return the program synthesized so far.&lt;br /&gt;
* If the constraint solver cannot find a solution because of exceeding the solver timeout, we return the program synthesized so far. On the one hand, this program might not be the one expected by the user if the examples describe ambiguous behavior. On the other hand, a synthesized program does always satisfy the provided examples. Thus, in practice, completeness depends on the selected solver timeout.&lt;br /&gt;
* If we find another non-equivalent program, we search for an example distinguishing both programs referred to as a distinguishing example. That is, an input state for which both programs yield different outputs. This example can be validated by the user and be considered in the set of examples for another run of synthesis possibly guiding synthesis to a unique solution. For instance, assume we want to synthesize a B predicate by providing a set of positive and negative examples and synthesis has found the predicate &amp;quot;x &amp;gt; 0&amp;quot; first. Assuming the examples describe ambiguous behavior synthesis may find another non-equivalent predicate &amp;quot;x &amp;gt; 1&amp;quot;. A distinguishing example would then be &amp;quot;x = 1&amp;quot; as the first predicate is true and the second one is false for this input.&lt;br /&gt;
The synthesis mode can be set using the method &amp;lt;b&amp;gt;setSynthesisMode()&amp;lt;/b&amp;gt;:&lt;br /&gt;
synthesizer.setSynthesisMode(SynthesisMode.INTERACTIVE);&lt;br /&gt;
&lt;br /&gt;
We provide three classes to create examples:&lt;br /&gt;
* &amp;lt;b&amp;gt;VariableExample.java&amp;lt;/b&amp;gt;: An example for a single machine variable consisting of the machine variable&#039;s name and its pretty printed B value.&lt;br /&gt;
* &amp;lt;b&amp;gt;Example.java&amp;lt;/b&amp;gt;: An example for a machine state which is described by a set of variable examples.&lt;br /&gt;
* &amp;lt;b&amp;gt;IOExample.java&amp;lt;/b&amp;gt;: An input-output example which is described by two examples for input and output respectively.&lt;br /&gt;
&lt;br /&gt;
As mentioned above one can either synthesize a B predicate or a complete machine operation. To do so, a BSynthesizer object provides two methods &amp;lt;b&amp;gt;synthesizePredicate()&amp;lt;/b&amp;gt; and &amp;lt;b&amp;gt;synthesizeOperation()&amp;lt;/b&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Synthesizing a B predicate expects a set of positive examples and a set of negative examples.&lt;br /&gt;
For instance, assume we have loaded a machine that has an integer variable called &amp;quot;floor&amp;quot; and want to synthesize the predicate &amp;quot;floor &amp;gt; 0&amp;quot;.&lt;br /&gt;
First, we create the set of positive and negative examples:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; positiveExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)));&lt;br /&gt;
positiveExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;)));&lt;br /&gt;
&lt;br /&gt;
HashSet&amp;lt;Example&amp;gt; negativeExamples = new HashSet&amp;lt;&amp;gt;();&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-1&amp;quot;)));&lt;br /&gt;
negativeExamples.add(new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;-2&amp;quot;)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note, the method addf() is just a wrapper for a Java set&#039;s add() method enabling a functional style.&lt;br /&gt;
Afterwards, we are able to run synthesis using synthesizePredicate():&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution = synthesizer.synthesizePredicate(positiveExamples, negativeExamples);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Predicate: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A **BSynthesisResult** is either a program or a distinguishing example depending on the selected synthesis mode.&lt;br /&gt;
If synthesis fails, an exception is thrown providing an appropriate error message.&lt;br /&gt;
&lt;br /&gt;
Now assume that we want to synthesize a B machine operation that increases the variable &amp;quot;floor&amp;quot; by one. Again, we first create the set of positive and negative examples which are now examples for input and output:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;0&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;1&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;))));&lt;br /&gt;
positiveIOExamples.add(new IOExample(&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;2&amp;quot;)),&lt;br /&gt;
    new Example().addf(new VariableExample(&amp;quot;floor&amp;quot;, &amp;quot;3&amp;quot;))));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Afterwards, we are able to run synthesis:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
try {&lt;br /&gt;
  BSynthesisResult solution =&lt;br /&gt;
      bSynthesizer.synthesizeOperation(positiveIOExamples, new HashSet&amp;lt;&amp;gt;(), lib);&lt;br /&gt;
  if (solution.isProgram()) {&lt;br /&gt;
    SynthesizedProgram synthesizedProgram = (SynthesizedProgram) solution;&lt;br /&gt;
    System.out.println(&amp;quot;Operation: &amp;quot; + synthesizedProgram);&lt;br /&gt;
  }&lt;br /&gt;
} catch (BSynthesisException e) {&lt;br /&gt;
  //&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Note, we do not provide any negative examples but pass an empty set. If we would provide negative input-output examples, an appropriate precondition would be synthesized for the machine operation. That is, the synthesized operation is enabled for the inputs of the positive examples and disabled for the inputs of the negative examples.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on the combination of program components and, thus, requires a predefined set of library components. For instance, an integer addition is such a library component. If using synthesis as described above, a default library configuration is used. This default configuration tries to use as little components as possible and successively intermingles components or increases the amount of specific components if no solution can be found using the current library configuration. As this default library configuration is mainly selected randomly, synthesis possibly lacks for performance compared to using the exact library of components that is necessary to synthesize a program. To that effect, the user is also able to specify the exact library configuration to be considered during synthesis. We provide the class **BLibrary** to create a specific library configuration.&lt;br /&gt;
&lt;br /&gt;
The enum LibraryComponentName provides all B components that are supported by the synthesis backend. Constructing a BLibrary object provides an empty library considerings the default configuration. We thus have to state that we want to use a specific library of components only and add the desired components using their names. For instance, we want to create a component library using an integer addition and subtraction:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
BLibrary lib = new BLibrary();&lt;br /&gt;
lib.setUseDefaultLibrary(false);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.ADD);&lt;br /&gt;
lib.addLibraryComponent(LibraryComponentName.MINUS);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
A BLibrary object can be passed as the third argument for synthesizePredicate() and synthesizeOperation() respectively.&lt;br /&gt;
&lt;br /&gt;
The employed synthesis technique is based on constraint solving and, thus, each component has a unique output within a synthesized program. For instance, to synthesize the predicate &amp;quot;x + y + z &amp;gt; 2&amp;quot; we need two addition components. There are three ways to adapt the amount how often a specific component should be considered:&lt;br /&gt;
* Use addLibraryComponent(LibraryComponentName) several times.&lt;br /&gt;
* Use updateComponentAmount(LibraryComponentName,AddAmount) adding the second argument to the amount of the specific component.&lt;br /&gt;
* Use setComponentAmount(LibraryComponentName,Amount) explicitly setting a component&#039;s amount.&lt;br /&gt;
Moreover, one can define whether synthesis should consider constants that have to be enumerated by the solver by using the method setEnumerateConstants(). If is false, only constants that are in the scope of the currently loaded machine are considered. For instance, if the current machine does not define any integer constant and we want to synthesize a predicate &amp;quot;x + 1 &amp;gt; y&amp;quot; the constraint solver needs to enumerate an integer constant to the value of 1 to achieve the desired behavior.&lt;br /&gt;
If synthesizing an operation, one can further define whether if-statements should be considered during synthesis represented by the enum **ConsiderIfType**. There are three possibilities:&lt;br /&gt;
* NONE: Do not consider if-statements.&lt;br /&gt;
* EXPLICIT: Use explicit if-then-else expressions as supported by ProB (this might be slow depending on the problem at hand).&lt;br /&gt;
* IMPLICIT: Do not use explicit if-statements but possibly synthesize several machine operations with appropriate preconditions instead (semantically equivalent to using explicit if-statements in a single machine operation).&lt;/div&gt;</summary>
		<author><name>Joshua Schmidt</name></author>
	</entry>
</feed>