A hybrid quantum computer and a method of processing code on a hybrid quantum computer
The described method optimizes hybrid quantum-classical systems by dynamically processing code using symbolic execution and deferring quantum operations until necessary, addressing the coherence time limitations of qubits to enhance performance.
Patent Information
- Application Number
- GB2024002780
- Authority / Receiving Office
- GB · GB
- Patent Type
- Applications
- Current Assignee / Owner
- Filing Date
- 2024-02-27
- Publication Date
- 2025-09-10
AI Technical Summary
Hybrid quantum computers face challenges due to the short coherence time of qubits, requiring efficient optimization of tasks between classical and quantum processing units to maximize performance.
A method for processing code in a hybrid quantum computer using a runtime system that dynamically processes and optimizes classical-quantum instructions through symbolic execution, deferring quantum circuit execution until the result is needed, and selectively folding or concretizing operations based on coherence time constraints.
Enhances computer performance by optimizing quantum processor usage, ensuring efficient execution of quantum operations within coherence limits, thereby improving the overall processing efficiency of hybrid quantum-classical systems.
Smart Images

Figure 00000000_0000_ABST
Abstract
Description
FIELD Embodiments described herein relate to a hybrid quantum computer and a method for processing code in a hybrid quantum computer and a module for processing code in a hybrid quantum computer. BACKGROUND A hybrid quantum computer will comprise a quantum processing unit and at least one type of classical processing using, for example standard CPU, GPU or FPGA. Hybrid quantum computing requires a subdivision of the tasks to be run on each of the different types of processors. Quantum operations are performed using qubits in a quantum processing unit (QPU). Processing using qubits provides many advantages, but processing using qubits provide unique challenges. Their short coherence time means that the time for running operations using qubits is short. Preparing tasks for running on a QPU needs to take into account the challenges of a QPU. BRIEF DESCRIPTION OF FIGURES FIG. 1 is a schematic of the application layers of a hybrid quantum computer; FIG. 2 is a schematic of a flow diagram for a method of processing code in accordance with an embodiment; FIG. 3 is a flow diagram showing some of the steps of the diagram of FIG. 2 in more detail; FIG. 4 is a schematic of a quantum circuit; FIG. 5 is a schematic of a graph; and FIGs. 6A and 6B is a trace showing the processing of the graph of FIG. 5. DETAILED DESCRIPTION OF FIGURES In a first embodiment, a method for processing code for a hybrid quantum computer is provided, the hybrid quantum computer comprising a quantum processor and a classical processor, the method comprising: receiving code to be executed on the hybrid computer; processing said code using the classical processor to extract a data structure, the data structure comprising quantum and classical instructions; processing said data structure using symbolic execution; determining the presence of an instruction in the data structure to perform a quantum operation; preparing a quantum circuit corresponding to the quantum operation; continuing to process the data structure using symbolic execution to identify an instance of the use of the result of the quantum operation; and running the quantum circuit on the quantum processor, such that the running of the quantum circuit is deferred until at least one further instance of the use of the result of the quantum operation has been determined. The disclosed system and method provides an improvement to computer functionality by allowing computer performance of a function not previously performed by a computer. Specifically, the disclosed system provides for optimisation of instructions that are provided to a quantum processor in a hybrid quantum computer. This is achieved by providing a runtime that dynamically processes the code and looks to optimise the code that is sent to a quantum processing unit (QPU). The runtime consumes hybrid code and then is responsible for optimising, then executing, both classical and quantum sections before returning a result In an embodiment, the runtime is a quantum intermediate representation (QIR) hybrid runtime which is capable of running arbitrarily interwoven classical-quantum code against a local or remote QPU. In an embodiment, continuing to process the data structure comprises performing symbolic execution of the data structure with the result of the quantum operation being represented as a variable. In an embodiment, the method further comprises selecting at least one of when a further instance of the used of the quantum operation has been determined: running the quantum circuit on the quantum processing unit to concretize the result; enlarging the quantum circuit to incorporate instructions defining the use of the at least one further instance of the result of the quantum operation, wherein the selecting is performed when at least one further instance of the use of the result of the quantum operation has been determined. Thus, the quantum circuit (projection) is deferred until a further instance of the use of the result of the quantum operation is determined by the runtime. At this stage, a decision is made between concretizing the result of the quantum operation or attempting to enlarge the quantum circuit to incorporate the instructions relating to the use of the result of the current quantum circuit This is referred to as "folding” the instructions into the quantum circuit The above decision of whether to concretize the result or enlarge the quantum circuit further may be made as part of a two stage decision process. Stage 1 - determines whether the instructions defining the use of the at least one further instance of the result of the quantum operation are capable of being folded into the quantum circuit. Stage 2 - determines whether the enlarged circuit will be too big. In stage 1, the runtime determines if it is possible for the instructions relating the use of the at least one further instance of the result of the quantum operation, hereinafter referred to as the "later instructions", can be folded into the circuit For example, do the instructions relate to something which can be added to the current quantum circuit - whether it is possible to fold the latest instructions into the quantum circuit without interfering with the function or performance of the existing quantum circuit. Due to the complex nature of quantum operations and specifically entanglement, care must be taken when enlarging the circuit Where the new instructions can just be added to the end of the quantum circuit, this can often be done without adversely affecting the original quantum circuit. If the instructions can be added, then a second stage is performed to see if the enlarged circuit could be efficiently run on the quantum processor. The qubits of a quantum processor will have a coherence time which is a physical property of the qubits. The number of gates (sometimes referred to as the size) of a quantum circuit will define the time that the processing will take on a QPU. If this time extends to the coherence time or close to the coherence time, then the coherence of the qubits will start to fail, this will result in a degradation of the performance of the QPU when it runs the quantum circuit Therefore, if the enlarged circuit will have too many gates, the runtime will concretize the result as opposed to enlarging the circuit. Each quantum processing unit will have its own coherence time which can be converted into the size of the quantum circuit that it can efficiently run. Also, not all gates will take the same length of time to run, for example, a CX gate will take longer to run than a rotation. However, typically, quantum circuit sizes of up to 1000 gates can be supported with current quantum processing units. Thus, in an embodiment, the quantum processing unit has a threshold size for quantum circuit and wherein the selecting determines not to enlarge the quantum circuit if the enlarged quantum circuit would exceed the threshold. In an embodiment, the threshold is related to the coherence time of qubits within the quantum processing unit The size of the quantum circuit may be determined from the number of gates of the quantum circuit In summary, the first stage answers the question "is it possible” and the second stage "is it advisable”. In an embodiment, as the data structure is processed using symbolic execution, the method further comprises, each time a further instance of the use of the result of the quantum operation has been determined, selecting at least one of: running the quantum circuit on the quantum processing unit to concretize the result; or enlarging the quantum circuit to incorporate the instructions to incorporate instructions defining the use of the at least one further instance of the result of the quantum operation. Thus, the runtime continually processes the data structure and each time it encounters an instance of the result of the quantum operation, it will decide between concretizing the result or enlarging the circuit This means that the quantum circuit may be enlarged a plurality of times before it is run on the quantum processor. Once the result is concretized, it can be used in the symbolic execution of the data structure. Thus there is a dynamic processing of the data structure by the runtime which determines the results from the quantum processor to be used in the symbolic execution. In an embodiment, code to be processed may comprise a conditional statement, the conditional statement comprising a condition and expressions to be executed dependent on the outcome of the condition, if the condition requires a quantum measurement this result can be concretized and used as a constant in the symbolic execution. However, in some cases, the entire conditional statement can be lowered into the QPU. For example, if the condition and the expressions to be executed dependent on the outcome of the condition are quantum operations then the entire conditional statement can be folded into a quantum circuit and eventually lowered into the QPU. However, even if the instructions can be folded into the quantum circuit, the size of the enlarged circuit will be checked to see if it should be run on the QPU. When the code comprises a loop, all, or a plurality of iterations of the loop can be lowered into the quantum circuit. Even if there is not a need to concretize a result, the quantum circuit may be run. For example, if the quantum circuit is enlarged, but the enlarged form is not suitable for the quantum processing unit, e.g. would take too long to run, requires too many qubits etc, the form of the quantum circuit prior to enlargement might be run. In an embodiment, the data structure is a graph. Processing code to extract a data structure may comprise processing code in the form of an intermediate representation. The intermediate representation may be QIR which is derived from LLVM. In an embodiment, the graph is produced so that it avoids non-determinism, for example operations requiring access calls outside the runtime environment of the graph. In an embodiment, OS / system calls and disk I / O are removed from the graph. This may be achieved by embedding arguments as constants and using stubbing. In the embodiments described herein, symbolic execution and dynamic interpretation of quantum-classical hybrid code is used to power optimization and execution. The use of symbolic execution allows the runtime to perform heavy execution deferral, dynamic lowering of stretches of instructions into the FPGA and fully constant parameterized circuit synthesis. In an embodiment, the quantum operations are selected from at least one of:measurements, gates and reset operations. The gates may comprise qubit rotations about the X, Y and Z axis, CNOT, CX, Hadamard, phase andToffoli. In an embodiment, optimisations are focussed on at least one of the following: 1. Dynamically analysing classical branching logic, such as if statements and loops, then lowering them into FPGA instructions to run directly on the QPU. 2. Restricting analysis to purely in-memory manipulations and no system calls. This optimisation allows a full view of the state of a program so all values are effectively constant 3. Being able to perform complex hoisting / lowering operations because the runtime has a full view of the entire code of the algorithm being run as opposed to a view of just fragments of quantum or classical code. In the embodiments described herein symbolic execution / analysis is used to analyse the code in a dynamic manner. In symbolic execution / analysis, code is processed, usually in intermediate representation (IR) form, and it is run line-by-line using another program to work out the global and local state of variables at each point in the program. This is then used for any number of optimizations, transformations or just straight-up execution of the program. In an embodiment, symbolic execution is performed in a runtime environment In an embodiment, the runtime uses the variable state information gathered while stepping through the code to: help improve the circuit to be run on a QPU using surrounding contextual information; making circuits entirely constant even if the arguments are variable; and heavily deferring QPU execution until the actual result of the value is used in a non-quantum context. In a further embodiment, a hybrid quantum computer is provided comprising: a quantum processor; and a classical processor, wherein the hybrid quantum computer is configured to support a first compiler and a runtime, the first compiler being configured to process code to extract a data structure, the data structure comprising quantum and classical instructions; the runtime being configured to: process said data structure using symbolic execution; determine the presence of an instruction in the data structure to perform a quantum operation; prepare a quantum circuit corresponding to the quantum operation; continue to process the data structure using symbolic execution to identify an instance of the use of the result of the quantum operation; and run the quantum circuit on the quantum processor, such that the running of the quantum circuit is deferred until at least one further instance of the use of the result of the quantum operation has been determined. The quantum processing unit comprises qubits which may be selected from at least one of: superconducting qubits, trapped ion qubits and photonic qubits. FIG. 1 is a schematic of the application layers in a hybrid quantum computer 1. In FIG. 1, two high level application layers are provided: first high level application level 3 which is configured to process high level code received via a quantum plug in, for example from Python, Julia; C++, JSON, JavaScript etc.; and second high level application level 5 which is configured to process code from a high end quantum computing language such as Q#, QASM etc. In some embodiments, a single high level application level is provided, in other embodiments more than two high level application levels are provided. The number and type of the high level application layers can be adapted to the type of code which will be handled by the quantum computer. The ability to provide multiple high level application layers allows the system to be adapted for any type of input code. A high-level compiler / runtime layer 7 is then provided to receive code from the high level application levels 3 and 5 and covert the code into an intermediate representation language such as QIR. The code is then parsed by layer 7 to form an abstract syntax tree. A runtime system (or environment) 9 is provided which is also present which provides an additional environment in which a program runs. A runtime system may control a number of issues such as management of application memory, how the program accesses variables, mechanisms for passing parameters between procedures interfacing with the operating system etc. In this embodiment, the runtime 9 provides extra functionality around high level compiler / runtime layer 7. The runtime 9 sits above the processing layers of a GPU 11, HPC / CPU 13 and a QPU 17. The runtime 9 servers to optimise the code which is passed to the QPU 17. How it achieves this will be described with reference to FIGs. 2 and 3. Gate pulse level compiler layer 15 sits between the QPU 17 and the runtime 9, the function of the gate pulse level compiler layer is to convert low level code into a form which can be used to address and manipulate qubits, e.g. pulse generation and shaping. A second quantum compiler / runtime Gate pulse level runtime 19 may also be provided as two layers of quantum compiler / runtime may be used with some quantum processing units. The output of the runtime 9 is processor agnostic and so one or more levels of compiler / runtime may be used dependent on the architecture of the QPU. The output of the runtime 9 will be in an abstract or intermediate form. FIG. 2 is a simplified flow diagram showing a method in accordance with an embodiment In step S101, code is received. This is high level code in a programming language of the type written by a human programmer. The process can be used with any high level code such as C, python, etc. The high level code is then converted into an intermediate representation such QiR (quantum intermediate representation) in S102. QIR is a subset of LLVM (low-level virtual machine) IR which adds in gate-level quantum operations and specific metadata like requested result formats, qubit count and the hardware capabilities required for execution. LLVM is a compilation toolchain and its IR is good at representing abstract classical instructions in a way that can then be targeted at numerous different backend architectures. The IR itself focuses purely on pointers, with no mention of registers or memory come into it beyond requests to store and load specific types. This allows many types of target architectures to be supported because no assumption is made on how the hardware itself should deal with memory or processing. However, in an embodiment, LLVM is mainly used for its IR and parsing capabilities. As described herein symbolic execution may be used to dynamically process QIR and therefore the registers provided by LLVM are not relevant since symbolic execution is concerned with the state of variables at each point Also, purely classical optimizations across arbitrarily interwoven classical / quantum code cannot be applied due to the subtle relations between quantum and classical code that need to be dealt with by more specific compilation. The method that will be described with reference to FIGs. 2 and 3 means that it is not necessary to use LLVMs built-in interpreter, symbolic analysis or IR linking and execution. This is because, in an embodiment, knowledge of the branching syntax is used and what triggered it and this information may be lost using some of the above functionality of LLVM. In step SI 03, the QIR is parsed and the parsed QIR is walked through to build a logic graph. After parsing a logic graph is produced which, in an embodiment, is a directed acyclic graph (DAG) that’s intent is a mixture of control-flow graph (CFG) and abstract syntax tree (AST). The graph encodes branching and jumps in the edges of the graph and its nodes are the expressions to be run, both classical and quantum. However, in an embodiment, the graph has a constraint: all values that are used in, or are the result of, expressions have to be generated during runtime or passed in as arguments. If there are any system calls or I / O operations they need to be resolved before building the graph, not during runtime. The only operations that do not need to follow this rule are the expressions that demand running something on specialist hardware such as QPUI GPUs. In further embodiments, some system operations may be allowed such as obtaining the current time. The more nondeterministic steps that are present in the graph, the harder the graph is to optimise and hence it is harder to optimise the calculation represented by the graph. The logic graph is viewed as a fragment of a pre-existing programing that is meant to be wholly runnable on, or near, a quantum computer. It is not necessary to process the whole program in this way, it is possible to take just fragments. What is contained in a full graph can have some impact on optimization of the hybrid code. Optimisation of the code can be achieved by examples such as: conditionals that can be lowered into the hardware; expressions that produce rotation angles; unrollable loops; or any values that can trigger these. All of this is reinforced by the nodes themselves and what they may to represent. In an embodiment, nodes may be used to represent one or more of the following: Assignments. Arithmetic and bitwise operations. A call to another graph. Equality comparisons. Quantum-related operations. Labels. Returns. Logging. Throws. It should be noted that branches, jumps and control-flow logic are not mentioned here. This is because such information is embedded into the edges of the graphs themselves. A node can only have multiple outward edges if one or more outward edges have conditions applied to them. That edge will then only be taken if its expression is satisfied. To help with scoping variables, edges can also have what’s known as an ‘edge assignment’ which means when that edge is taken a variety of assignment expressions will be applied atthe same time. Considering briefly the values that inhabit the graph and flow through it: a value is an object that represents traditional programming primitives, strings, arrays, qubits or references to other values. While these are the only ones that exist in the graph before it is executed, additional values are used during runtime for deference and external hardware execution. Once the graph has been produced in step S103, it is processed in step S105 using the runtime environment. Each graph has a designated entry-point which it was loaded with. The processing of the graph starts from this entry point and with the arguments supplied as its initial values. Symbolic execution is then performed. In symbolic execution, each input or argument is represented by a variable and these variable are flowed through the code to see how the code operates. During symbolic execution, the code is just taken as its written and run. In step SI05, the code is run using symbolic execution by stepping through the nodes in the runtime. Here a node is processed and any global / local state changes in its context are stored. Next, an edge from the node is traversed and the next node is processed. While the runtime is stepping through the nodes it is also performs contextual analysis. In summary, the graph is dynamically optimising and modifying itself as it runs to efficiently transfer calculations to the QPU. When processing the graph, a quantum circuit is generated in step S107. This circuit may be modified and updated depending on the processing performed by the runtime. When appropriate, the quantum circuit is lowered into the quantum processor to produce or concretize a quantum result in step S109. This result, may, depending on the processing of the graph in S105 be fed back to the processing in step S105. In an embodiment, once the runtime identifies a result which requires use of the QPU to obtain the result, a projection or quantum circuit is produced in step S107. This will be termed the "first quantum circuit”. However, this first quantum circuit is not lowered into (or run on) the QPU. This step is deferred until the runtime performs further processing of the graph in SI 05. When the use of the result of the first quantum circuit is encountered by the runtime at a further expression, the runtime determines whether it is possible to expand the first quantum circuit by folding in this further expression or whether the first quantum circuit needs to be lowered in step SI 09. The result of the first quantum circuit then being concretised and fed back for use in the processing of the graph in step S105. The flow chart of FIG. 3 goes through steps S105, S107 and S109 of FIG. 2 in more detail and with some examples. In step S201, the graph is stepped through by the runtime using symbolic execution, and in this example, a quantum measurement (or operation) is encountered at step S203. When a quantum operation is reached the runtime attempts to optimise the instructions to be sent to the QPU. Quantum related operations may comprise at least one of the following Initialise, to set the initial state of the QPU run. Activate / deactivate qubit. Marks when a qubit comes into and falls out of scope. Gate. All common gates that allow for universal quantum computation: X, Y, Z, CX, (where X, Y, Z, relate to qubit rotations about the X, Y and Z axis) etc. Reset Marks when a qubit has been reset The last two "Gate" and "reset” are quantum operations as they represent manipulations performed on qubits. However, the first two in the above list "initialise” and "activate” are performed as preparation for a quantum operation and can be viewed as quantum metadata and would not form part of a quantum circuit. When a quantum operation is identified, the runtime creates a quantum projections step S205 that starts to record all further quantum operations that it processes. The quantum projection may also be referred to as a quantum circuit which represents the operations that can be run on a QPU. FIG. 4 shows an example of a quantum circuit. When it is required to run the quantum circuit it is "lowered” into the QPU. However, the quantum circuit is not run atthis stage and is deferred in step S207. By deferring, a quantum promise is created where the output of the quantum circuit is represented by a variable in the following symbolic execution by the runtime. In step S209, the runtime continues to process the graph using symbolic execution. In step S211, the runtime reaches an instruction which requires the use of the quantum promise. At this stage, the runtime determines how this next instruction should be handled to optimise use of the QPU. For example, is necessary to concretise the quantum promise or can the next instruction be folded into the quantum circuit? To understand the decisions that can be made, a number of examples will now be worked through. Example 1 The above code sets a variable qlresult which is obtained my measuring a first qubit ql. If ql == 1, then a rotation of a second qubit (q2) is performed about the x axis (x q2) and the y axis (y q2). The above contains a quantum instruction to measure the first qubit. This can be moved to a quantum projection, but not lowered into the QPU. Next, a conditional statement is provided. However, in this case the operations within the condition are purely quantum and the condition is also only reliant upon a measure result. Thus, the above block is purely quantum with no traditional classical operations. Thus the above block of code can be lowered into a QPU together. Thus, each of the above operations can be provided in the same quantum circuit Lowering of the produced quantum circuit can be deferred until the result of the above code is required. At this stage, a decision can be made as to whether to enlarge the quantum circuit. Example 2 In this example, there is more classical code interweaved with the quantum instructions: 11 This is an argument passed in from outside the code block. It's value is unknown / / . arg =... qlresult = measure ql; if qlresult == 1 { rxpi / 2 *argq2; ry pi / 4 * arg q2; In the above, the argument "arg" is nondeterministic. Its value is unknown until it is received and its value will vary between runs. It may even be a result computed earlier in the script via quantum code so is entirely unknowable until the code is run. In theory, it is possible to design a projection to lower all of the code into the QPU. However, the QPU is very inefficient for performing calculations that do not take advantage of the quantum nature of the QPU and wastes processing time of the QPU. The coherence time of the qubits in the QPU impacts the processing time of the QPU. Superconducting machines are fast, but have a low coherence time as a trade-off, so for them running long classical calculations drastically reduces the complexity of the quantum code that can be run with an expectation of a precise result Processing the graph aims to be able to selectively lower only the code that is absolutely necessary into the QPU. Symbolic execution helps with this problem as it allows analysis of blocks of logic that require complicated lowering rules as it is possible to look ahead at the incoming branches, as well as the surrounding state of the system, and make nuanced decisions that may be difficult or impossible to do via static analysis. Example 3 is related to Example 2 by replacing the nondeterministic argument of Example 2 with the result of another quantum call that itself takes in a nondeterministic value. Example 3 / 1 This is an argument passed in from outside the code block. / / it's value is unknown. qubit_count =... / / This calls a QPU to generate a random number. random_number = generate_random_number_quantumly(qubit_count) qlresult = measure ql; if qlresult == 1 { rx pi / 2 * random_number q2; ry pi / 4 * random_number q2; In the above code, rx and ry define a rotation about the x and y axis by the amount specified after rx, ry. Example 3 is incredibly difficult, if not impossible, to try and solve statically. It is possible to try to attempt to simulate the QRNG method to help, but as the algorithm uses more qubits it will reach the point where it's unviable to simulate. At that point all attempts to solve it break down. However, using symbolic execution, it is possible to just run the QRNG function directly and use the value as a constant to embed in our rotations as the system executes. Thus, for example, if the quantum randomness generator returns a 5. The code simplifies away to: qlresult = measure ql; if qlresult == 1 { rx 24.6740... q2; ry 3.92699... q2; ........................................................} This means that it is possible to lower the above code directly into the QPU and so this can be folded in the quantum circuit. Thus, in step S213 of FIG. 3, the method would progress toS217. Example 4 This example relates to fully constant code. Here, there is no variance in how the method runs, and thus, it is possible to be entirely optimised to return just its result. ratio = 5*1.52 result = (7 \ 242) * ratio The above will always return 0.219834710(.,.). In the processing of purely classical code, a traditional compiler would just embed the result in all places that called it and the method itself would vanish from the compiled code. However, this cannot be easily done with quantum code, as simulating it with any precision is incredibly difficult past a certain point This means that any value returned from a quantum computer is unknowable at compilation time and anything that value interacts with is equally unknowable. This nondeterminism means that an optimizer's view of the world is incomplete and thus it can’t perform its job effectively. With hybrid algorithms, quantum computers need to be able to run more classical concepts directly on the machine. Thus, increasingly complicated algorithms will require hybrid optimization techniques. Techniques which will process both the quantum algorithm as well as its surrounding classical code and optimising both parts at the same time. In Example 2, there was a discussion of being able to contextually simplify and lower classical logic into a quantum computer. Such optimization techniques perform best when they have full knowledge of both the classical and quantum state at any point in a program. However, as explained above it is incredibly difficult to perform this using a static approach. The embodiments described herein use symbolic execution to perform optimisation. As noted above, nondeterminism negatively impacts optimisation. Therefore, in an embodiment some points of non-determinism are removed from the code. There are many points of nondeterminism in code, for example, OS / system calls and disk I / O being some of the most prominent Thus, in an embodiment, these are removed. For example: arguments are embedded to become constants; and system calls and disk reads are ignored, stubbed if possible, or rejected. When system calls and disk reads are stubbed, they are replaced with a something that constrains the read or system call. For example, a call to a file may be stubbed by a string of a certain length, or a value within a range if the range known. Thus, in an embodiment, as symbolic execution and analysis is run, every value at every point will be known, except for a result of a quantum execution. However, as the code is being executed as well as compiled, these results can be obtained. As explained herein, a quantum circuit is built up to define the operations to be run on a quantum computer. When it is necessary to concretize a quantum result, this result is then inserted as a constant directly back into the symbolic execution. This means that there are no holes at all from an analysis standpoint. Both classical and quantum results are ‘constant’ in the eyes of the system. This is incredibly powerful when considering optimizations because it is possible to dynamically optimise code as it is executed. In some cases, this dramatically simplifies the code. Example 5 args = [...] random_quantum_number = qrng(arg[0]) if random_quantum_number >500 { Xarg[l] } else { / / CNOT across every qubit available. When the above is processed via, symbolic execution, the first function is a quantum random number generator. This is likely to be a large quantum circuit and therefore, it will be run on a QPU on its own. Once this result is concretized, it is used by the symbolic execution. Inserting the value into the if statement allows one of the branches to be entirely cut off. Thus, dependent on the result of the quantum random number generator, the dynamic processing of the data structure using symbolic execution is simplified. Dependent on what is in the IF statement, it may be possible to avoid performing a quantum operation in the IF statement. This also allows us to run sub-executions of a circuit to simplify an outer one, perform circuit splicing using contextual clues of the surrounding code, or a whole range of experimental approaches to simplify the overall complexity of a quantum circuit by using dynamic hybrid optimizations. The ability to fully represent both classical and quantum sides of an algorithm in a unified form allows for some interesting transformations and optimizations even when static compilation is being performed. Example 6 for 20 iterations: / / ... perform various gates to do something, result = measure ql-q20; The above example has a flat loop that runs quantum operations 20 times with no values escaping the loop, early returns or complicated syntax. The above code also implies that the measure is the final block of this execution, as nothing else happens after it Since the body of the loop is entirely quantum and there are 20 iterations the above examples is a target for some form of optimization. In one embodiment, it is possible to lower the loop directly into the QPU to drastically speed up the execution loop. In other embodiments, loops are batched together to run across multiple machines. None of these are mutually exclusive, but each one is faster than attempting to send through 20 individual requests to a QPU. Example 7 result = list() II Generate 20 random numbers via the QPU, then generate some random seed / / values, for 20 iterations: random_number = quantum_rng() first_seed = generate_quantum_seed(random_number); second_seed = (first_seed * random_number) + 42; final_seed = generate_quantum_seed(second_seed); resultadd(final_seed); The above can be broken down as follows: 1. There are 20 iterations of a loop that contains: multiple quantum sub-calls; classical arithmetic; and a result that leaks outside of its scope. 2. There are three quantum calls ("quantum_rng” and two calls "generate_quantum_seed”) and it is difficult to reliably reason using these results prior to their calculation. 3. There is a combination of two separate quantum results and then the addition of a flat number to generate the second_seed. The second_seed it then used as an argument in the generation of the final_seed. 4. The final_seed is added to a results list which is outside the loop. While some of the above can be dealt with statically, there are some unique opportunities which can be exploited due to the use symbolic execution to allow deferring quantum results. When a circuit is considered finished in the code and there is a variable that holds the quantum measure result from a quantum circuit (first quantum circuit), the quantum circuit has not yet been run on a QPU. In an embodiment, whenever, when the code is stepped through, an expression is performed on a deferred result, there is an attempt to calculate whether that expression can be built into the first current quantum circuit. If not, then the first quantum circuit is lowered into the QPU and a result is obtained. However, if the expression can be folded into the first quantum circuit, the first quantum circuit is enlarged with the expression and the enlarged quantum circuit (second quantum circuit) is still deferred. Applying this methodology to Example 6 random_number = quantum_rng() first_seed = generate_quantum_seed(random_number); second_seed = (first_seed * random_number) + 42; Taking the target as the above third line, the argument "random_number” has already been used as an argument to generate the first seed. Therefore, it is assumed that that this result has been embedded into whatever circuit has been built and the result is considered to be a constant value. The argument, first_seed has just been returned so is currently deferred. The expression it’s currently being used in is composed of a literal and an already-returned quantum execution, both considered constants by the symbolic executor. Therefore, the runtime will attempt to fold them into the deferred circuit built from generate_quantum_seed. In this example, it will be assumed that the QPU is both perfect and infinite in size and thus there will be no discussion of qubit usage and length. However, if this was attempted on a real machine it would be necessary to evaluate whether the newly generated circuit could fit current hardware or whether the newly generated circuit would fail either fully or in part In an embodiment, quantum adders and multipliers are folded into the quantum circuit as required. Again, if there are situations where this can’t be done accurately the folding will simply fail and the code will be run "as is”. random_number = quantum_rng() first_seed = generate_quantum_seed(random_number); / / Both of these calls are added to the deferred circuit, so running on the QPU is still deferred first_seed. multiply _by(random_number); first_seed.add(42); The above entire fragment is now fully quantum as the classical sections have been folded into the deferred circuit However, there is one further optimisation. As the argument “random_number" is being used in a purely quantum fashion it is not necessary to treat the value as classical. The results of one quantum execution are only used directly in another. This means that it is possible to attempt to fold the two circuits into one another, eliminating an entire run on the QPU. The folding may still fail for multiple reasons, including the fact that the system simply deems it not a worthwhile optimization. As explained above, the size of a quantum circuit is constrained by the QPU on which it is to run, if the quantum circuit is too big, the time it takes to run will mean that decoherence of the qubits will start to impact the results produced by the QPU. Therefore, when folding in further instructions to the quantum circuit, a check is made to ensure that the quantum circuit does not become too big to run. If the optimisation proceeds, the example fragment becomes: first_seed = generate_random_quantum_seed(); first_seed.add(42); This can then be folded into the quantum circuit once more just by moving the addition directly into the quantum method, turning it into a single line. The full example now looks like this: result = list() II Generate 20 random numbers via our QPU, then generate some random seed / / values, for 20 iterations: final_seed = generate_random_quantum_seed(); resultadd(final_seed); It may also be possible to fold both the loop and list creation into the quantum method. However, again a check is made to ensure that the quantum circuit does not become too big to run. The further instructions are not folded into the quantum circuit if the quantum circuit would become too big. The above example has shown that when dealing with complicated mixed-context code a symbolic execution approach with heavy result deference can enable some interesting optimisation methods. Instead, when a measure operation is recorded, instead of executing against a QPU and returning a concrete result, the projection will return a quantum promise instead. This promise defers running of the projection on the QPU until it is absolutely necessary. This has multiple benefits: as it allows quantum folding to be performed, as described in the previous section; being able to properly scope a quantum execution, since it may define multiple measures before it should actually be executed; allowing more precise optimization because it will be known how the results are actually used and what other values may flow into it. When a promise can be deferred no longer it optimises and transforms all the operations in the projection and runs it against an available QPU in step S107 which has the right characteristics and qubits available. When the result comes back the projection caches it and then returns a quantum result, which is a view over the projection's values for specific qubits. As multiple promises may be linked to a particular projection this means that when one promise has to execute it also concretizes the results for the others as well. Example 8 This example is used to accompany the quantum circuit of FIG. 4 arg =... ql = QubitQ; q2 = QubitQ; q3 = QubitQ; q4 = QubitQ; h ql; CNOTql, q2; qlresult = measure ql; q2result = measure q2; if qlresult == q2result { rxpi / 2 * argq3; ry pi / 4 * arg q4;} q3result = measure q3; q4result = measure q4; final_result = 57 * (q3result + q4result) The relationship between the code, its operation and FIG. 4 is detailed below: arg =... This is an argument passed in from outside the code block. Its value is unknown. In FIG.4, arg = 2. Ql = QubitQ; Q2 = QubitQ; Q3 = QubitQ; Q4 = QubitQ; The above lines of code initializing the qubits for the algorithm. Once a qubit has been allocated, quantum code related to the qubit is expected to arrive in the next few lines of code. A projection (quantum circuit) is then opened and for each of the current active 4 qubits shown on FIG. 4 hql; Ahadamard 401 is added on qubit 1 to the projection. The projection is not run at this stage. CNOTql, q2; A CNOT is then provided between qubit 1 and 2 to the projection. The projection is still not run at this stage qlresult = measure ql; A measure is added to the projection, which returns a deferred quantum result targeting qubit 1 and storing in qlresult argument. The lowering of the quantum circuit into the QPU is still deferred. q2result = measure q2; This is exactly the same as the previous line, but relates to qubit 2 and storing in q2result argument. if qlresult == q2result { rxpi / 2 * argq3; ry pi / 4 * arg q4;} When processed by the runtime, the expression (in this case an "if statement”) is analysed to see if this is an expression that can be lowered into our QPU directly. An "If statement” can, in theory, be lowered. Next, the expressions and the context surrounding the "If statement” are analysed using symbolic execution. As noted above, in FIG. 4 arg=2. For example, the following conditions are checked: (i) Are both arguments to the "IF" able to be lowered - i.e. qlresult and q2result These are both deferred quantum results from the same quantum execution, so while complicated, they can both be lowered (ii) Is the body of the "IF”able to be lowered? Within the “IF" there are 2 qubit rotations Rx Pi 407 and RY Pi / 2 409. These both have arguments that can be propagated during symbolic execution. These qubit rotations are quantum operations and are also capable of being lowered. If any part of (i) or (ii) fail, symbolic execution can be performed as normal. This means that qlresult and q2result would be concretized and the deferred quantum circuit executed. However, in this example, since (i) and (ii) are determined to be able to be folded into the quantum circuit / projection, they are folded into the QPU. This means that all of the above lines of code are folded into the quantum projection / circuit It is presumed that the size of the circuit (as enlarged) is still small enough to run on the QPU. The lines of code: qlresult = measure ql; q2result = measure q2; if qlresult == q2result { are all represented by box 405 in FIG. 4. The ability to develop and construct the entire circuit which allows the running of all lines on code on a QPU provides an efficient and optimised way to execute the above code. if qlresult == q2result { rxpi / 2 * argq3; ry pi / 4 * argq4; The above lines of code are exactly the same as measuring ql / q2 and have been folded into the quantum circuit. q3result = measure q3; q4result = measure q4; While the above code can be (technically) folded this multiplication into the circuit, it would have little advantage. Thus, in this example, the runtime recognizes that this is the end of the line, concretizes itself fully, and then the results of q3 result and q4result are concretized and used to determine. final_result = 57 * (q3result + q4result) The processing of the code continues. However, as the projection of FIG. 4 has been fully consumed it automatically closes. The next time that qubits are encountered in the code, a new quantum circuit will be created. As the above quantum circuit has been created, it is possible for itto be saved and run again on the QPU. It would be expected to function exactly the same. FIG. 5 is a schematic of an example of a graph which could be stepped through by the runtime. The entry point for the graph is at step S501. Processing of the graph starts at S503. The graph is initialised and variable arrays are setup as required. In this example, there are variables %arg (which is Boolean) and %9. At step S505, a variable %f is assigned to a qubit and the qubit is activated in S505. S505 is the start of an if statement which is shown on branch S507 which is taken if %arg==TRUE. When this condition is satisfied, the method proceeds to step S509 X[%f] Pi which instructs the qubit (assigned to %f) to be rotated by Pi radians about the X axis, the method then progresses to step S511 where a measurement is performed on the qubit %f to obtain variable %9 (%9=Measure(%f)). If %arg==FALSE then the method moves directly to step S511 without rotating the qubit. However, as the graph is processed using symbolic execution, the if statement has already been resolved and the FALSE branch is not traversed. The step S509 of rotating the qubit and the measurement of the qubit at step S511 is deferred and a quantum circuit (or projection) is built to represent these instructions in a form that can be lowered into a quantum processor. However, the lowering of the quantum circuit is deferred. The runtime then moves to step S513 where %result is set using %result = IsResult0ne(%9). The function IsResultOne returns TRUE if %9 is one and FALSE if %9 is notone. The function IsResultOne is split into steps S515, S517, S519 and S521. At step S515, functions to initialise the graph are performed such as reading in variables and setting up variable arrays for the variables %input which is a quantum result. In step S517, %l=%input==l, %1 is set to the result of "%input==l” which returns TRUE if the quantum result (%input) is 1 and FALSE if the quantum result (%input) is not one 1. S519 returns the results of S517 and the graph (IsResultOne) ends at S521 with its results returned to S513. After S513, the runtime steps to S523 which deactivates the qubit %f and the graph ends at The graph corresponds to the following code: @EntryPoint() operation RunProgram(arg: Bool) : Unit { use f = QubitO; within { if arg {X(Q; } } apply { let result = IsResultOne(MResetZ(f)); II Do something with result. The runtime performs symbolic execution on the graph. FIGs 6A and 6B shows a trace of the runtime as it symbolically executes the graph of FIG. 5. The trace is a detailed output which shows the decisions and outputs as the runtime sequentially processes the graph of FIG. 5. The trace is an actual output of the runtime and therefore has a level beyond what is necessary to appreciate the concepts described here. However, there are some lines of the trace which aid explanation of some of the processes applied when processing the graph. The code in box 601 corresponds to S505 and S509 where the qubit is activated in S505 and then rotated in step S509. Due to the symbolic execution, the FALSE branch of the if statement has been cancelled. Box 603 of FIG. 6A refers to the measurement in S511 of FIG. 5 and, as described above, the quantum circuit which is produced for this is then deferred and not run on the QPU. Box 605 corresponds to the start of the process in step S513, here an "IsResultOne" function is called. This function requires the use of the output of the deferred quantum circuit At this stage, the deferred quantum circuit is run on the QPU as indicated in box 607 on FIG. 6B. The concretized result from this is then used to resolve the “IsResultOne” function and the qubit is deactivated. As can be seen from the above, the measure in S511 of the rotation of the qubit in S509 is deferred until the next instance of the use of the result in S513. In this specific example, there are no further instances of the use of the result of the measuring in S511 (after S513) and so the result is concretized at this stage. However, if S513 was followed by further instructions which use the measurement of S511, then these further instructions might be folded into the quantum circuit built to measure the result of S511. When further instructions are encountered which use the result of an earlier quantum operation, the runtime makes a decision whether to concretize the deferred result and use the concretized result to execute the quantum operation or to fold the further instructions into the quantum circuit The decision made by the runtime can be influenced by a number of factors. However, QPUs will usually only be able to efficiently process quantum circuits of a particular size. This size is governed by the coherence time of the qubits of the QPU. A larger quantum circuit will take longer to run and the error rate will increase if there is decoherence of qubits. Each QPU will have its own parameters for suitable circuit sizes that it can handle. The size of a quantum circuit is usually measured in terms of the number of gates. If there are too many gates, the circuit will take longer to run. Whilst certain embodiments have been described, these embodiments have been presented by way of example only, and are not intended to limit the scope of the inventions. Indeed, the novel devices, and methods described herein may be embodied in a variety of other forms; furthermore, various omissions, substitutions and changes in the form of the devices, methods and products described herein may be made without departing from the spirit of the inventions. The accompanying claims and their equivalents are intended to cover such forms or modifications as would fall within the scope and spirit of the inventions.
Claims
1. A method for processing code for a hybrid quantum computer, the hybrid quantum computer comprising a quantum processor and a classical processor, the method comprising:receiving code to be executed on the hybrid computer;processing said code using the classical processor to extract a data structure, the data structure comprising quantum and classical instructions;processing said data structure using symbolic execution;determining the presence of an instruction in the data structure to perform a quantum operation;preparing a quantum circuit corresponding to the quantum operation;continuing to process the data structure using symbolic execution to identify an instance of the use of the result of the quantum operation; andrunning the quantum circuit on the quantum processor, such that the running of the quantum circuit is deferred until at least one further instance of the use of the result of the quantum operation has been determined.
2. A method according to claim 1, wherein continuing to process the data structure comprises performing symbolic execution of the data structure with the result of the quantum operation being represented as a variable.
3. A method according to either of claims 1 or 2, further comprising selecting, when a further instance of the used of the quantum operation has been determined, at least one of: running the quantum circuit on the quantum processing unit to concretize the result; andenlarging the quantum circuit to incorporate instructions defining the use of the at least one further instance of the result of the quantum operation,wherein the selecting is performed when at least one further instance of the use of the result of the quantum operation has been determined.
4. A method according to claim 3, wherein selecting comprises determining whether the instructions defining the use of the at least one further instance of the result of the quantum operation are capable of being folded into the quantum circuit5. A method according to either of claims 3 or 4, wherein the quantum processing unit has a threshold size for quantum circuit and wherein the selecting determines not to enlarge the quantum circuit if the enlarged quantum circuit would exceed the threshold.
6. A method according to claim 5, wherein the threshold is related to the coherence time of qubits within the quantum processing unit7. A method according to either of claims 5 or 6, wherein the size of the quantum circuit is determined from the number of gates of the quantum circuit8. A method according to any of claims 3 to 7, wherein as the data structure is processed using symbolic execution, the method further comprises, each time a further instance of the use of the result of the quantum operation has been determined, selecting at least one of:running the quantum circuit on the quantum processing unit to concretize the result; orenlarging the quantum circuit to incorporate the instructions to incorporate instructions defining the use of the at least one further instance of the result of the quantum operation.
9. A method according to claim 8, wherein the quantum circuit is enlarged a plurality of times before it is run on the quantum processor.
10. A method according to any of claims 3 to 9, wherein the result is concretized, it is used in the symbolic execution of the data structure.
11. A method according to any preceding claim, wherein the code to be processed comprises a conditional statement, the conditional statement comprising a condition and expressions to be executed dependent on the outcome of the condition, and wherein processing said data structure comprises generating a quantum circuit comprising the conditional statement if the condition and the expressions to be executed dependent on the outcome of the condition are quantum.
12. A method according to any preceding claim, wherein the code to be processed comprises a conditional statement, the conditional statement comprising a condition andexpressions to be executed dependent on the outcome of the condition, the condition requiring a quantum measurement and wherein processing said data structure comprises running a quantum circuit to obtain the measurement and use this as a constant in the symbolic execution.
13. A method according to any preceding claim, wherein the code to be processed comprises a loop, and wherein processing said data structure comprises providing a plurality of iterations of the loop in the quantum circuit14. A method according to any preceding claim, wherein the data structure is a graph.
15. A method according to claim 14, wherein the graph is configured to avoid operations requiring access calls outside the runtime environment of the graph.
16. A method according to any preceding claim, wherein processing code to extract a data structure comprises processing code in the form of an intermediate representation.
17. A method according to any preceding claim, wherein quantum operations are selected from at least one of:measurements, gates and reset operations.
18. A method according to claim 17, wherein the gates comprise qubit rotations about the X, Y and Z axis, CNOT, CX, Hadamard, phase and Toffoli.
19. A hybrid quantum computer comprising:a quantum processor; anda classical processor,wherein the hybrid quantum computer is configured to support a first compiler and a runtime,the first compiler being configured to process code to extract a data structure, the data structure comprising quantum and classical instructions;the runtime being configured to:process said data structure using symbolic execution;determine the presence of an instruction in the data structure to perform a quantum operation;prepare a quantum circuit corresponding to the quantum operation;continue to process the data structure using symbolic execution to identify an instance of the use of the result of the quantum operation; andrun the quantum circuit on the quantum processor, such that the running of the5 quantum circuit is deferred until at least one further instance of the use of the result of thequantum operation has been determined.
20. A hybrid quantum computer according to claim 19, wherein quantum processing unit comprises qubits which are selected from at least one of: superconducting qubits, 10 trapped ion qubits and photonic qubits.
Citation Information
Patent Citations
Compilation of hybrid quantum computing programs
US20240028943A1
Quantum hybrid computation
WO2020018752A1