qutip_qip.compiler package¶
Submodules¶
qutip_qip.compiler.cavityqedcompiler module¶
-
class
qutip_qip.compiler.cavityqedcompiler.
CavityQEDCompiler
(num_qubits, params, global_phase=0.0, pulse_dict=None, N=None)[source]¶ Bases:
qutip_qip.compiler.gatecompiler.GateCompiler
Decompose a
QubitCircuit
into the pulse sequence for the processor.- Parameters
- num_qubits: int
The number of qubits in the system.
- params: dict
A Python dictionary contains the name and the value of the parameters. See
DispersiveCavityQED.set_up_params()
for the definition.- global_phase: float, optional
Record of the global phase change and will be returned.
- Attributes
- gate_compiler: dict
The Python dictionary in the form of {gate_name: decompose_function}. It saves the decomposition scheme for each gate.
qutip_qip.compiler.circuitqedcompiler module¶
-
class
qutip_qip.compiler.circuitqedcompiler.
SCQubitsCompiler
(num_qubits, params)[source]¶ Bases:
qutip_qip.compiler.gatecompiler.GateCompiler
Compiler for
SCQubits
. Compiled pulse strength is in the unit of GHz.-
cnot_compiler
(gate, args)[source]¶ Compiler for CNOT gate using the cross resonance iteraction. See https://journals.aps.org/prb/abstract/10.1103/PhysRevB.81.134507 for reference
-
qutip_qip.compiler.gatecompiler module¶
-
class
qutip_qip.compiler.gatecompiler.
GateCompiler
(num_qubits=None, params=None, pulse_dict=None, N=None)[source]¶ Bases:
object
Base class. It compiles a
QubitCircuit
into the pulse sequence for the processor. The core member function compile calls compiling method from the sub-class and concatenate the compiled pulses.- Parameters
- num_qubits: int
The number of the component systems.
- params: dict, optional
A Python dictionary contains the name and the value of the parameters, such as laser frequency, detuning etc. It will be saved in the class attributes and can be used to calculate the control pulses.
- Attributes
- gate_compiler: dict
The Python dictionary in the form of {gate_name: compiler_function}. It saves the compiling routine for each gate. See sub-classes for implementation. Note that for continuous pulse, the first coeff should always be 0.
- args: dict
Arguments for individual compiling routines. It adds more flexibility in customizing compiler.
-
compile
(circuit, schedule_mode=None, args=None)[source]¶ Compile the the native gates into control pulse sequence. It calls each compiling method and concatenates the compiled pulses.
- Parameters
- circuit: :class:`.QubitCircuit` or list of
Gate
A list of elementary gates that can be implemented in the corresponding hardware. The gate names have to be in gate_compiler.- schedule_mode: str, optional
"ASAP"
for “as soon as possible” or"ALAP"
for “as late as possible” orFalse
orNone
for no schedule. Default is None.- args: dict, optional
A dictionary of arguments used in a specific gate compiler function.
- Returns
- tlist, coeffs: array_like or dict
Compiled ime sequence and pulse coefficients. if
return_array
is true, return A 2d NumPy array of the shape(len(ctrls), len(tlist))
. Each row corresponds to the control pulse sequence for one Hamiltonian. ifreturn_array
is false
qutip_qip.compiler.instruction module¶
-
class
qutip_qip.compiler.instruction.
Instruction
(gate, tlist=None, pulse_info=(), duration=1)[source]¶ Bases:
object
The instruction that implements a quantum gate. It contains the control pulse required to implement the gate on a particular hardware model.
- Parameters
- gate: :class:`.Gate`
The quantum gate.
- duration: list, optional
The execution time needed for the instruction.
- tlist: array_like, optional
A list of time at which the time-dependent coefficients are applied. See
Pulse
for detailed information`- pulse_info: list, optional
A list of tuples, each tuple corresponding to a pair of pulse label and pulse coefficient, in the format (str, array_like). This pulses will implement the desired gate.
- Attributes
- targets: list, optional
The target qubits.
- controls: list, optional
The control qubits.
- used_qubits: set
Union of the control and target qubits.
-
property
controls
¶ Control qubits
- Type
list
-
property
name
¶ Corresponding gate name
-
property
targets
¶ Target qubits
- Type
list
qutip_qip.compiler.scheduler module¶
-
class
qutip_qip.compiler.scheduler.
InstructionsGraph
(instructions)[source]¶ Bases:
object
A directed acyclic graph (DAG) representation of the quantum instruction dependency. An example is Fig3(b) in https://doi.org/10.1117/12.666419. It contains methods of generating the instruction dependency graph, a list-schedule algorithm to find the topological order and the computation of the distance in the weighted graph (circuit latency).
It uses the Instruction object as a representation of node and adds the following attributes to it:
predecessors, successors: dependency arrow of the DAG distance_to_start, distance_to_end: longest distance to the start and end
- Parameters
- instructions: list
A list of instructions
- Attributes
- nodes: list
The input list of instruction with additional graph information.
- start, end: list
List of indices of nodes connected to the start or end nodes.
-
add_constraint_dependency
(constraint_dependency)[source]¶ Add the dependency caused by hardware constraint to the graph.
- Parameters
- constraint_dependency: list
constraint_dependency obtained by the method find_topological_order.
-
compute_distance
(cycles_list)[source]¶ Compute the longest distance of each node to the start and end nodes. The weight for each dependency arrow is the duration of the source instruction (which should be 1 for gates schedule). The method solves the longest path problem by using the topological order in cycles_list. It makes sure that by following the list, the distance to the predecessors (successors) of the source (target) node is always calculated before the target (source) node.
- Parameters
- cycles_list: list
A cycles_list obtained by the method find_topological_order.
-
find_topological_order
(priority=True, apply_constraint=None, random=False)[source]¶ A list-schedule algorithm, it finds the topological order of the directed graph under certain constraint and priority indicator. The function returns a list of cycles, where each cycle is a list of instructions that can be executed in parallel. In the case of gates schedule, the result will be the gates cycle list.
- Parameters
- priority: bool
If use distance to the start and end nodes as a priority measure for the schedule problem.
- apply_constraint: function
A Python function that determines if to instruction can be executed in parallel. E.g. if two gates apply to the same qubit, the function returns False.
- Returns
- cycles_list: list
A list of cycles, where each cycle is a list of instructions that can be executed in parallel.
- constraint_dependency: set
A set of instruction pairs that are found conflicted due to the hardware constraints. Because of this, they are executed in different cycles. This set is used to add this dependency to the graph in another method.
-
generate_dependency_graph
(commuting)[source]¶ Generate the instruction dependency graph. It modifies the class attribute nodes, where each element (node) is an Instruction. The graph is represented by attributes predecessors and successors, each a set of indices pointing to the position of the target node in the nodes list.
The graph preserves the mobility of the gates, i.e. if two gates commute with each other, such as
CNOT 2, 3
andCNOT 2, 1
, there should be no dependency arrow between them. Because of this, the generated graph does not consider the hardware constraints, e.g. two commuting gates addressing the same qubits cannot be executed at the same time. A dependency arrow between Instruction 1 and instruction 2 means that they do not commute. However, the converse does not hold because we do not need gate1->gate3 if we already have gate1->gate2->gate3.- Parameters
- commuting: function
A Python function that determines if two gates commute, given that their used qubits overlap.
-
class
qutip_qip.compiler.scheduler.
Scheduler
(method='ALAP', constraint_functions=None)[source]¶ Bases:
object
A gate (pulse) scheduler for quantum circuits (instructions). It schedules a given circuit or instructions to reduce the total execution time by parallelization. It uses heuristic methods mainly from in https://doi.org/10.1117/12.666419.
The scheduler includes two methods, “ASAP”, as soon as possible, and “ALAP”, as late as possible. The later is commonly used in quantum computation because of the finite lifetime of qubits.
The scheduler aims at pulse schedule and therefore does not consider merging gates to reduce the gates number. It assumes that the input circuit is optimized at the gate level and matches the hardware topology.
- Parameters
- method: str
“ASAP” for as soon as possible. “ALAP” for as late as possible.
- constraint_functions: list, optional
A list of hardware constraint functions. Default includes a function qubit_contraint, i.e. one qubit cannot be used by two gates at the same time.
-
apply_constraint
(ind1, ind2, instructions)[source]¶ Apply hardware constraint to check if two instructions can be executed in parallel.
- Parameters
- ind1, ind2: int
indices of the two instructions
- instructions: list
The instruction list
-
commutation_rules
(ind1, ind2, instructions)[source]¶ Determine if two gates commute, given that their used qubits overlap. Since usually the input gates are already in a universal gate sets, it uses an oversimplified condition:
If the two gates do not have the same name, they are considered as not commuting. If they are the same gate and have the same controls or targets, they are considered as commuting. E.g. CNOT 0, 1 commute with CNOT 0, 2.
-
schedule
(circuit, gates_schedule=False, return_cycles_list=False, random_shuffle=False, repeat_num=0)[source]¶ Schedule a QubitCircuit, a list of Gates or a list of Instruction. For pulse schedule, the execution time for each Instruction is given in its duration attributes.
The scheduler first generates a quantum gates dependency graph, containing information about which gates have to be executed before some other gates. The graph preserves the mobility of the gates, i.e. commuting gates are not dependent on each other, even if they use the same qubits. Next, it computes the longest distance of each node to the start and end nodes. The distance for each dependency arrow is defined by the execution time of the instruction (By default, it is 1 for all gates). This is used as a priority measure in the next step. The gate with a longer distance to the end node and a shorter distance to the start node has higher priority. In the last step, it uses a list-schedule algorithm with hardware constraint and priority and returns a list of cycles for gates/instructions.
For pulse schedule, an additional step is required to compute the start time of each instruction. It adds the additional dependency caused by hardware constraint to the graph and recomputes the distance of each node to the start and end node. This distance is then converted to the start time of each instruction.
- Parameters
- circuit: QubitCircuit or list
For gate schedule, it should be a QubitCircuit or a list of Gate objects. For pulse schedule, it should be a list of Instruction objects, each with an attribute duration that indicates the execution time of this instruction.
- gates_schedule: bool, optional
True, if only gates schedule is needed. This saves some computation that is only useful to pulse schedule. If the input circuit is a QubitCircuit, it will be assigned to True automatically. Otherwise, the default is False.
- return_cycles_list: bool, optional
If True, the method returns the cycles_list, e.g. [{0, 2}, {1, 3}], which means that the first cycle contains gates0 and gates2 while the second cycle contains gates1 and gates3. It is only usefull for gates schedule.
- random_shuffle: bool, optional
If the commuting gates are randomly scuffled to explore larger search space.
- repeat_num: int, optional
Repeat the scheduling several times and use the best result. Used together with
random_shuffle=Ture
.
- Returns
- gate_cycle_indices or instruction_start_time: list
The cycle indices for each gate or the start time for each instruction.
Examples
>>> from qutip_qip.circuit import QubitCircuit >>> from qutip_qip.compiler import Scheduler >>> circuit = QubitCircuit(7) >>> circuit.add_gate("SNOT", 3) # gate0 >>> circuit.add_gate("CZ", 5, 3) # gate1 >>> circuit.add_gate("CZ", 4, 3) # gate2 >>> circuit.add_gate("CZ", 2, 3) # gate3 >>> circuit.add_gate("CZ", 6, 5) # gate4 >>> circuit.add_gate("CZ", 2, 6) # gate5 >>> circuit.add_gate("SWAP", [0, 2]) # gate6 >>> >>> scheduler = Scheduler("ASAP") >>> scheduler.schedule(circuit, gates_schedule=True) [0, 1, 3, 2, 2, 3, 4]
The result list is the cycle indices for each gate. It means that the circuit can be executed in 5 gate cycles:
[gate0, gate1, (gate3, gate4), (gate2, gate5), gate6]
Notice that gate3 and gate4 commute with gate2, therefore, the order is changed to reduce the number of cycles.
qutip_qip.compiler.spinchaincompiler module¶
-
class
qutip_qip.compiler.spinchaincompiler.
SpinChainCompiler
(num_qubits, params, setup='linear', global_phase=0.0, pulse_dict=None, N=None)[source]¶ Bases:
qutip_qip.compiler.gatecompiler.GateCompiler
Compile a
QubitCircuit
into the pulse sequence for the processor.- Parameters
- num_qubits: int
The number of qubits in the system.
- params: dict
A Python dictionary contains the name and the value of the parameters. See
SpinChain.set_up_params()
for the definition.- setup: string
“linear” or “circular” for two sub-classes.
- global_phase: bool
Record of the global phase change and will be returned.
- pulse_dict: dict, optional
A map between the pulse label and its index in the pulse list. If given, the compiled pulse can be identified with
(pulse_label, coeff)
, instead of(pulse_index, coeff)
. The number of key-value pairs should match the number of pulses in the processor. If it is empty, an integerpulse_index
needs to be used in the compiling routine saved under the attributesgate_compiler
.
- Attributes
- num_qubits: int
The number of the component systems.
- params: dict
A Python dictionary contains the name and the value of the parameters, such as laser frequency, detuning etc.
- gate_compiler: dict
The Python dictionary in the form of {gate_name: decompose_function}. It saves the decomposition scheme for each gate.
- setup: string
“linear” or “circular” for two sub-classes.
- global_phase: bool
Record of the global phase change and will be returned.