On this page a tutorial about how to add a new algorithm to the library is given. As example, a simple version of the window optimization algorithm is used. Therefore, a sub-circuit of the given circuit with a predefined size (a so called window) is extracted. Afterwards, this window is re-synthesized. If the resulting circuit is smaller, then the original sub-circuit is replaced with it. Therefore, different cost functions are applied.
This tutorial examines the following topics:
skeleton
scriptThe helpers
directory provide a script called skeleton
, which can be used to create a basic skeleton for a new algorithm. The corresponding files are automatically generated in the unstable
directory of the toolkit. In order to generate a skeleton for the desired window optimization approach, the following values should be entered after invoking the script.
This creates a skeleton for the algorithm, i.e. two files unstable/optimization/window_optimization.hpp and unstable/optimization/window_optimization.cpp. The directory optimization
is automatically determined from the choice 6 at type of algorithm. Three options were added to the settings:
u
suffix, since it is an unsigned
variable)The information what data type to create and what are the necessary parameters is also determined from the algorithm type (here 6).
At first, we add the includes needed for the implementation of the algorithm. It becomes more clear when describing the algorithm implementation, where the corresponding functions are needed. Some are needed because we have corresponding setting parameters.
Note that it is not optimal to include the simple_simulation in the algorithm. It is needed for the re-synthesize step, but forces a strong dependency to the algorithms. The better solution would be to offer a simulation functor to the settings struct.
Now, we can focus on the actual implementation. The parsing of the properties into local variables and time measurement code has already been generated by the skeleton script together with an entry point to start with the implementation.
First, the meta-data of the base
circuit is copied to the circuit circ
, which should be created by this algorithm.
The variable pos
keeps track of the position in the base
circuit, from where the window should be extracted.
As long as the end of the base
circuit is not reached...
... sub-circuits are extracted. Therefore, the length
of the window is determined. If there are enough gates left, window_length
is used for this purpose. Otherwise, only the remaining gates are considered. Having the length, the variable to
stores the right-hand side position of the considered sub-circuit.
With that information a sub-circuit can be extracted.
From that sub-circuit its corresponding truth table is extracted. Therefore, a simulation engine and the function circuit_to_truth_table is applied.
Using this truth table, the sub-circuit is re-synthesized. Therefore, the synthesis approach given by the functor (parsed from the settings above) is applied. The success value of the synthesis algorithm is stored in the variable ok
.
Afterwards it is checked, if the newly synthesized circuit is cheaper. This is the case if the synthesis was successful and if the resulting circuit is cheaper than the original with respect to the given cost function.
Depending on whether the new circuit part
is cheaper, either that circuit or the old sub-circuit is appended to the circuit circ
.
Since no errors occurred, true
is returned by the algorithm.
The helpers
directory also provides a script in order to generate an executable of an implemented approach (called testcase
). Such an executable can be used e.g. to test a newly implemented approach without binding it to the Python library. As the skeleton
script above, the testcase
script is interactive and basically generates a skeleton for a main
function as well as for program options. If desired, it also integrates the resulting approach (as test case) into the build environment.
After invoking the script, first the parameters to be used have to be chosen. In the example, parameters denoting the original circuit realization (to be optimized), the final circuit (where the result is stored), and the cost function, respectively, is selected. Afterwards, a default value for the window length is added.
Doing that, a file examples/test_wo.cpp
is created. Into this file, some includes statements needed to implement the test case are added (highlighted by an additional comment below).
Now, we can focus on the implementation of the test case. We create a new empty circuit newcirc
, which should be generated by the window optimization algorithm. Therefore, the settings given by the parameters are set. After invoking the optimization approach, statistics about the newly created circuit as well as the run-time are printed out. Finally, the code generated by the script for writing the circuit realization is modified.. Instead of circuit todo
the circuit newcirc
should be written.
After re-building RevKit (make sure to build it with -DBUILD_UNSTABLE=ON and -DBUILD_EXAMPLES=ON) you can find the executable in ./build/examples/test_wo