| Prev: The ‘Simple’ Simulation Algorithm | Up: Contents | Next: Optimised Algorithms |
After the initial implementation of the simulator was finished I decided that the next most important step was to implement the ability to read in files describing the circuit. Since my original specification of the project it had become apparent that researchers in the field of quantum computation tended to describe their circuits mathematically. Further, the matrices of certain gates with these circuits sometimes had values that were determined by mathematical equations depending upon their position in the circuit. Many circuits also exhibited a recursive quality.
Bearing this in mind I decided to scrap the original plans for the structure of the input file. The example structure as shown in the section entitled 'The Simulator's Final Design' did not allow mathematical equations. To extend the system to cope with equations would have involved writing a parser. To allow recursion would have involved designing an input file format that would be programmable.
I started research in to the amount of work involved in developing a programmable input file format. I estimated that designing and implementing a format of sufficient quality would take about two weeks of full time programming. Whilst undertaking the research I realised that many of the formulae and constructs in quantum computing texts could be handled be a lazy evaluation technique. As such they were ideal for representing in a functional programming language. I decided that the ideal situation occur if I could find a publicly available C or C++ source-code implementation of a functional programming language. The program could then be integrated within my project. Some further research continued and I managed to find HUGS, a C implementation of the functional language Haskell.
After investigating the source code and capabilities of HUGS I decided that the best way of integrating the program with my own was to leave HUGS as an external program which was called to process circuits. This saved reworking the program to make it compatible with the simulator. However in order to maintain the maximum precision while simulating circuits I modified HUGS to make sure that it used double-precision floating-point numbers throughout.
I decided that the output from HUGS should be a bare sequence of numbers. This minimised the complexity of the parser that I had to build in to the simulator.
Finding HUGS was a stroke of luck. I estimate that it took me about a week to learn HUGS and integrate it within the simulator. The alternative would have been to implement some language myself, which would have been far less powerful and not compatible with the constructs of the major functional languages. The alternative would have also taken at least an extra week of work. The extra time that I spent researching the area of input files certainly paid off and saved me attempting to re-invent the wheel.
In order to capture the output from HUGS in to my application I developed a parser in the simulator was made to take tuples in the form (number of bits in the circuit, initial input value, ordered list of gates). The definition of a gate was (ordered list of bits to act upon, ordered list of complex numbers in the gate matrix). For example, the square root of not gate acting on a single bit circuit with an initial value of 0 would be (1, 0, [ ( [0], [ 0.707, -0.707, 0.707, 0.707 ] ) ] ).
I then made a set of Haskell libraries for HUGS to output this raw data. There are two Haskell files - gates.hs defines the gates used in a circuit, while circuit.hs defines the circuits. The square root of not gate, for instance, requires the following code in gates.hs.
type Gate = ([Int], [Complex Double])
oneOverRootTwo :: Complex Double
oneOverRootTwo = 2**(-0.5) :+ 0
--------------------------------------------------------------------------
-- Matrices
sqrtNotMatrix ::[ Complex Double ]
sqrtNotMatrix = [ oneOverRootTwo, -oneOverRootTwo, oneOverRootTwo, oneOverRootTwo ]
--------------------------------------------------------------------------
-- sqrtGate n, where n is the bit for the gate to act on
sqrtGate :: Int -> Gate
sqrtGate n = ([n], sqrtNotMatrix)
We can easily extend this code to allow circuits made up of square root of not gates. For instance by using the following code.
-- sqrtGates [n]. Constructs a column of sqrtNot gates, where
-- [n] gives the bits to act on
sqrtGates :: [Int] -> [Gate]
sqrtGates [] = []
sqrtGates (b:bs) = (sqrtGate b) : sqrtGates bs
And in circuit.hs we have the following code.
type Circuit = ( Int, Int, [Gate] )
-- test circuit
notTestCircuit :: Int -> Int -> Circuit
notTestCircuit (n+1) i = (n+1, i, (sqrtGates [0..n]) ++ (sqrtGates [0..n]) )
A 10-bit circuit to invert the number 53, for example, would be created by typing in the command notTestCircuit 10 53. We could simulate this circuit opening the file circuit.hs from within the simulator. After this, the user would select the option 'Start Simulation'. This, in turn, causes the simulator to ask the user for the Haskell command to execute. HUGS is then invoked, the command is piped in to it and its output is captured. The parser within the simulation then reads and parses the HUGS output and creates a circuit from the description.
| Prev: The ‘Simple’ Simulation Algorithm | Up: Contents | Next: Optimised Algorithms |
This web page (c) 2000 Jon Marshall. Last updated 3rd June 2000