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
1.8.3.1