mimiqcircuits package#

class mimiqcircuits.AsciiCanvas(width=None)[source]#

Bases: object

draw_box(row, col, width, height, clean=False)[source]#
draw_double_hline(row, col, width)[source]#
draw_double_vline(row, col, height)[source]#
draw_empty(row, col, width, height)[source]#
draw_fill(char, row, col, width, height)[source]#
draw_hline(row, col, width)[source]#
draw_text(text, row, col)[source]#
draw_vline(row, col, height)[source]#
draw_vtext(text, row, col)[source]#
get_cols()[source]#
get_rows()[source]#
push_line()[source]#
reset()[source]#
class mimiqcircuits.AsciiCircuit(width=None)[source]#

Bases: object

draw_barrier(barrier, qubits)[source]#
draw_control(operation, qubits, _)[source]#
draw_ifstatement(if_statement, qubits, bits)[source]#
draw_instruction(instruction)[source]#
draw_measure(qubits, bits)[source]#
draw_measurereset(qubits, bits)[source]#
draw_operation(operation, qubits, bits)[source]#
draw_parallel(parallel, qubits, _)[source]#
draw_reset(reset, qubits, _)[source]#
draw_wires(qubits, bits)[source]#
get_bit_row()[source]#
get_current_col()[source]#
get_qubit_row(qubit)[source]#
reset()[source]#
set_current_col(col)[source]#
class mimiqcircuits.Barrier(*args)[source]#

Bases: Operation

Barrier operation.

A barrier is a special operation that does not affect the quantum state or the execution of a circuit, but it prevents compression or optimization operation from being applied across it.

Examples

Adding Barrier operation to the Circuit (The args can be: range, list, tuple, set or int)

>>> from mimiqcircuits import *
>>> c= Circuit()
>>> c.push(Barrier(1), 1)
2-qubit circuit with 1 instructions:
└── Barrier @ q[1]
>>> from mimiqcircuits import *
>>> c= Circuit()
>>> c.push(Barrier(1), range(0,4))
4-qubit circuit with 4 instructions:
├── Barrier @ q[0]
├── Barrier @ q[1]
├── Barrier @ q[2]
└── Barrier @ q[3]

Adding Barrier to the circuit as a multi-qubits gate

>>> from mimiqcircuits import *
>>> c= Circuit()
>>> c.push(Barrier(5),1,2,3,4,5)
6-qubit circuit with 1 instructions:
└── Barrier @ q[1,2,3,4,5]
asciiwidth(qubits, bits)[source]#
control(num_qubits)[source]#
inverse()[source]#
iswrapper()[source]#
power(p)[source]#
class mimiqcircuits.BitString(arg)[source]#

Bases: object

BitString for the quantum states.

Representation of the quantum state of a quantum register with definite values for each qubit.

Examples

Initialization:

>>> from mimiqcircuits import *
>>> from bitarray import bitarray
>>> BitString(16) # number of qubits
bs"0000000000000000"
>>> BitString('10101') # binary string
bs"10101"
>>> BitString([1,0,0,0,1]) # binary string
bs"10001"
>>> BitString((1,0,0,0,1)) # binary string
bs"10001"
>>> BitString(bitarray('101010')) # bitarray
bs"101010"

Other initializations:

>>> BitString.fromnonzeros(16, [1, 3, 5, 7, 9, 11, 13, 15])
bs"0101010101010101"
>>> BitString.fromfunction(16, lambda i: i % 2 == 1)
bs"0101010101010101"
>>> BitString.fromstring('10101')
bs"10101"
>>> BitString.fromint(16, 21)
bs"1010100000000000"
>>> BitString.fromint(16, 21, 'little')
bs"0000000000010101"

Accessing the bits:

>>> bs = BitString(16)
>>> bs[0] # get the 0th bit
0
>>> bs[0:4] # get the first 4 bits
bs"0000"

Bitwise operations:

>>> bs1 = BitString('10101')
>>> bs2 = BitString('11100')
>>> bs1 | bs2 # OR
bs"11101"
>>> bs1 & bs2 # AND
bs"10100"
>>> bs1 ^ bs2 # XOR
bs"01001"
>>> ~bs1 # NOT
bs"01010"
>>> bs1 << 2 # left shift
bs"10100"
>>> bs1 >> 2 # right shift
bs"00101"

Other operations:

>>> bs1 + bs2 # concatenation
bs"1010111100"
>>> bs1 * 2 # repetition
bs"1010110101"
property bits#
static fromfunction(num_qubits: int, f: type[~mimiqcircuits.bitstrings.BitString.<lambda>])[source]#

Initialize a BitString from a function.

Parameters:
  • num_qubits (int) – The number of qubits in the BitString.

  • f (function) – A function that takes an integer and returns a boolean.

Returns:

A BitString.

static fromint(num_qubits: int, integer: int, endianess: str = 'big')[source]#

Initialize a BitString from an integer.

Parameters:
  • num_qubits (int) – The number of qubits in the BitString.

  • integer (int) – The integer value of the BitString.

  • endianess (str) – The endianess of the integer. Default is ‘big’.

Returns:

A BitString.

static fromnonzeros(num_qubits: int, nonzeros: list)[source]#

Initialize a BitString with specific non-zero qubits.

Parameters:
  • num_qubits (int) – The number of qubits in the BitString.

  • nonzeros (list) – A list of non-zero qubit indices to set in the BitString.

Returns:

A BitString with the specified non-zero qubits.

static fromstring(bitstring: str)[source]#

Initialize a BitString from a string.

Parameters:

bitstring (str) – The string representation of the BitString.

Returns:

A BitString.

nonzeros()[source]#

Return the indices of the non-zero qubits.

num_qubits()[source]#

Return the number of qubits in the BitString.

to01(endianess='big')[source]#

Return the binary string representation of the BitString.

Parameters:

endianess (str) – The endianess of the integer. Default is ‘big’

Retruns:

The binary string representation of the BitString.

toindex(endianess: str = 'big')[source]#

Return the integer index of the BitString.

Parameters:

endianess (str) – The endianess of the integer. Default is ‘big’.

Returns:

The integer index of the BitString.

tointeger(endianess: str = 'big')[source]#

Return the integer value of the BitString.

Parameters:

endianess (str) – The endianess of the integer. Default is ‘big’.

Returns:

The integer value of the BitString.

zeros()[source]#

Return the indices of the zero qubits.

class mimiqcircuits.Circuit(instructions=None)[source]#

Bases: object

Representation of a quantum circuit.

Operation can be added one by one to a circuit with the c.push(operation, targets...) function

Parameters:

instructions (list of Instruction) – Instructiuons to add at construction.

Raises:

TypeError – If initialization list contains non-Instruction objects.

Examples

>>> from mimiqcircuits import *
>>> from symengine import pi

Create a new circuit object

>>> c = Circuit()

Add a GateX (Pauli-X) gate on qubit 0

>>> c.push(GateX(), 0)
1-qubit circuit with 1 instructions:
└── X @ q[0]

Add a Controlled-NOT (CX) gate with control qubit 0 and target qubit 1

>>> c.push(GateCX(), 0, 1)
2-qubit circuit with 2 instructions:
├── X @ q[0]
└── CX @ q[0], q[1]

Add a Parametric GateRX gate with parameters pi/4

>>> c.push(GateRX(pi / 4),0)
2-qubit circuit with 3 instructions:
├── X @ q[0]
├── CX @ q[0], q[1]
└── RX((1/4)*pi) @ q[0]

Add a Reset gate on qubit 0

>>> c.push(Reset(), 0)
2-qubit circuit with 4 instructions:
├── X @ q[0]
├── CX @ q[0], q[1]
├── RX((1/4)*pi) @ q[0]
└── Reset @ q[0]

Add a Barrier gate on qubits 0 and 1

>>> c.push(Barrier(2), 0, 1)
2-qubit circuit with 5 instructions:
├── X @ q[0]
├── CX @ q[0], q[1]
├── RX((1/4)*pi) @ q[0]
├── Reset @ q[0]
└── Barrier @ q[0,1]

Add a Measurement gate on qubit 0, storing the result in bit 0.

>>> c.push(Measure(), 0, 0)
2-qubit circuit with 6 instructions:
├── X @ q[0]
├── CX @ q[0], q[1]
├── RX((1/4)*pi) @ q[0]
├── Reset @ q[0]
├── Barrier @ q[0,1]
└── Measure @ q[0], c[0]

Add a Control gate with GateX as the target gate. The first 3 qubits are the control qubits.

>>> c.push(Control(3, GateX()), 0, 1, 2, 3)
4-qubit circuit with 7 instructions:
├── X @ q[0]
├── CX @ q[0], q[1]
├── RX((1/4)*pi) @ q[0]
├── Reset @ q[0]
├── Barrier @ q[0,1]
├── Measure @ q[0], c[0]
└── C₃X @ q[0,1,2], q[3]

Add a 3-qubit Parallel gate with GateX

>>> c.push(Parallel(3,GateX()),0, 1, 2)
4-qubit circuit with 8 instructions:
├── X @ q[0]
├── CX @ q[0], q[1]
├── RX((1/4)*pi) @ q[0]
├── Reset @ q[0]
├── Barrier @ q[0,1]
├── Measure @ q[0], c[0]
├── C₃X @ q[0,1,2], q[3]
└── Parallel(3, X) @ q[0], q[1], q[2]

To add operations without constructing them first, use the c.emplace(…) function.

Available operations#

Gates

Single qubit gates

GateX() GateY() GateZ() GateH() GateS() GateSDG() GateT() GateTDG() GateSX() GateSXDG() GateID()

Single qubit gates (parametric)

GateU() GateP() GateRX() GateRY() GateRZ() GateP()

Two qubit gates

GateCX() GateCY() GateCZ() GateCH() GateSWAP() GateISWAP() GateCS() GateCSX() GateECR() GateDCX()

Two qubit gates (parametric)

GateCU() GateCP() GateCRX() GateCRY() GateCRZ() GateRXX() GateRYY() GateRZZ() GateXXplusYY() GateXXminusYY()

Other

GateCustom()

No-ops

Barrier()

Non-unitary operations

Measure() Reset()

Composite operations

Control() Parallel()

Power & Inverse operations

Power() Inverse()

Generalized gates

QFT() PhaseGradient()

append(other)[source]#

Appends all the gates of the given circuit at the end of the current circuit.

Parameters:

other (Circuit) – the circuit to append.

copy()[source]#
decompose()[source]#

Decompose all the gates in the circuit.

If applied multiple times, will reduce the circuit to a basis set of U and CX gates.

deepcopy()[source]#
depth()[source]#

Computes the depth of the quantum circuit.

draw()[source]#

Draws the entire quantum circuit on the ASCII canvas and handles the layout of various quantum operations.

This method iterates through all instructions in the circuit, determines the required width for each operation, and delegates the drawing of each operation to the appropriate specialized method based on the operation type. If an operation’s width exceeds the available space in the current row of the canvas, the canvas is printed and reset to continue drawing from a new starting point.

The method manages different operation types including control, measurement, reset, barrier, parallel, and conditional (if) operations using specific drawing methods from the AsciiCircuit class.

Raises:
  • TypeError – If any item in the circuit’s instructions is not an instance of Instruction.

  • ValueError – If an operation cannot be drawn because it exceeds the available canvas width even after a reset.

Prints:

The current state of the ASCII canvas, either incrementally after each operation if space runs out, or entirely at the end of processing all instructions.

Returns:

None

emplace(op, *regs)[source]#

Constructs and adds an Operation to the end of the circuit.

It is useful to add to the circuit operations that are dependent on the number of qubits.

Parameters:
  • operation (Type subclass of Operation) – the type of operation to add.

  • args (vararg of list) – A variable number of arguments compriseing a list of parameters (if the operation is parametric), one list of qubits for each quantum register, and one list of bits of every classical register supported.

Examples

>>> from mimiqcircuits import *
>>> c = Circuit()
>>> c.emplace(GateX(), [0])
1-qubit circuit with 1 instructions:
└── X @ q[0]

>>> c.emplace(GateRX(0.2), [0])
1-qubit circuit with 2 instructions:
├── X @ q[0]
└── RX(0.2) @ q[0]

>>> c.emplace(QFT(), range(10))
10-qubit circuit with 3 instructions:
├── X @ q[0]
├── RX(0.2) @ q[0]
└── QFT @ q[0,1,2,3,4,5,6,7,8,9]
empty()[source]#

Checks if the circuit is empty.

evaluate(d)[source]#
insert(index: int, operation, *args)[source]#

Inserts an operation or another circuit at a specific index in the circuit.

Parameters:
  • index (int) – The index at which the operation should be inserted.

  • operation (Operation or Instruction) – the quantum operation to add.

  • args (integers or iterables) – Target qubits and bits for the operation (not instruction), given as variable number of arguments.

Raises:
  • TypeError – If operation is not an Operation object.

  • ValueError – If the number of arguments is incorrect or the target qubits specified are invalid.

Examples

Inserting an operation to the specify index of the circuit

>>> from mimiqcircuits import *
>>> c= Circuit()
>>> c.push(GateX(), 0)
1-qubit circuit with 1 instructions:
└── X @ q[0]

>>> c.push(GateCX(),0,1)
2-qubit circuit with 2 instructions:
├── X @ q[0]
└── CX @ q[0], q[1]

>>> c.insert(1, GateH(), 0)
2-qubit circuit with 3 instructions:
├── X @ q[0]
├── H @ q[0]
└── CX @ q[0], q[1]
inverse()[source]#

Returns the inverse of the circuit.

is_symbolic()[source]#

Check whether the circuit contains any symbolic (unevaluated) parameters.

This method examines each instruction in the circuit to determine if any parameter remains symbolic (i.e., unevaluated). It recursively checks through each instruction and its nested operations, if any.

Returns:

True if any parameter is symbolic (unevaluated), False if all parameters are fully evaluated.

Return type:

bool

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> x, y = symbols("x y")
>>> c = Circuit()
>>> c.push(GateH(), 0)
1-qubit circuit with 1 instructions:
└── H @ q[0]

>>> c.is_symbolic()
False
>>> c.push(GateP(x), 0)
1-qubit circuit with 2 instructions:
├── H @ q[0]
└── P(x) @ q[0]

>>> c.is_symbolic()
True
>>> c = c.evaluate({x: 1, y: 2})
>>> c
1-qubit circuit with 2 instructions:
├── H @ q[0]
└── P(1) @ q[0]

>>> c.is_symbolic()
False
static loadproto(filename)[source]#

Loads a circuit from a protobuf (binary) file.

Parameters:

filename (str) – The name of the file to load the circuit from.

Returns:

The circuit loaded from the file.

Return type:

Circuit

Note

Look for example in Circuit.saveproto()

num_bits()[source]#

Returns the number of bits in the circuit.

num_qubits()[source]#

Returns the number of qubits in the circuit.

push(operation, *args)[source]#

Adds an Operation or an Instruction to the end of the circuit.

Parameters:
  • operation (Operation or Instruction) – the quantum operation to add.

  • args (integers or iterables) – Target qubits and bits for the operation (not instruction), given as variable number of arguments.

Raises:
  • TypeError – If operation is not an Operation object.

  • ValueError – If the number of arguments is incorrect or the target qubits specified are invalid.

Examples

Adding multiple operations to the Circuit (The args can be integers or integer-valued iterables)

>>> from mimiqcircuits import *
>>> from symengine import pi
>>> c = Circuit()
>>> c.push(GateH(), 0)
1-qubit circuit with 1 instructions:
└── H @ q[0]

>>> c.push(GateT(), 0)
1-qubit circuit with 2 instructions:
├── H @ q[0]
└── T @ q[0]

>>> c.push(GateH(), [0,2])
3-qubit circuit with 4 instructions:
├── H @ q[0]
├── T @ q[0]
├── H @ q[0]
└── H @ q[2]

>>> c.push(GateS(), 0)
3-qubit circuit with 5 instructions:
├── H @ q[0]
├── T @ q[0]
├── H @ q[0]
├── H @ q[2]
└── S @ q[0]

>>> c.push(GateCX(), [2, 0], 1)
3-qubit circuit with 7 instructions:
├── H @ q[0]
├── T @ q[0]
├── H @ q[0]
├── H @ q[2]
├── S @ q[0]
├── CX @ q[2], q[1]
└── CX @ q[0], q[1]

>>> c.push(GateH(), 0)
3-qubit circuit with 8 instructions:
├── H @ q[0]
├── T @ q[0]
├── H @ q[0]
├── H @ q[2]
├── S @ q[0]
├── CX @ q[2], q[1]
├── CX @ q[0], q[1]
└── H @ q[0]

>>> c.push(Barrier(3), *range(3)) # equivalent to c.push(Barrier(3), 0, 1, 2)
3-qubit circuit with 9 instructions:
├── H @ q[0]
├── T @ q[0]
├── H @ q[0]
├── H @ q[2]
├── S @ q[0]
├── CX @ q[2], q[1]
├── CX @ q[0], q[1]
├── H @ q[0]
└── Barrier @ q[0,1,2]

>>> c.push(Measure(), range(3), range(3))
3-qubit circuit with 12 instructions:
├── H @ q[0]
├── T @ q[0]
├── H @ q[0]
├── H @ q[2]
├── S @ q[0]
├── CX @ q[2], q[1]
├── CX @ q[0], q[1]
├── H @ q[0]
├── Barrier @ q[0,1,2]
├── Measure @ q[0], c[0]
├── Measure @ q[1], c[1]
└── Measure @ q[2], c[2]

>>> c
3-qubit circuit with 12 instructions:
├── H @ q[0]
├── T @ q[0]
├── H @ q[0]
├── H @ q[2]
├── S @ q[0]
├── CX @ q[2], q[1]
├── CX @ q[0], q[1]
├── H @ q[0]
├── Barrier @ q[0,1,2]
├── Measure @ q[0], c[0]
├── Measure @ q[1], c[1]
└── Measure @ q[2], c[2]
remove(index: int)[source]#

Removes an instruction at a specific index from the circuit.

Parameters:

index (int) – The index of the gate to remove.

Raises:

IndexError – If index is out of range.

saveproto(filename)[source]#

Saves the circuit as a protobuf (binary) file.

Parameters:

filename (str) – The name of the file to save the circuit to.

Returns:

The number of bytes written to the file.

Return type:

int

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> import tempfile
>>> x, y = symbols("x y")
>>> c = Circuit()
>>> c.push(GateH(), 0)
1-qubit circuit with 1 instructions:
└── H @ q[0]

>>> c.push(GateXXplusYY(x**2, y),0,1)
2-qubit circuit with 2 instructions:
├── H @ q[0]
└── XXplusYY(x**2, y) @ q[0,1]

>>> c.push(Measure(),0,0)
2-qubit circuit with 3 instructions:
├── H @ q[0]
├── XXplusYY(x**2, y) @ q[0,1]
└── Measure @ q[0], c[0]

>>> tmpfile = tempfile.NamedTemporaryFile(suffix=".pb", delete=True)
>>> c.saveproto(tmpfile.name)
61
>>> c.loadproto(tmpfile.name)
2-qubit circuit with 3 instructions:
├── H @ q[0]
├── XXplusYY(x**2, y) @ q[0,1]
└── Measure @ q[0], c[0]
Note:

This example uses a temporary file to demonstrate the save and load functionality. You can save your file with any name at any location using:

c.saveproto("example.pb")
c.loadproto("example.pb")
specify_operations()[source]#
class mimiqcircuits.Control(num_controls, operation, *args, **kwargs)[source]#

Bases: Operation

Control operation.

A Control is a special operation that applies multi-control gates to the Circuit at once.

Examples

>>> from mimiqcircuits import *
>>> c = Circuit()
>>> c.push(Control(3,GateX()),1,2,3,4)
5-qubit circuit with 1 instructions:
└── C₃X @ q[1,2,3], q[4]

>>> Control(2, GateX()).matrix()
[1.0, 0, 0, 0, 0, 0, 0, 0]
[0, 1.0, 0, 0, 0, 0, 0, 0]
[0, 0, 1.0, 0, 0, 0, 0, 0]
[0, 0, 0, 1.0, 0, 0, 0, 0]
[0, 0, 0, 0, 1.0, 0, 0, 0]
[0, 0, 0, 0, 0, 1.0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1.0]
[0, 0, 0, 0, 0, 0, 1.0, 0]
control(*args)[source]#
evaluate(d)[source]#
get_operation()[source]#
getparams()[source]#
inverse()[source]#
iswrapper()[source]#
matrix()[source]#
property num_controls#
property num_targets#
property op#
parallel(*args)[source]#
power(*args)[source]#
class mimiqcircuits.Diffusion(*args)[source]#

Bases: Gate

Grover’s diffusion operator.

Parameters:

num_qubits (int) – The number of qubits.

Raises:

ValueError – If the number of qubits is not an integer or less than 1.

Returns:

Grover’s diffusion operator.

Return type:

Diffusion

num_qubits#

The number of qubits for the diffusion operator.

Type:

int

Examples

>>> from mimiqcircuits import *
>>> c = Circuit()
>>> c.push(Diffusion(2), 1, 2)
3-qubit circuit with 1 instructions:
└── Diffusion @ q[1,2]
class mimiqcircuits.Gate[source]#

Bases: Operation

control(*args)[source]#
evaluate(d)[source]#
inverse()[source]#
iswrapper()[source]#
matrix()[source]#
parallel(*args)[source]#
power(*args)[source]#
class mimiqcircuits.GateC3X[source]#

Bases: Control

Four qubit Controlled-Controlled-Controlled-X gate.

By convention, the first three qubits are the controls and the fourth is the target

Examples

>>> from mimiqcircuits import *
>>> GateC3X(), GateC3X().num_controls, GateC3X().num_targets, GateC3X().num_qubits
(C₃X, 3, 1, 4)
>>> GateC3X().matrix()
[1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0]
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0]

>>> c = Circuit().push(GateC3X(), 0, 1, 2, 3)
>>> c
4-qubit circuit with 1 instructions:
└── C₃X @ q[0,1,2], q[3]

>>> GateC3X().power(2), GateC3X().inverse()
(C₃ID, C₃X)
>>> GateC3X().decompose()
4-qubit circuit with 31 instructions:
├── H @ q[3]
├── P((1/8)*pi) @ q[0]
├── P((1/8)*pi) @ q[1]
├── P((1/8)*pi) @ q[2]
├── P((1/8)*pi) @ q[3]
├── CX @ q[0], q[1]
├── P((-1/8)*pi) @ q[1]
├── CX @ q[0], q[1]
├── CX @ q[1], q[2]
├── P((-1/8)*pi) @ q[2]
├── CX @ q[0], q[2]
├── P((1/8)*pi) @ q[2]
├── CX @ q[1], q[2]
├── P((-1/8)*pi) @ q[2]
├── CX @ q[0], q[2]
├── CX @ q[2], q[3]
├── P((-1/8)*pi) @ q[3]
├── CX @ q[1], q[3]
├── P((1/8)*pi) @ q[3]
⋮   ⋮
└── H @ q[3]
class mimiqcircuits.GateCCP(*args, **kwargs)[source]#

Bases: Control

Three qubit Controlled-Controlled-Phase gate.

By convention, the first two qubits are the controls and the third is the target

Parameters:

lmbda – Phase angle.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> lmbda = Symbol('lmbda')
>>> GateCCP(lmbda), GateCCP(lmbda).num_controls, GateCCP(lmbda).num_targets, GateCCP(lmbda).num_qubits
(C₂P(lmbda), 2, 1, 3)
>>> GateCCP(lmbda).matrix()
[1.0, 0, 0, 0, 0, 0, 0, 0]
[0, 1.0, 0, 0, 0, 0, 0, 0]
[0, 0, 1.0, 0, 0, 0, 0, 0]
[0, 0, 0, 1.0, 0, 0, 0, 0]
[0, 0, 0, 0, 1.0, 0, 0, 0]
[0, 0, 0, 0, 0, 1.0, 0, 0]
[0, 0, 0, 0, 0, 0, 1.0, 0]
[0, 0, 0, 0, 0, 0, 0, exp(I*lmbda)]

>>> c = Circuit().push(GateCCP(lmbda), 0, 1, 2)
>>> c
3-qubit circuit with 1 instructions:
└── C₂P(lmbda) @ q[0,1], q[2]

>>> GateCCP(lmbda).power(2), GateCCP(lmbda).inverse()
(C₂P(2*lmbda), C₂P(-lmbda))
>>> GateCCP(lmbda).decompose()
3-qubit circuit with 5 instructions:
├── CP((1/2)*lmbda) @ q[1], q[2]
├── CX @ q[0], q[1]
├── CP((-1/2)*lmbda) @ q[1], q[2]
├── CX @ q[0], q[1]
└── CP((1/2)*lmbda) @ q[0], q[2]
class mimiqcircuits.GateCCX[source]#

Bases: Control

Three qubit Controlled-Controlled-X gate.

By convention, the first two qubits are the controls and the third is the target.

Examples

>>> from mimiqcircuits import *
>>> GateCCX(), GateCCX().num_controls, GateCCX().num_targets, GateCCX().num_qubits
(C₂X, 2, 1, 3)
>>> GateCCX().matrix()
[1.0, 0, 0, 0, 0, 0, 0, 0]
[0, 1.0, 0, 0, 0, 0, 0, 0]
[0, 0, 1.0, 0, 0, 0, 0, 0]
[0, 0, 0, 1.0, 0, 0, 0, 0]
[0, 0, 0, 0, 1.0, 0, 0, 0]
[0, 0, 0, 0, 0, 1.0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1.0]
[0, 0, 0, 0, 0, 0, 1.0, 0]

>>> c = Circuit().push(GateCCX(), 0, 1, 2)
>>> c
3-qubit circuit with 1 instructions:
└── C₂X @ q[0,1], q[2]

>>> GateCCX().power(2), GateCCX().inverse()
(C₂ID, C₂X)
>>> GateCCX().decompose()
3-qubit circuit with 15 instructions:
├── H @ q[2]
├── CX @ q[1], q[2]
├── T† @ q[2]
├── CX @ q[0], q[2]
├── T @ q[2]
├── CX @ q[1], q[2]
├── T† @ q[2]
├── CX @ q[0], q[2]
├── T @ q[1]
├── T @ q[2]
├── H @ q[2]
├── CX @ q[0], q[1]
├── T @ q[0]
├── T† @ q[1]
└── CX @ q[0], q[1]
class mimiqcircuits.GateCH[source]#

Bases: Control

Two qubit Controlled-Hadamard gate.

By convention, the first qubit is the control and the second is the target

Matrix representation:

\[\begin{split}\operatorname{CH} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \frac{1}{\sqrt{2}} & \frac{1}{\sqrt{2}} \\ 0 & 0 & \frac{1}{\sqrt{2}} & -\frac{1}{\sqrt{2}} \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateCH(), GateCH().num_controls, GateCH().num_targets, GateCH().num_qubits
(CH, 1, 1, 2)
>>> GateCH().matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, 0.707106781186548, 0.707106781186548]
[0, 0, 0.707106781186548, -0.707106781186548]

>>> c = Circuit().push(GateCH(), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CH @ q[0], q[1]

>>> GateCH().power(2), GateCH().inverse()
(CID, CH)
>>> GateCH().decompose()
2-qubit circuit with 7 instructions:
├── S @ q[1]
├── H @ q[1]
├── T @ q[1]
├── CX @ q[0], q[1]
├── T† @ q[1]
├── H @ q[1]
└── S† @ q[1]
class mimiqcircuits.GateCP(*args, **kwargs)[source]#

Bases: Control

Two qubit Controlled-Phase gate.

By convention, the first qubit is the control and the second is the target

See Also GateP()

Matrix representation:

\[\begin{split}\operatorname{CP}(\lambda) = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & e^{i\lambda} \end{pmatrix}\end{split}\]
Parameters:

lambda – Phase angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> lmbda = Symbol('lambda')
>>> GateCP(lmbda), GateCP(lmbda).num_controls, GateCP(lmbda).num_targets, GateCP(lmbda).num_qubits
(CP(lambda), 1, 1, 2)
>>> GateCP(lmbda).matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, 1.0, 0]
[0, 0, 0, exp(I*lambda)]

>>> c = Circuit().push(GateCP(lmbda), 10, 11)
>>> c
12-qubit circuit with 1 instructions:
└── CP(lambda) @ q[10], q[11]

>>> GateCP(lmbda).decompose()
2-qubit circuit with 5 instructions:
├── P((1/2)*lambda) @ q[0]
├── CX @ q[0], q[1]
├── P((-1/2)*lambda) @ q[1]
├── CX @ q[0], q[1]
└── P((1/2)*lambda) @ q[1]
class mimiqcircuits.GateCRX(*args, **kwargs)[source]#

Bases: Control

Two qubit Controlled-RX gate.

By convention, the first qubit is the control and the second is the target

See Also GateRX(), GateCRY(), GateCRZ()

Matrix representation:

\[\begin{split}\operatorname{CRX}(\theta) = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} \\ 0 & 0 & -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{pmatrix}\end{split}\]
Parameters:

theta – The rotation angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta = Symbol('theta')
>>> GateCRZ(theta), GateCRZ(theta).num_controls, GateCRZ(theta).num_targets, GateCRZ(theta).num_qubits
(CRZ(theta), 1, 1, 2)
>>> GateCRZ(theta).matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, exp(-1/2*I*theta), 0]
[0, 0, 0, exp(1/2*I*theta)]

>>> c = Circuit().push(GateCRZ(theta), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CRZ(theta) @ q[0], q[1]

>>> GateCRZ(theta).power(2), GateCRZ(theta).inverse()
(CRZ(2*theta), CRZ(-theta))
>>> GateCRZ(theta).decompose()
2-qubit circuit with 4 instructions:
├── RZ((1/2)*theta) @ q[1]
├── CX @ q[0], q[1]
├── RZ((-1/2)*theta) @ q[1]
└── CX @ q[0], q[1]
class mimiqcircuits.GateCRY(*args, **kwargs)[source]#

Bases: Control

Two qubit Controlled-RY gate.

By convention, the first qubit is the control and the second is the target

See Also GateRY(), GateCRX(), GateCRZ()

Matrix representation:

\[\begin{split}\operatorname{CRY}(\theta) = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \\ 0 & 0 & \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{pmatrix}\end{split}\]
Parameters:

theta – The rotation angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta = Symbol('theta')
>>> GateCRY(theta), GateCRY(theta).num_controls, GateCRY(theta).num_targets, GateCRY(theta).num_qubits
(CRY(theta), 1, 1, 2)
>>> GateCRY(theta).matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, cos((1/2)*theta), -sin((1/2)*theta)]
[0, 0, sin((1/2)*theta), cos((1/2)*theta)]

>>> c = Circuit().push(GateCRY(theta), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CRY(theta) @ q[0], q[1]

>>> GateCRY(theta).power(2), GateCRY(theta).inverse()
(CRY(2*theta), CRY(-theta))
>>> GateCRY(theta).decompose()
2-qubit circuit with 4 instructions:
├── RY((1/2)*theta) @ q[1]
├── CX @ q[0], q[1]
├── RY((-1/2)*theta) @ q[1]
└── CX @ q[0], q[1]
class mimiqcircuits.GateCRZ(*args, **kwargs)[source]#

Bases: Control

Two qubit Controlled-RZ gate.

By convention, the first qubit is the control and the second is the target

See Also GateRZ(), GateCRX(), GateCRY()

Matrix representation:

\[\begin{split}\operatorname{CRZ}(\theta) = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & e^{-i\frac{\lambda}{2}} & 0 \\ 0 & 0 & 0 & e^{i\frac{\lambda}{2}} \end{pmatrix}\end{split}\]
Parameters:

theta – The rotation angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> lmbda = Symbol('lambda')
>>> GateCRZ(lmbda), GateCRZ(lmbda).num_controls, GateCRZ(lmbda).num_targets, GateCRZ(lmbda).num_qubits
(CRZ(lambda), 1, 1, 2)
>>> GateCRZ(lmbda).matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, exp(-1/2*I*lambda), 0]
[0, 0, 0, exp(1/2*I*lambda)]

>>> c = Circuit().push(GateCRZ(lmbda), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CRZ(lambda) @ q[0], q[1]

>>> GateCRZ(lmbda).power(2), GateCRZ(lmbda).inverse()
(CRZ(2*lambda), CRZ(-lambda))
>>> GateCRZ(lmbda).decompose()
2-qubit circuit with 4 instructions:
├── RZ((1/2)*lambda) @ q[1]
├── CX @ q[0], q[1]
├── RZ((-1/2)*lambda) @ q[1]
└── CX @ q[0], q[1]
class mimiqcircuits.GateCS[source]#

Bases: Control

Two qubit Controlled-S gate.

By convention, the first qubit is the control and the second is the target

See Also GateS()

Matrix representation::

\[\begin{split}\operatorname{CS} =\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & i \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateCS(), GateCS().num_controls, GateCS().num_targets, GateCS().num_qubits
(CS, 1, 1, 2)
>>> GateCS().matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, 1.0, 0]
[0, 0, 0, 0.0 + 1.0*I]

>>> c = Circuit().push(GateCS(), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CS @ q[0], q[1]

>>> GateCS().power(2), GateCS().inverse()
(CZ, CS†)
>>> GateCS().decompose()
2-qubit circuit with 1 instructions:
└── CP((1/2)*pi) @ q[0], q[1]
class mimiqcircuits.GateCSDG[source]#

Bases: Control

Adjoint of two qubit Controlled-S gate.

By convention, the first qubit is the control and the second is the target

Matrix representation:

\[\begin{split}\operatorname{CS}^{\dagger} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & -i \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateCSDG(), GateCSDG().num_controls, GateCSDG().num_targets, GateCSDG().num_qubits
(CS†, 1, 1, 2)
>>> GateCSDG().matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, 1.0, 0]
[0, 0, 0, 6.12323399573677e-17 - 1.0*I]

>>> c = Circuit().push(GateCSDG(), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CS† @ q[0], q[1]

>>> GateCSDG().power(2), GateCSDG().inverse()
(C(S†**2), CS)
>>> GateCSDG().decompose()
2-qubit circuit with 1 instructions:
└── CP((-1/2)*pi) @ q[0], q[1]
class mimiqcircuits.GateCSWAP[source]#

Bases: Control

Three qubit Controlled-SWAP gate.

By convention, the first qubit is the control and last two are the targets.

Examples

>>> from mimiqcircuits import *
>>> GateCSWAP(), GateCSWAP().num_controls, GateCSWAP().num_targets, GateCSWAP().num_qubits
(CSWAP, 1, 2, 3)
>>> GateCSWAP().matrix()
[1.0, 0, 0, 0, 0, 0, 0, 0]
[0, 1.0, 0, 0, 0, 0, 0, 0]
[0, 0, 1.0, 0, 0, 0, 0, 0]
[0, 0, 0, 1.0, 0, 0, 0, 0]
[0, 0, 0, 0, 1.0, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 1.0, 0]
[0, 0, 0, 0, 0, 1.0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1.0]

>>> c = Circuit().push(GateCSWAP(), 0, 1, 2)
>>> GateCSWAP().power(2), GateCSWAP().inverse()
(C(Parallel(2, ID)), CSWAP)
>>> c = Circuit().push(GateCSWAP(), 0, 1, 2)
>>> c
3-qubit circuit with 1 instructions:
└── CSWAP @ q[0], q[1,2]

>>> GateCSWAP().power(2), GateCSWAP().inverse()
(C(Parallel(2, ID)), CSWAP)
>>> GateCSWAP().decompose()
3-qubit circuit with 3 instructions:
├── CX @ q[2], q[1]
├── C₂X @ q[0,1], q[2]
└── CX @ q[2], q[1]
class mimiqcircuits.GateCSX[source]#

Bases: Control

Two qubit Controled-SX gate.

By convention, the first qubit is the control and second one is the targets.

Matrix representation:

\[\begin{split}\operatorname{CSX} =\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \frac{1+i}{2} & \frac{1-i}{2} \\ 0 & 0 & \frac{1-i}{2} & \frac{1+i}{2} \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateCSX(), GateCSX().num_controls, GateCSX().num_targets, GateCSX().num_qubits
(CSX, 1, 1, 2)
>>> GateCSX().matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, 0.5 + 0.5*I, 0.5 - 0.5*I]
[0, 0, 0.5 - 0.5*I, 0.5 + 0.5*I]

>>> c = Circuit().push(GateCSX(), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CSX @ q[0], q[1]

>>> GateCSX().power(2), GateCSX().inverse()
(CX, CSX†)
>>> GateCSX().decompose()
2-qubit circuit with 3 instructions:
├── H @ q[1]
├── CU1((1/2)*pi) @ q[0], q[1]
└── H @ q[1]
class mimiqcircuits.GateCSXDG[source]#

Bases: Control

Two qubit \({CSX}^\dagger\) gate.

Matrix representation:

\[\begin{split}\operatorname{CSX}^{\dagger} =\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & \frac{1-i}{2} & \frac{1+i}{2} \\ 0 & 0 & \frac{1+i}{2} & \frac{1-i}{2} \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateCSXDG(), GateCSXDG().num_controls, GateCSXDG().num_targets, GateCSXDG().num_qubits
(CSX†, 1, 1, 2)
>>> GateCSXDG().matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, 0.5 - 0.5*I, 0.5 + 0.5*I]
[0, 0, 0.5 + 0.5*I, 0.5 - 0.5*I]

>>> c = Circuit().push(GateCSXDG(), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CSX† @ q[0], q[1]

>>> GateCSXDG().power(2), GateCSXDG().inverse()
(C(SX†**2), CSX)
>>> GateCSXDG().decompose()
2-qubit circuit with 3 instructions:
├── H @ q[1]
├── CU1((-1/2)*pi) @ q[0], q[1]
└── H @ q[1]
class mimiqcircuits.GateCU(*args, **kwargs)[source]#

Bases: Control

Two qubit controlled unitary gate.

Matrix representation:

\[\begin{split}\operatorname{CU}(\theta, \phi, \lambda, \gamma) = \frac{1}{2} e^{i\gamma} \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & e^{i\gamma} \cos\left(\frac{\theta}{2}\right) & -e^{i\gamma} e^{i\lambda}\sin\left(\frac{\theta}{2}\right) \\ 0 & 0 & e^{i\gamma} \mathrm{e}^{i\phi}\sin\left(\frac{\theta}{2}\right) & e^{i\gamma} \mathrm{e}^{i(\phi+\lambda)}\cos\left(\frac{\theta}{2}\right) \end{pmatrix}\end{split}\]
Parameters:
  • theta (float) – Euler angle 1 in radians.

  • phi (float) – Euler angle 2 in radians.

  • lmbda (float) – Euler angle 3 in radians.

  • gamma (float) – Global phase of the CU gate.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta, phi, lmbda, gamma = symbols('theta phi lambda gamma')
>>> GateCU(theta, phi, lmbda, gamma), GateCU(theta, phi, lmbda, gamma).num_controls, GateCU(theta, phi, lmbda, gamma).num_targets, GateCU(theta, phi, lmbda, gamma).num_qubits
(CU(theta, phi, lambda, gamma), 1, 1, 2)
>>> GateCU(theta, phi, lmbda, gamma).matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, exp(I*gamma)*cos((1/2)*theta), -exp(I*(gamma + lambda))*sin((1/2)*theta)]
[0, 0, exp(I*(gamma + phi))*sin((1/2)*theta), exp(I*(gamma + lambda + phi))*cos((1/2)*theta)]

>>> c = Circuit().push(GateCU(theta, phi, lmbda, gamma), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CU(theta, phi, lambda, gamma) @ q[0], q[1]

>>> GateCU(theta, phi, lmbda, gamma).power(2), GateCU(theta, phi, lmbda, gamma).inverse()
(C(U(theta, phi, lambda, gamma)**2), CU(-theta, -lambda, -phi, -gamma))
>>> GateCU(theta, phi, lmbda, gamma).decompose()
2-qubit circuit with 7 instructions:
├── P(gamma) @ q[0]
├── P((1/2)*(lambda + phi)) @ q[0]
├── P((1/2)*(lambda - phi)) @ q[1]
├── CX @ q[0], q[1]
├── U((-1/2)*theta, 0, (-1/2)*(lambda + phi), 0.0) @ q[1]
├── CX @ q[0], q[1]
└── U((1/2)*theta, phi, 0, 0.0) @ q[1]
class mimiqcircuits.GateCX[source]#

Bases: Control

Two qubit Controlled-X gate (or CNOT).

By convention, the first qubit is the control and the second is the target

Matrix representation:

\[\begin{split}\operatorname{CX} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateCX(), GateCX().num_controls, GateCX().num_targets
(CX, 1, 1)
>>> GateCX().matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, 0, 1.0]
[0, 0, 1.0, 0]

>>> c = Circuit().push(GateCX(), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CX @ q[0], q[1]

>>> GateCX().power(2), GateCX().inverse()
(CID, CX)
>>> GateCX().decompose()
2-qubit circuit with 1 instructions:
└── CX @ q[0], q[1]
class mimiqcircuits.GateCY[source]#

Bases: Control

Two qubit Controlled-Y gate.

By convention, the first qubit is the control and the second is the target

Matrix representation:

\[\begin{split}\operatorname{CY} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & -i \\ 0 & 0 & i & 0 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateCY(), GateCY().num_controls, GateCY().num_targets
(CY, 1, 1)
>>> GateCY().matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, 0, -0.0 - 1.0*I]
[0, 0, 0.0 + 1.0*I, 0]

>>> c = Circuit().push(GateCY(), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CY @ q[0], q[1]

>>> GateCY().power(2), GateCY().inverse()
(CID, CY)
>>> GateCY().decompose()
2-qubit circuit with 3 instructions:
├── S† @ q[1]
├── CX @ q[0], q[1]
└── S @ q[1]
class mimiqcircuits.GateCZ[source]#

Bases: Control

Two qubit Controlled-Z gate.

By convention, the first qubit is the control and the second is the target

Matrix representation:

\[\begin{split}\operatorname{CZ} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & -1 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateCZ(), GateCZ().num_controls, GateCZ().num_targets
(CZ, 1, 1)
>>> GateCZ().matrix()
[1.0, 0, 0, 0]
[0, 1.0, 0, 0]
[0, 0, 1.0, 0]
[0, 0, 0, -1.0]

>>> c = Circuit().push(GateCZ(), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── CZ @ q[0], q[1]

>>> GateCZ().power(2), GateCZ().inverse()
(CID, CZ)
>>> GateCZ().decompose()
2-qubit circuit with 3 instructions:
├── H @ q[1]
├── CX @ q[0], q[1]
└── H @ q[1]
class mimiqcircuits.GateCall(decl: GateDecl, args: Tuple[float, ...])[source]#

Bases: Gate

evaluate(d)[source]#
class mimiqcircuits.GateCustom(matrix)[source]#

Bases: Gate

One or Two qubit Custom gates.

Examples

>>> from mimiqcircuits import Circuit, GateCustom
>>> import numpy as np
>>> matrix = np.array([[1, 0, 0, 0],
...                    [0, 1, 0, 0],
...                    [0, 0, 0, -1j],
...                    [0, 0, 1j, 0]])
>>> c = Circuit()
>>> c.push(GateCustom(matrix), 0, 1)
2-qubit circuit with 1 instructions:
└── Custom([[1.0 + 0.0*I, 0.0 + 0.0*I, 0.0 + 0.0*I, 0.0 + 0.0*I], [0.0 + 0.0*I, 1.0 + 0.0*I, 0.0 + 0.0*I, 0.0 + 0.0*I], [0.0 + 0.0*I, 0.0 + 0.0*I, 0.0 + 0.0*I, -0.0 - 1.0*I], [0.0 + 0.0*I, 0.0 + 0.0*I, 0.0 + 1.0*I, 0.0 + 0.0*I]]) @ q[0,1]
evaluate(d)[source]#
inverse()[source]#
static is_unitary(matrix, tol=1e-08)[source]#
property num_qubits#
class mimiqcircuits.GateDCX[source]#

Bases: Gate

Two qubit double-CNOT gate.

A two qubit Clifford gate consisting of two back-to-back CNOTs with alternate controls.

Matrix representation:

\[\begin{split}\operatorname{DCX} =\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 1 & 0 & 0 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateDCX()
DCX
>>> GateDCX().matrix()
[1.0, 0, 0, 0]
[0, 0, 1.0, 0]
[0, 0, 0, 1.0]
[0, 1.0, 0, 0]

>>> c = Circuit().push(GateDCX(), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── DCX @ q[0,1]

>>> GateDCX().power(2), GateDCX().inverse()
(DCX†, DCX†)
>>> GateDCX().decompose()
2-qubit circuit with 2 instructions:
├── CX @ q[0], q[1]
└── CX @ q[1], q[0]
class mimiqcircuits.GateDecl(name: str, arguments: Tuple[str, ...], instructions: List[Instruction])[source]#

Bases: object

Simple declaration of gates using the @gatedecl decorator.

Examples

First way

>>> from symengine import symbols
>>> from mimiqcircuits import *

Define symbols for the gate arguments

>>> x, y = symbols('x y')

Declare a gate using the @gatedecl decorator

>>> @gatedecl("ansatz")
... def ansatz(x):
...     insts = [
...         Instruction(GateX(), (1,)),
...         Instruction(GateRX(x), (2,))
...     ]
...     return insts

Create a GateDecl object using the decorator

>>> ansatz(x)
gate ansatz(x) =
├── X @ q[1]
└── RX(x) @ q[2]
>>> ansatz(y)
gate ansatz(y) =
├── X @ q[1]
└── RX(y) @ q[2]

Decompose the GateCall into a quantum circuit

>>> GateCall(ansatz(x), (1.57,)).decompose()
3-qubit circuit with 2 instructions:
├── X @ q[1]
└── RX(1.57) @ q[2]
>>> GateCall(ansatz(y), (1.57,)).decompose()
3-qubit circuit with 2 instructions:
├── X @ q[1]
└── RX(1.57) @ q[2]

Second Way

>>> from symengine import *
>>> from mimiqcircuits import *

Define symbols for the gate arguments

>>> x, y = symbols('x y')

Create a GateDecl object using the GateDecl class

>>> gate_decl = GateDecl("ansatz", ('x','y'), [Instruction(GateXXplusYY(x,y), (1,2)), Instruction(GateRX(x),(2,))])
>>> GateCall(gate_decl, (2,4))
ansatz(2, 4)

Decompose the GateCall into a quantum circuit

>>> GateCall(gate_decl, (2,4)).decompose()
3-qubit circuit with 2 instructions:
├── XXplusYY(2, 4) @ q[1,2]
└── RX(2) @ q[2]

Add to Circuit

>>> g = GateCall(gate_decl, (2,4))
>>> c = Circuit()
>>> c.push(g,10,22)
23-qubit circuit with 1 instructions:
└── ansatz(2, 4) @ q[10,22]
class mimiqcircuits.GateECR[source]#

Bases: Gate

Two qubit ECR (echo) gate.

Matrix representation:

\[\begin{split}\operatorname{ECR} =\begin{pmatrix} 0 & \frac{1}{\sqrt{2}} & 0 & \frac{i}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} & 0 & \frac{-i}{\sqrt{2}} & 0 \\ 0 & \frac{i}{\sqrt{2}} & 0 & \frac{1}{\sqrt{2}} \\ \frac{-i}{\sqrt{2}} & 0 & \frac{1}{\sqrt{2}} & 0 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateECR()
ECR
>>> GateECR().matrix()
[0, 0, 0.707106781186548, 0.0 + 0.707106781186548*I]
[0, 0, 0.0 + 0.707106781186548*I, 0.707106781186548]
[0.707106781186548, -0.0 - 0.707106781186548*I, 0, 0]
[-0.0 - 0.707106781186548*I, 0.707106781186548, 0, 0]

>>> c = Circuit().push(GateECR(), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── ECR @ q[0,1]

>>> GateECR().power(2), GateECR().inverse()
(Parallel(2, ID), ECR)
>>> GateECR().decompose()
2-qubit circuit with 3 instructions:
├── RZX((1/4)*pi) @ q[0,1]
├── X @ q[0]
└── RZX((-1/4)*pi) @ q[0,1]
inverse()[source]#
class mimiqcircuits.GateH[source]#

Bases: Gate

Single qubit Hadamard gate.

Matrix representation:

\[\begin{split}\operatorname{H} = \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateH()
H
>>> GateH().matrix()
[0.707106781186548, 0.707106781186548]
[0.707106781186548, -0.707106781186548]

>>> c = Circuit().push(GateH(), 0)
>>> c
1-qubit circuit with 1 instructions:
└── H @ q[0]

>>> GateH().power(2), GateH().inverse()
(ID, H)
>>> GateH().decompose()
1-qubit circuit with 1 instructions:
└── U((1/2)*pi, 0, pi, 0.0) @ q[0]
inverse()[source]#
class mimiqcircuits.GateID[source]#

Bases: Gate

Single qubit Identity gate.

Matrix representation:

\[\begin{split}\operatorname{ID} = \begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateID()
ID
>>> GateID().matrix()
[1.0, 0]
[0, 1.0]

>>> c = Circuit().push(GateID(), 0)
>>> c
1-qubit circuit with 1 instructions:
└── ID @ q[0]

>>> GateID().power(2), GateID().inverse()
(ID, ID)
>>> GateID().decompose()
1-qubit circuit with 1 instructions:
└── U(0, 0, 0, 0.0) @ q[0]
inverse()[source]#
class mimiqcircuits.GateISWAP[source]#

Bases: Gate

Two qubit ISWAP gate.

See Also GateISWAPDG() and GateSWAP()

Matrix representation:

\[\begin{split}\operatorname{ISWAP} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & i & 0 \\ 0 & i & 0 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateISWAP()
ISWAP
>>> GateISWAP().matrix()
[1.0, 0, 0, 0]
[0, 0, 0.0 + 1.0*I, 0]
[0, 0.0 + 1.0*I, 0, 0]
[0, 0, 0, 1.0]

>>> c = Circuit().push(GateISWAP(), 0, 1)
>>> GateISWAP().power(2), GateISWAP().inverse()
(ISWAP**2, ISWAP†)
>>> GateISWAP().decompose()
2-qubit circuit with 6 instructions:
├── S @ q[0]
├── S @ q[1]
├── H @ q[0]
├── CX @ q[0], q[1]
├── CX @ q[1], q[0]
└── H @ q[1]
class mimiqcircuits.GateP(lmbda)[source]#

Bases: Gate

Single qubit Phase gate.

Matrix representation:

\[\begin{split}\operatorname{P}(\lambda) = \operatorname{U}(0,0,\lambda) = \begin{pmatrix} 1 & 0 \\ 0 & \mathrm{e}^{i\lambda} \end{pmatrix}\end{split}\]
Parameters:

lambda – Phase angle

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> lmbda = Symbol('lambda')
>>> GateP(lmbda)
P(lambda)
>>> GateP(lmbda).matrix()
[1.0, 0]
[0, exp(I*lambda)]

>>> c = Circuit().push(GateP(lmbda), 0)
>>> c
1-qubit circuit with 1 instructions:
└── P(lambda) @ q[0]

>>> GateP(lmbda).power(2), GateP(lmbda).inverse()
(P(2*lambda), P(-lambda))
>>> GateP(lmbda).decompose()
1-qubit circuit with 1 instructions:
└── U(0, 0, lambda, 0.0) @ q[0]
inverse()[source]#
class mimiqcircuits.GateR(theta, phi)[source]#

Bases: Gate

Single qubit Rotation gate around the axis \(\cos(\phi)\hat{x} + \sin(\phi)\hat{y}\).

Matrix representation:

\[\begin{split}\operatorname R(\theta,\phi) = \begin{pmatrix} \cos \frac{\theta}{2} & -i e^{-i\phi} \sin \frac{\theta}{2} \\ -i e^{i \phi} \sin \frac{\theta}{2} & \cos \frac{\theta}{2} \end{pmatrix}\end{split}\]
Parameters:
  • theta (float) – The rotation angle in radians.

  • phi (float) – The axis of rotation in radians.

Example

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta, phi = symbols('theta phi')
>>> GateR(theta, phi)
R(theta, phi)
>>> GateR(theta, phi).matrix()
[cos((1/2)*theta), -I*exp(-I*phi)*sin((1/2)*theta)]
[-I*exp(I*phi)*sin((1/2)*theta), cos((1/2)*theta)]

>>> c = Circuit().push(GateR(theta, phi), 0)
>>> GateR(theta, phi).power(2), GateR(theta, phi).inverse()
(R(2*theta, phi), R(-theta, phi))
>>> GateR(theta, phi).decompose()
1-qubit circuit with 1 instructions:
└── U3(theta, phi + (-1/2)*pi, -phi + (1/2)*pi) @ q[0]
inverse()[source]#
class mimiqcircuits.GateRX(theta)[source]#

Bases: Gate

Single qubit Rotation gate around the axis \(\hat{x}\)

Matrix representation:

\[\begin{split}\operatorname{RX}(\theta) = \begin{pmatrix} \cos\frac{\theta}{2} & -i\sin\frac{\theta}{2} \\ -i\sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{pmatrix}\end{split}\]
Parameters:

theta – Rotation angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta = Symbol('theta')
>>> GateRX(theta)
RX(theta)
>>> GateRX(theta).matrix()
[cos((1/2)*theta), -I*sin((1/2)*theta)]
[-I*sin((1/2)*theta), cos((1/2)*theta)]

>>> c = Circuit().push(GateRX(theta), 0)
>>> c
1-qubit circuit with 1 instructions:
└── RX(theta) @ q[0]

>>> GateRX(theta).power(2), GateRX(theta).inverse()
(RX(2*theta), RX(-theta))
>>> GateRX(theta).decompose()
1-qubit circuit with 1 instructions:
└── U(theta, (-1/2)*pi, (1/2)*pi, 0.0) @ q[0]
inverse()[source]#
class mimiqcircuits.GateRXX(theta)[source]#

Bases: Gate

Two qubit RXX gate (rotation about XX).

This gate is symmetric, and is maximally entangling at \((\theta = \frac{\pi}{2})\)

Matrix representation:

\[\begin{split}\operatorname{RXX}(\theta) =\begin{pmatrix} \cos(\frac{\theta}{2}) & 0 & 0 & -i\sin(\frac{\theta}{2}) \\ 0 & \cos(\frac{\theta}{2}) & -i\sin(\frac{\theta}{2}) & 0 \\ 0 & -i\sin(\frac{\theta}{2}) & \cos(\frac{\theta}{2}) & 0 \\ -i\sin(\frac{\theta}{2}) & 0 & 0 & \cos(\frac{\theta}{2}) \end{pmatrix}\end{split}\]
Parameters:

theta – The angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta = Symbol('theta')
>>> GateRXX(theta)
RXX(theta)
>>> c = Circuit()
>>> c.push(GateRXX(theta), 0, 1)
2-qubit circuit with 1 instructions:
└── RXX(theta) @ q[0,1]

>>> GateRXX(theta).power(2), GateRXX(theta).inverse()
(RXX(theta)**2, RXX(-theta))
>>> GateRXX(theta).matrix()
[cos((1/2)*theta), 0, 0, -I*sin((1/2)*theta)]
[0, cos((1/2)*theta), -I*sin((1/2)*theta), 0]
[0, -I*sin((1/2)*theta), cos((1/2)*theta), 0]
[-I*sin((1/2)*theta), 0, 0, cos((1/2)*theta)]

>>> GateRXX(theta).decompose()
2-qubit circuit with 7 instructions:
├── H @ q[0]
├── H @ q[1]
├── CX @ q[0], q[1]
├── RZ(theta) @ q[1]
├── CX @ q[0], q[1]
├── H @ q[1]
└── H @ q[0]
inverse()[source]#
class mimiqcircuits.GateRY(theta)[source]#

Bases: Gate

Single qubit Rotation gate around the axis \(\hat{y}\)

Matrix representation:

\[\begin{split}\operatorname{RY}(\theta) = \begin{pmatrix} \cos\frac{\theta}{2} & -\sin\frac{\theta}{2} \\ \sin\frac{\theta}{2} & \cos\frac{\theta}{2} \end{pmatrix}\end{split}\]
Parameters:

theta (float) – Rotation angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta = Symbol('theta')
>>> GateRY(theta)
RY(theta)
>>> GateRY(theta).matrix()
[cos((1/2)*theta), -sin((1/2)*theta)]
[sin((1/2)*theta), cos((1/2)*theta)]

>>> c = Circuit().push(GateRY(theta), 0)
>>> c
1-qubit circuit with 1 instructions:
└── RY(theta) @ q[0]

>>> GateRY(theta).power(2), GateRY(theta).inverse()
(RY(2*theta), RY(-theta))
>>> GateRY(theta).decompose()
1-qubit circuit with 1 instructions:
└── U(theta, 0, 0, 0.0) @ q[0]
inverse()[source]#
class mimiqcircuits.GateRYY(theta)[source]#

Bases: Gate

Two qubit RYY gate (rotation about YY).

This gate is symmetric, and is maximally entangling at \((\theta = \frac{\pi}{2})\)

Matrix representation:

\[\begin{split}\operatorname{RYY}(\theta) =\begin{pmatrix} \cos(\frac{\theta}{2}) & 0 & 0 & i\sin(\frac{\theta}{2}) \\ 0 & \cos(\frac{\theta}{2}) & -i\sin(\frac{\theta}{2}) & 0 \\ 0 & -i\sin(\frac{\theta}{2}) & \cos(\frac{\theta}{2}) & 0 \\ i\sin(\frac{\theta}{2}) & 0 & 0 & \cos(\frac{\theta}{2}) \end{pmatrix}\end{split}\]
Parameters:

theta (float) – The angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta = Symbol('theta')
>>> GateRYY(theta)
RYY(theta)
>>> GateRYY(theta).matrix()
[cos((1/2)*theta), 0, 0, I*sin((1/2)*theta)]
[0, cos((1/2)*theta), -I*sin((1/2)*theta), 0]
[0, -I*sin((1/2)*theta), cos((1/2)*theta), 0]
[I*sin((1/2)*theta), 0, 0, cos((1/2)*theta)]

>>> c = Circuit().push(GateRYY(theta), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── RYY(theta) @ q[0,1]

>>> GateRYY(theta).power(2), GateRYY(theta).inverse()
(RYY(theta)**2, RYY(-theta))
>>> GateRYY(theta).decompose()
2-qubit circuit with 7 instructions:
├── RX((1/2)*pi) @ q[0]
├── RX((1/2)*pi) @ q[1]
├── CX @ q[0], q[1]
├── RZ(theta) @ q[1]
├── CX @ q[0], q[1]
├── RX((-1/2)*pi) @ q[0]
└── RX((-1/2)*pi) @ q[1]
inverse()[source]#
class mimiqcircuits.GateRZ(lmbda)[source]#

Bases: Gate

Single qubit Rotation gate around the axis \(\hat{z}\)

Matrix representation:

\[\begin{split}\operatorname{RZ}(\lambda) = \begin{pmatrix} e^{-i\frac{\lambda}{2}} & 0 \\ 0 & e^{i\frac{\lambda}{2}} \end{pmatrix}\end{split}\]
Parameters:

lambda – Rotation angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> lmbda = Symbol('lambda')
>>> GateRZ(lmbda)
RZ(lambda)
>>> GateRZ(lmbda).matrix()
[exp(-1/2*I*lambda), 0]
[0, exp(1/2*I*lambda)]

>>> c = Circuit().push(GateRZ(lmbda), 0)
>>> c
1-qubit circuit with 1 instructions:
└── RZ(lambda) @ q[0]

>>> GateRZ(lmbda).power(2), GateRZ(lmbda).inverse()
(RZ(2*lambda), RZ(-lambda))
>>> GateRZ(lmbda).decompose()
1-qubit circuit with 1 instructions:
└── U(0, 0, lambda, (-1/2)*lambda) @ q[0]
inverse()[source]#
class mimiqcircuits.GateRZX(theta)[source]#

Bases: Gate

Two qubit RZX gate.

This gate is maximally entangling at \((\theta = \frac{\pi}{2})\)

Matrix representation:

\[\begin{split}\operatorname{RZX}(\theta) =\begin{pmatrix} \cos(\frac{\theta}{2}) & -i\sin(\frac{\theta}{2}) & 0 & 0 \\ -i\sin(\frac{\theta}{2}) & \cos(\frac{\theta}{2}) & 0 & 0 \\ 0 & 0 & \cos(\frac{\theta}{2}) & i\sin(\frac{\theta}{2}) \\ 0 & 0 & i\sin(\frac{\theta}{2}) & \cos(\frac{\theta}{2}) \end{pmatrix}\end{split}\]
Parameters:

theta (float) – The angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta = Symbol('theta')
>>> GateRZX(theta)
RZX(theta)
>>> GateRZX(theta).matrix()
[cos((1/2)*theta), -I*sin((1/2)*theta), 0, 0]
[-I*sin((1/2)*theta), cos((1/2)*theta), 0, 0]
[0, 0, cos((1/2)*theta), I*sin((1/2)*theta)]
[0, 0, I*sin((1/2)*theta), cos((1/2)*theta)]

>>> c = Circuit().push(GateRZX(theta), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── RZX(theta) @ q[0,1]

>>> GateRZX(theta).power(2), GateRZX(theta).inverse()
(RZX(theta)**2, RZX(-theta))
>>> GateRZX(theta).decompose()
2-qubit circuit with 5 instructions:
├── H @ q[1]
├── CX @ q[0], q[1]
├── RZ(theta) @ q[1]
├── CX @ q[0], q[1]
└── H @ q[1]
inverse()[source]#
class mimiqcircuits.GateRZZ(theta)[source]#

Bases: Gate

Two qubit RZZ gate (rotation about ZZ)..

This gate is symmetric, and is maximally entangling at \((\theta = \frac{\pi}{2})\)

Matrix representation:

\[\begin{split}\operatorname{RZZ}(\theta) = \begin{pmatrix} e^{-i\frac{\theta}{2}} & 0 & 0 & 0 \\ 0 & e^{i\frac{\theta}{2}} & 0 & 0 \\ 0 & 0 & e^{i\frac{\theta}{2}} & 0 \\ 0 & 0 & 0 & e^{-i\frac{\theta}{2}} \end{pmatrix}\end{split}\]
Parameters:

theta (float) – The angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta = Symbol('theta')
>>> GateRZZ(theta)
RZZ(theta)
>>> GateRZZ(theta).matrix()
[exp(-1/2*I*theta), 0, 0, 0]
[0, exp(1/2*I*theta), 0, 0]
[0, 0, exp(1/2*I*theta), 0]
[0, 0, 0, exp(-1/2*I*theta)]

>>> c = Circuit().push(GateRZZ(theta), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── RZZ(theta) @ q[0,1]

>>> GateRZZ(theta).power(2), GateRZZ(theta).inverse()
(RZZ(theta)**2, RZZ(-theta))
>>> GateRZZ(theta).decompose()
2-qubit circuit with 3 instructions:
├── CX @ q[0], q[1]
├── RZ(theta) @ q[1]
└── CX @ q[0], q[1]
inverse()[source]#
class mimiqcircuits.GateS[source]#

Bases: Power

Single qubit gate S.

It induces a \(\frac{\pi}{2}\) phase gate.

Matrix representation:

\[\begin{split}\operatorname{S} = \begin{pmatrix} 1 & 0 \\ 0 & i \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateS()
S
>>> GateS().matrix()
[1.0, 0]
[0, 0.0 + 1.0*I]

>>> c = Circuit().push(GateS(), 0)
>>> c
1-qubit circuit with 1 instructions:
└── S @ q[0]

>>> GateS().power(2), GateS().inverse()
(Z, S†)
>>> GateS().decompose()
1-qubit circuit with 1 instructions:
└── U(0, 0, (1/2)*pi, 0.0) @ q[0]
inverse()[source]#
isopalias()[source]#
class mimiqcircuits.GateSDG[source]#

Bases: Inverse

Single qubit S-dagger gate (conjugate transpose of the S gate).

Matrix representation:

\[\begin{split}\operatorname{S}^\dagger = \begin{pmatrix} 1 & 0 \\ 0 & -i \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateSDG()
S†
>>> GateSDG().matrix()
[1.0, 0]
[0, 6.12323399573677e-17 - 1.0*I]

>>> c = Circuit().push(GateSDG(), 0)
>>> c
1-qubit circuit with 1 instructions:
└── S† @ q[0]

>>> GateSDG().power(2), GateSDG().inverse()
(S†**2, S)
>>> GateSDG().decompose()
1-qubit circuit with 1 instructions:
└── U(0, 0, (-1/2)*pi, 0.0) @ q[0]
inverse()[source]#
isopalias()[source]#
class mimiqcircuits.GateSWAP[source]#

Bases: Gate

Two qubit SWAP gate.

See Also GateISWAP()

Matrix representation:

\[\begin{split}\operatorname{SWAP} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateSWAP()
SWAP
>>> GateSWAP().matrix()
[1.0, 0, 0, 0]
[0, 0, 1.0, 0]
[0, 1.0, 0, 0]
[0, 0, 0, 1.0]

>>> c = Circuit().push(GateSWAP(), 0, 1)
>>> GateSWAP().power(2), GateSWAP().inverse()
(Parallel(2, ID), SWAP)
>>> GateSWAP().decompose()
2-qubit circuit with 3 instructions:
├── CX @ q[0], q[1]
├── CX @ q[1], q[0]
└── CX @ q[0], q[1]
inverse()[source]#
class mimiqcircuits.GateSX[source]#

Bases: Power

Single qubit \(\sqrt{X}\) gate.

Matrix representation:

\[\begin{split}\sqrt{\operatorname{X}} = \frac{1}{2} \begin{pmatrix} 1+i & 1-i \\ 1-i & 1+i\\ \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateSX()
SX
>>> GateSX().matrix()
[0.5 + 0.5*I, 0.5 - 0.5*I]
[0.5 - 0.5*I, 0.5 + 0.5*I]

>>> c = Circuit().push(GateSX(), 0)
>>> c
1-qubit circuit with 1 instructions:
└── SX @ q[0]

>>> GateSX().power(2), GateSX().inverse()
(X, SX†)
>>> GateSX().decompose()
1-qubit circuit with 4 instructions:
├── S† @ q[0]
├── H @ q[0]
├── S† @ q[0]
└── U(0, 0, 0, (1/4)*pi) @ q[0]
inverse()[source]#
isopalias()[source]#
name = 'SX'#
class mimiqcircuits.GateSXDG[source]#

Bases: Inverse

Single qubit \(\sqrt{X}^\dagger\) gate (conjugate transpose of the \(\sqrt{X}\) gate).

Matrix representation:

\[\begin{split}\sqrt{\operatorname{X}}^\dagger = \frac{1}{2} \begin{pmatrix} 1-i & 1+i \\ 1+i & 1-i\\ \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateSXDG()
SX†
>>> GateSXDG().matrix()
[0.5 - 0.5*I, 0.5 + 0.5*I]
[0.5 + 0.5*I, 0.5 - 0.5*I]

>>> c = Circuit().push(GateSXDG(), 0)
>>> c
1-qubit circuit with 1 instructions:
└── SX† @ q[0]

>>> GateSXDG().power(2), GateSXDG().inverse()
(SX†**2, SX)
>>> GateSXDG().decompose()
1-qubit circuit with 4 instructions:
├── S @ q[0]
├── H @ q[0]
├── S @ q[0]
└── U(0, 0, 0, (-1/4)*pi) @ q[0]
inverse()[source]#
isopalias()[source]#
class mimiqcircuits.GateT[source]#

Bases: Power

Single qubit T gate.

Matrix representation:

\[\begin{split}\operatorname{T} = \begin{pmatrix} 1 & 0 \\ 0 & \exp\left(\frac{i\pi}{4}\right) \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateT()
T
>>> GateT().matrix()
[1.0, 0]
[0, 0.707106781186548 + 0.707106781186548*I]

>>> c = Circuit().push(GateT(), 0)
>>> c
1-qubit circuit with 1 instructions:
└── T @ q[0]

>>> GateT().power(2), GateT().inverse()
(S, T†)
>>> GateT().decompose()
1-qubit circuit with 1 instructions:
└── U(0, 0, (1/4)*pi, 0.0) @ q[0]
inverse()[source]#
isopalias()[source]#
class mimiqcircuits.GateTDG[source]#

Bases: Inverse

Single qubit T-dagger gate (conjugate transpose of the T gate).

Matrix representation:

\[\begin{split}\operatorname{T}^\dagger = \begin{pmatrix} 1 & 0 \\ 0 & \exp\left(\frac{-i\pi}{4}\right) \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateTDG()
T†
>>> GateTDG().matrix()
[1.0, 0]
[0, 0.707106781186547 - 0.707106781186547*I]

>>> c = Circuit().push(GateTDG(), 0)
>>> c
1-qubit circuit with 1 instructions:
└── T† @ q[0]

>>> GateTDG().power(2), GateTDG().inverse()
(T†**2, T)
>>> GateTDG().decompose()
1-qubit circuit with 1 instructions:
└── U(0, 0, (-1/4)*pi, 0.0) @ q[0]
inverse()[source]#
isopalias()[source]#
class mimiqcircuits.GateU(theta, phi, lmbda, gamma=0.0)[source]#

Bases: Gate

Single qubit generic unitary phase gate.

Matrix representation:

\[\begin{split}\operatorname{U}(\theta, \phi, \lambda, \gamma) = \frac{1}{2} \mathrm{e}^{i\gamma} \begin{pmatrix} \cos\left(\frac{\theta}{2}\right) & -\mathrm{e}^{i\lambda}\sin\left(\frac{\theta}{2}\right)\\ \mathrm{e}^{i\phi}\sin\left(\frac{\theta}{2}\right) & \mathrm{e}^{i(\phi+\lambda)}\cos\left (\frac{\theta}{2}\right) \end{pmatrix}\end{split}\]
Parameters:
  • theta (float) – Euler angle 1 in radians.

  • phi (float) – Euler angle 2 in radians.

  • lambda (float) – Euler angle 3 in radians.

  • gamma (float, optional) – Euler angle 4 in radians (default is 0).

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta, phi, lmbda, gamma = symbols('theta phi lambda gamma')
>>> GateU(theta, phi, lmbda, gamma)
U(theta, phi, lambda, gamma)
>>> GateU(theta, phi, lmbda, gamma).matrix()
[exp(I*gamma)*cos((1/2)*theta), -exp(I*(gamma + lambda))*sin((1/2)*theta)]
[exp(I*(gamma + phi))*sin((1/2)*theta), exp(I*(gamma + lambda + phi))*cos((1/2)*theta)]

>>> c = Circuit().push(GateU(theta, phi, lmbda, gamma), 0)
>>> c
1-qubit circuit with 1 instructions:
└── U(theta, phi, lambda, gamma) @ q[0]

>>> GateU(theta, phi, lmbda, gamma).power(2), GateU(theta, phi, lmbda, gamma).inverse()
(U(theta, phi, lambda, gamma)**2, U(-theta, -lambda, -phi, -gamma))
>>> GateU(theta, phi, lmbda, gamma).decompose()
1-qubit circuit with 1 instructions:
└── U(theta, phi, lambda, gamma) @ q[0]

>>> c = Circuit().push(GateU(theta, phi, lmbda, gamma), 0)
>>> c
1-qubit circuit with 1 instructions:
└── U(theta, phi, lambda, gamma) @ q[0]

>>> GateU(theta, phi, lmbda, gamma).power(2), GateU(theta, phi, lmbda, gamma).inverse()
(U(theta, phi, lambda, gamma)**2, U(-theta, -lambda, -phi, -gamma))
>>> GateU(theta, phi, lmbda, gamma).decompose()
1-qubit circuit with 1 instructions:
└── U(theta, phi, lambda, gamma) @ q[0]
inverse()[source]#
class mimiqcircuits.GateU1(lmbda)[source]#

Bases: Gate

Single qubit generic unitary gate \({U_1}\).

Equivalent to GateP()

Matrix representation:

\[\begin{split}\operatorname{U1}(\lambda) = \begin{pmatrix} 1 & 0 \\ 0 & e^{i\lambda} \end{pmatrix}\end{split}\]
Parameters:

lambda (float) – Euler angle 3 in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> lmbda = Symbol('lambda')
>>> GateU1(lmbda)
U1(lambda)
>>> GateU1(lmbda).matrix()
[1.0, 0]
[0, exp(I*lambda)]

>>> c = Circuit().push(GateU1(lmbda), 0)
>>> c
1-qubit circuit with 1 instructions:
└── U1(lambda) @ q[0]

>>> GateU1(lmbda).power(2), GateU1(lmbda).inverse()
(U1(2*lambda), U1(-lambda))
>>> GateU1(lmbda).decompose()
1-qubit circuit with 1 instructions:
└── U(0, 0, lambda, 0.0) @ q[0]
inverse()[source]#
class mimiqcircuits.GateU2(phi, lmbda)[source]#

Bases: Gate

Single qubit generic unitary gate \({U_2}\).

Matrix representation:

\[\begin{split}\operatorname{U2}(\phi,\lambda) = \frac{1}{\sqrt{2}}e^{-(\phi+\lambda)/2}\begin{pmatrix} 1 & -e^{i\lambda} \\ e^{i\phi} & e^{i(\phi+\lambda)} \end{pmatrix}\end{split}\]
Parameters:
  • phi – Euler angle in radians.

  • lambda – Euler angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> phi, lmbda = symbols('phi lambda')
>>> GateU2(phi, lmbda)
U2(phi, lambda)
>>> GateU2(phi, lmbda).matrix()
[0.707106781186548, -0.707106781186548*exp(I*lambda)]
[0.707106781186548*exp(I*phi), 0.707106781186548*exp(I*(lambda + phi))]

>>> c = Circuit().push(GateU2(phi, lmbda), 0)
>>> c
1-qubit circuit with 1 instructions:
└── U2(phi, lambda) @ q[0]

>>> GateU2(phi, lmbda).power(2), GateU2(phi, lmbda).inverse()
(U2(phi, lambda)**2, U2(-lambda - pi, -phi + pi))
>>> GateU2(phi, lmbda).decompose()
1-qubit circuit with 1 instructions:
└── U((1/2)*pi, phi, lambda, 0.0) @ q[0]
inverse()[source]#
class mimiqcircuits.GateU3(theta, phi, lmbda)[source]#

Bases: Gate

Single qubit generic unitary gate \({U_3}\).

This gate is equivalent to GateU() up to a global phase, \(\operatorname{U3}(\theta,\phi,\lambda) = e^{-i(\phi + \lambda + \theta)/2} \operatorname{U}(\theta,\phi,\lambda)\)

Matrix representation:

\[\begin{split}\operatorname{U3}(\theta,\phi,\lambda) = \frac{1}{2}e^{-i(\phi + \lambda + \theta)/2} \begin{pmatrix} 1 + e^{i\theta} & -i e^{i\lambda}(1 - e^{i\theta}) \\ i e^{i\phi}(1 - e^{i\theta}) & e^{i(\phi + \lambda)}(1 + e^{i\theta}) \end{pmatrix}\end{split}\]
Parameters:
  • theta – Euler angle 1 in radians.

  • phi – Euler angle 2 in radians.

  • lambda – Euler angle 3 in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta, phi, lmbda = symbols('theta phi lambda')
>>> GateU3(theta, phi, lmbda)
U3(theta, phi, lambda)
>>> GateU3(theta, phi, lmbda).matrix()
[1.0*cos((1/2)*theta), -exp(I*lambda)*sin((1/2)*theta)]
[exp(I*phi)*sin((1/2)*theta), exp(I*(lambda + phi))*cos((1/2)*theta)]

>>> c = Circuit().push(GateU3(theta, phi, lmbda), 0)
>>> GateU3(theta, phi, lmbda).power(2), GateU3(theta, phi, lmbda).inverse()
(U3(theta, phi, lambda)**2, U3(-theta, -lambda, -phi))
>>> GateU3(theta, phi, lmbda).decompose()
1-qubit circuit with 1 instructions:
└── U(theta, phi, lambda, 0.0) @ q[0]
inverse()[source]#
class mimiqcircuits.GateX[source]#

Bases: Gate

Single qubit Pauli-X gate.

Matrix representation:

\[\begin{split}\operatorname{X} = \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateX()
X
>>> GateX().matrix()
[0, 1.0]
[1.0, 0]

>>> c = Circuit().push(GateX(), 0)
>>> c
1-qubit circuit with 1 instructions:
└── X @ q[0]

>>> GateX().power(2), GateX().inverse()
(ID, X)
>>> GateX().decompose()
1-qubit circuit with 1 instructions:
└── U(pi, 0, pi, 0.0) @ q[0]
inverse()[source]#
class mimiqcircuits.GateXXminusYY(theta, beta)[source]#

Bases: Gate

Two qubit parametric GateXXminusYY gate.

Its action is to induce a coherent rotation by some angle between \(\ket{00}\) and \(\ket{11}\)

Matrix representation:

\[\begin{split}\operatorname{(XX-YY)}(\theta, \beta)=\begin{pmatrix} \cos(\frac{\theta}{2}) & 0 & 0 & -i\sin(\frac{\theta}{2})e^{-i\beta} \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ -i\sin(\frac{\theta}{2})e^{i\beta} & 0 & 0 & \cos(\frac{\theta}{2}) \end{pmatrix}\end{split}\]
Parameters:
  • theta (float) – The angle in radians.

  • beta (float) – The angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta, beta = symbols('theta beta')
>>> GateXXminusYY(theta, beta)
XXminusYY(theta, beta)
>>> GateXXminusYY(theta, beta).matrix()
[cos((1/2)*theta), 0, 0, I*(I*sin(beta) - cos(beta))*sin((1/2)*theta)]
[0, 1.0, 0, 0]
[0, 0, 1.0, 0]
[(sin(beta) - I*cos(beta))*sin((1/2)*theta), 0, 0, cos((1/2)*theta)]

>>> c = Circuit().push(GateXXminusYY(theta, beta), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── XXminusYY(theta, beta) @ q[0,1]

>>> GateXXminusYY(theta, beta).power(2), GateXXminusYY(theta, beta).inverse()
(XXminusYY(theta, beta)**2, XXminusYY(-theta, beta))
>>> GateXXminusYY(theta, beta).decompose()
2-qubit circuit with 14 instructions:
├── RZ(-beta) @ q[1]
├── RZ((-1/2)*pi) @ q[0]
├── SX @ q[0]
├── RZ((1/2)*pi) @ q[0]
├── S @ q[1]
├── CX @ q[0], q[1]
├── RY((1/2)*theta) @ q[0]
├── RY((-1/2)*theta) @ q[1]
├── CX @ q[0], q[1]
├── S† @ q[1]
├── RZ((-1/2)*pi) @ q[0]
├── SX† @ q[0]
├── RZ((1/2)*pi) @ q[0]
└── RZ(beta) @ q[1]
inverse()[source]#
class mimiqcircuits.GateXXplusYY(theta, beta)[source]#

Bases: Gate

Two qubit parametric XXplusYY gate.

Also known as an XY gate. Its action is to induce a coherent rotation by some angle between \(\ket{10}\) and \(\ket{01}\).

Matrix representation:

\[\begin{split}\operatorname{(XX+YY)}(\theta, \beta)= \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & \cos(\frac{\theta}{2}) & -i\sin(\frac{\theta}{2})e^{i\beta} & 0\\ 0 & -i\sin(\frac{\theta}{2})e^{-i\beta} & \cos(\frac{\theta}{2}) & 0\\ 0 & 0 & 0 & 1 \end{pmatrix}\end{split}\]
Parameters:
  • theta – The angle in radians.

  • beta – The phase angle in radians.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> theta, beta = symbols('theta beta')
>>> GateXXplusYY(theta, beta)
XXplusYY(theta, beta)
>>> GateXXplusYY(theta, beta).matrix()
[1.0, 0, 0, 0]
[0, cos((1/2)*theta), (sin(beta) - I*cos(beta))*sin((1/2)*theta), 0]
[0, I*(I*sin(beta) - cos(beta))*sin((1/2)*theta), cos((1/2)*theta), 0]
[0, 0, 0, 1.0]

>>> c = Circuit().push(GateXXplusYY(theta, beta), 0, 1)
>>> c
2-qubit circuit with 1 instructions:
└── XXplusYY(theta, beta) @ q[0,1]

>>> GateXXplusYY(theta, beta).power(2), GateXXplusYY(theta, beta).inverse()
(XXplusYY(theta, beta)**2, XXplusYY(-theta, beta))
>>> GateXXplusYY(theta, beta).decompose()
2-qubit circuit with 14 instructions:
├── RZ(beta) @ q[0]
├── RZ((-1/2)*pi) @ q[1]
├── SX @ q[1]
├── RZ((1/2)*pi) @ q[1]
├── S @ q[0]
├── CX @ q[1], q[0]
├── RY((-1/2)*theta) @ q[1]
├── RY((-1/2)*theta) @ q[0]
├── CX @ q[1], q[0]
├── S† @ q[0]
├── RZ((-1/2)*pi) @ q[1]
├── SX† @ q[1]
├── RZ((1/2)*pi) @ q[1]
└── RZ(-beta) @ q[0]
inverse()[source]#
class mimiqcircuits.GateY[source]#

Bases: Gate

Single qubit Pauli-Y gate.

Matrix representation:

\[\begin{split}\operatorname{Y} = \begin{pmatrix} 0 & -i \\ i & 0 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateY()
Y
>>> GateY().matrix()
[0, -0.0 - 1.0*I]
[0.0 + 1.0*I, 0]

>>> c = Circuit().push(GateY(), 0)
>>> GateY().power(2), GateY().inverse()
(ID, Y)
>>> GateY().decompose()
1-qubit circuit with 1 instructions:
└── U(pi, (1/2)*pi, (1/2)*pi, 0.0) @ q[0]
inverse()[source]#
class mimiqcircuits.GateZ[source]#

Bases: Gate

Single qubit Pauli-Z gate.

Matrix representation:

\[\begin{split}\operatorname{Z} = \begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}\end{split}\]

Examples

>>> from mimiqcircuits import *
>>> GateZ()
Z
>>> GateZ().matrix()
[1.0, 0]
[0, -1.0]

>>> c = Circuit().push(GateZ(), 0)
>>> GateZ().power(2), GateZ().inverse()
(ID, Z)
>>> GateZ().decompose()
1-qubit circuit with 1 instructions:
└── P(pi) @ q[0]
inverse()[source]#
class mimiqcircuits.IfStatement(operation, num_bits, val, *args, **kwargs)[source]#

Bases: Operation

Conditional operation

This operation applies a specific operation if a given classical bit condition is met.

Examples

>>> from mimiqcircuits import *
>>> c = Circuit()
>>> c.push(IfStatement(GateX(), 1,1), 0,0)
init if -> operation= X
1-qubit circuit with 1 instructions:
└── IF(c == 1) X @ q[0], c[0]
asciiwidth(qubits, bits)[source]#
control(num_controls)[source]#
evaluate(d)[source]#
get_operation()[source]#
get_unwrapped_value()[source]#
getparams()[source]#
inverse()[source]#
iswrapper()[source]#
property op#
power(power)[source]#
property val#
class mimiqcircuits.Instruction(operation, qubits=None, bits=None)[source]#

Bases: object

Initializes an instruction of a quantum circuit.

Parameters:
  • operation (Operation) – The operation applied by the instruction.

  • qubits (tuple of int) – The qubits to apply the quantum operation to.

  • bits (tuple of int) – The classical bits to apply the quantum operation to.

Raises:
  • TypeError – If operation is not a subclass of Gate or qubits is not a tuple.

  • ValueError – If qubits contains less than 1 or more than 2 elements.

Examples

>>> from mimiqcircuits import *
>>> Instruction(GateX(),(0,),())
X @ q[0]
>>> Instruction(Barrier(4),(0,1,2,3),())
Barrier @ q[0,1,2,3]
asciiwidth()[source]#
property bits#
copy()[source]#
decompose()[source]#
deepcopy()[source]#
evaluate(d)[source]#
get_bits()[source]#
get_operation()[source]#
get_qubits()[source]#
inverse()[source]#
property operation#
property qubits#
class mimiqcircuits.Inverse(operation, *args, **kwargs)[source]#

Bases: Operation

Inverse of the wrapped quantum operation.

The inversion is not performed right away, but only when the circuit is cached or executed.

Warning

Users should not use Inverse directly but rather the inverse method, which performs all the necessary simplifications (e.g., op.inverse().inverse() == op)

Examples

>>> from mimiqcircuits import *
>>> Inverse(GateP(1)).matrix()
[1.0, 0]
[0, 0.54030230586814 - 0.841470984807897*I]

>>> c = Circuit()
>>> c.push(Inverse(GateP(1)), 1)
2-qubit circuit with 1 instructions:
└── P(1)† @ q[1]
control(*args)[source]#
evaluate(d)[source]#
getparams()[source]#
inverse()[source]#
iswrapper()[source]#
matrix()[source]#
parallel(*args)[source]#
power(*args)[source]#
class mimiqcircuits.LazyArg[source]#

Bases: object

class mimiqcircuits.LazyExpr(obj, *args)[source]#

Bases: object

control(*args)[source]#
inverse()[source]#
parallel(*args)[source]#
power(*args)[source]#
class mimiqcircuits.Measure[source]#

Bases: Operation

Measure operation.

Single qubit measurement operation in the computational basis.

This operation is non-reversible

Examples

Adding Measure operation to the Circuit (The qubits (first arg) and the bits (second arg) can be: range, list, tuple, set or int)

>>> from mimiqcircuits import *
>>> c= Circuit()
>>> c.push(Measure(),0,0)
1-qubit circuit with 1 instructions:
└── Measure @ q[0], c[0]
>>> from mimiqcircuits import *
>>> c= Circuit()
>>> c.push(Measure(), range(0,3), range(0,3))
3-qubit circuit with 3 instructions:
├── Measure @ q[0], c[0]
├── Measure @ q[1], c[1]
└── Measure @ q[2], c[2]
asciiwidth(_, bits)[source]#
control(num_qubits)[source]#
static from_json(d)[source]#
get_operation()[source]#
inverse()[source]#
iswrapper()[source]#
power(p)[source]#
class mimiqcircuits.MeasureReset[source]#

Bases: Operation

MeasureReset operation.

This operation measures a qubit q, stores the value in a classical bit c, then applies a X operation to the qubit if the measured value is 1, effectively resetting the qubit to the |0> state.

Examples

>>> from mimiqcircuits import *
>>> c = Circuit()
>>> c.push(MeasureReset(), 1, 0)
2-qubit circuit with 1 instructions:
└── MeasureReset @ q[1], c[0]

>>> c.decompose()
init if -> operation= X
2-qubit circuit with 2 instructions:
├── Measure @ q[1], c[0]
└── IF(c == 1) X @ q[1], c[0]
asciiwidth(qubits, bits)[source]#
control(num_qubits)[source]#
get_operation()[source]#
inverse()[source]#
iswrapper()[source]#
power(p)[source]#
class mimiqcircuits.MimiqConnection(url=None)[source]#

Bases: MimiqConnection

Represents a connection to the Mimiq Server.

Inherits from: mimiqlink.MimiqConnection python.

execute(circuit, label='pyapi_v0.10.0', algorithm='auto', nsamples=1000, bitstrings=None, timelimit=None, bonddim=None, entdim=None, seed=None, qasmincludes=None)[source]#

Execute a circuit simulation using the MIMIQ cloud services.

Parameters:
  • circuit (Circuit) – The quantum circuit to be executed.

  • label (str) – The label for the execution (default: “circuitsimu”).

  • algorithm (str) – The algorithm to be used for execution (default: “auto”).

  • nsamples (int) – The number of samples to generate (default: 1000).

  • bitstrings (list) – List of bitstrings for conditional execution (default: None).

  • timelimit (int) – The time limit for execution in seconds (default: 5 * 60).

  • bonddim (int) – The bond dimension for the MPS algorithm (default: None).

  • entdim (int) – The entangling dimension for the MPS algorithm (default: None).

  • seed (int) – The seed for generating random numbers (default: randomly generated). If provided, uses the specified seed.

  • qasmincludes (list) – List of OPENQASM files to include in the execution (default: None).

Returns:

The execution identifier.

Return type:

str

Raises:

ValueError – If bonddim, nsamples, or timelimit exceeds the allowed limits.

Examples

>>> from mimiqcircuits import *
>>> conn = MimiqConnection(url = "https://mimiq.qperfect.io/api")
>>> conn.connect()
Starting authentication server on port 1444 (http://localhost:1444)
>>> c = Circuit()
>>> c.push(GateH(),range(10))
10-qubit circuit with 10 instructions:
├── H @ q[0]
├── H @ q[1]
├── H @ q[2]
├── H @ q[3]
├── H @ q[4]
├── H @ q[5]
├── H @ q[6]
├── H @ q[7]
├── H @ q[8]
└── H @ q[9]

>>> job=conn.execute(c,algorithm="auto")
>>> res=conn.get_results(job)
>>> res
QCSResults:
├── simulator: MIMIQ-StateVector 0.12.1
├── amplitudes time: 1.16e-07s
├── total time: 0.001320324s
├── compression time: 1.717e-05s
├── sample time: 0.000999485s
├── apply time: 0.000115216s
├── fidelity estimate (min,max): (1.000, 1.000)
├── average ≥2-qubit gate error (min,max): (0.000, 0.000)
├── 1 executions
├── 0 amplitudes
└── 1000 samples

Connecting Using Credentials#

conn = MimiqConnection(url="https://mimiq.qperfect.io/api")
conn.connectUser("Email_address", "Password")

Saving and Loading Tokens#

conn.savetoken("qperfect.json")
conn = MimiqConnection.loadtoken("qperfect.json")

Closing a Connection and Checking Connection Status#

conn.close()

conn.isOpen()
get_inputs(execution)[source]#

Retrieve the inputs (circuit and parameters) of the execution.

Parameters:

execution (str) – The execution identifier.

Returns:

parameters (dict) of the execution.

Return type:

dict

Raises:

RuntimeError – If the required files are not found in inputs. Update your library.

get_results(execution, interval=10)[source]#

Retrieve the results of a completed execution.

Parameters:
  • execution (str) – The execution identifier.

  • interval (int) – The interval (in seconds) for checking job status (default: 10).

Returns:

An instance of the QCSResults class.

Return type:

Results

Raises:

RuntimeError – If the remote job encounters an error.

class mimiqcircuits.Operation[source]#

Bases: ABC

Abstract base class for quantum operations.

asciiwidth(qubits, bits)[source]#
copy()[source]#
property cregsizes#
decompose()[source]#
deepcopy()[source]#
evaluate(d)[source]#
get_operation()[source]#
getparam(pn)[source]#
getparams()[source]#
is_symbolic()[source]#
isopalias()[source]#
abstract iswrapper()[source]#
property name#
property num_bits#
property num_cregs#
property num_qregs#
property num_qubits#
property parnames#
property qregsizes#
class mimiqcircuits.Parallel(num_repeats, op: Operation)[source]#

Bases: Operation

Parallel operation

This is a composite operation that applies multiple gates in parallel to the circuit at once.

Examples

>>> from mimiqcircuits import *
>>> c= Circuit()
>>> c.push(Parallel(3,GateX()),1,2,3)
4-qubit circuit with 1 instructions:
└── Parallel(3, X) @ q[1], q[2], q[3]
control(*args)[source]#
evaluate(d)[source]#
get_operation()[source]#
inverse()[source]#
iswrapper()[source]#
matrix()[source]#
property num_repeats#
property op#
parallel(*args)[source]#
power(*args)[source]#
class mimiqcircuits.PhaseGradient(*args)[source]#

Bases: Gate

Phase Gradient gate

A phase gradient gate applies a phase shift to a quantum register of n qubits, where each computational basis state |k⟩ experiences a phase proportional to its integer value k

Parameters:

n (int) – The number of qubits in the quantum register.

Returns:

The PhaseGradient gate.

Return type:

PhaseGradient

name#

The name of the operation.

Type:

str

num_qubits#

The number of qubits in the quantum register.

Type:

int

qregsizes#

The sizes of the quantum registers.

Type:

list of int

Examples

>>> from mimiqcircuits import *
>>> c=Circuit()
>>> c.push(PhaseGradient(2),9,8)
10-qubit circuit with 1 instructions:
└── PhaseGradient @ q[9,8]
class mimiqcircuits.PolynomialOracle(*args)[source]#

Bases: Gate

Polynomial Oracle.

Parameters:
  • a (Num) – Coefficient a in the polynomial.

  • b (Num) – Coefficient b in the polynomial.

  • c (Num) – Coefficient c in the polynomial.

  • d (Num) – Coefficient d in the polynomial.

Raises:

ValueError – If the input parameters do not satisfy the required conditions.

Returns:

The Polynomial Oracle.

Return type:

PolynomialOracle

Examples

>>> from mimiqcircuits import *
>>> c = Circuit()
>>> c.push(PolynomialOracle(5,5,1, 2, 3, 4), 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
11-qubit circuit with 1 instructions:
└── PolynomialOracle(1, 2, 3, 4) @ q[1,2,3,4,5], q[6,7,8,9,10]
inverse()[source]#
class mimiqcircuits.Power(operation, exponent, *args, **kwargs)[source]#

Bases: Operation

Power operation.

Represents a Power operation raised to a specified exponent.

Examples

>>> from mimiqcircuits import *
>>> c= Circuit()
>>> c.push(Power(GateX(),1/2),1)
2-qubit circuit with 1 instructions:
└── SX @ q[1]

>>> c.push(Power(GateX(),5),1)
2-qubit circuit with 2 instructions:
├── SX @ q[1]
└── X**5 @ q[1]

>>> c.decompose()
2-qubit circuit with 6 instructions:
├── U(1.57079632679490, -1.57079632679490, 1.57079632679490, 0.785398163397448) @ q[1]
├── X @ q[1]
├── X @ q[1]
├── X @ q[1]
├── X @ q[1]
└── X @ q[1]
control(*args)[source]#
decompose()[source]#
evaluate(d)[source]#
property exponent#
getparams()[source]#
inverse()[source]#
iswrapper()[source]#
matrix()[source]#
property op#
parallel(*args)[source]#
power(*args)[source]#
class mimiqcircuits.QCSResults(simulator=None, version=None, fidelities=None, avggateerrors=None, cstates=None, zstates=None, amplitudes=None, timings=None)[source]#

Bases: object

Represents the results of quantum computations obtained from quantum cloud services (QCS).

Parameters:
  • simulator (str) – The name of the quantum simulator.

  • version (str) – The version of the quantum simulator.

  • fidelities (list) – List of fidelity estimates from different executions.

  • avggateerrors (list) – List of average multi-qubit gate errors from different executions.

  • cstates (list) – List of classical states obtained from executions.

  • zstates (list) – Not used in the current implementation.

  • amplitudes (dict) – Dictionary of statevector amplitudes for different quantum states.

  • timings (dict) – Dictionary of timing information for different phases of the computation.

histogram()[source]#

Histogram of the obtained classical states’ occurrences.

Returns:

A dictionary of classical states (bitarray) and their occurrences (float).

Raises:

TypeError – If a non QCSResults object is passed.

static loadproto(filename)[source]#

Load QCSResults object from a Protocol Buffers file.

The loadproto() method is a static method and should be called on the class, not on an instance of the class.

Note

Look for example in QCSResults.saveproto()

saveproto(filename)[source]#

Save QCSResults object to a Protocol Buffers file.

Examples

>>> from mimiqcircuits import *
>>> from symengine import *
>>> import tempfile
>>> x, y = symbols("x y")
>>> c = Circuit()
>>> c.push(GateH(), 0)
1-qubit circuit with 1 instructions:
└── H @ q[0]

>>> conn = MimiqConnection()
>>> conn.connect()
Starting authentication server on port 1444 (http://localhost:1444)
>>> job = conn.execute(c)
>>> res = conn.get_results(job)
>>> res
QCSResults:
├── simulator: MIMIQ-StateVector 0.14.1
├── timings:
│    ├── parse time: 7.1008e-05s
│    ├── apply time: 1.3554e-05s
│    ├── total time: 0.00023100600000000002s
│    ├── compression time: 3.207e-06s
│    └── sample time: 4.8047e-05s
├── fidelity estimate: 1
├── average multi-qubit gate error estimate: 0
├── most sampled:
│    ├── bs"0" => 509
│    └── bs"1" => 491
├── 1 executions
├── 0 amplitudes
└── 1000 samples
>>> tmpfile = tempfile.NamedTemporaryFile(suffix=".pb", delete=True)
>>> res.saveproto(tmpfile.name)
9167
>>> res.loadproto(tmpfile.name)
QCSResults:
├── simulator: MIMIQ-StateVector 0.14.1
├── timings:
│    ├── parse time: 7.1008e-05s
│    ├── apply time: 1.3554e-05s
│    ├── total time: 0.00023100600000000002s
│    ├── compression time: 3.207e-06s
│    └── sample time: 4.8047e-05s
├── fidelity estimate: 1
├── average multi-qubit gate error estimate: 0
├── most sampled:
│    ├── bs"0" => 509
│    └── bs"1" => 491
├── 1 executions
├── 0 amplitudes
└── 1000 samples
Note:

This example uses a temporary file to demonstrate the save and load functionality. You can save your file with any name at any location using:

res.saveproto("example.pb")
res.loadproto("example.pb")
class mimiqcircuits.QFT(*args)[source]#

Bases: Gate

Quantum Fourier transform.

Performs the quantum Fourier transform on a register of n qubits.

Parameters:

n (int) – The number of qubits in the quantum register.

Raises:

ValueError – If the number of qubits is less than 1.

Returns:

The Quantum Fourier Transform operation.

Return type:

QFT

name#

The name of the operation.

Type:

str

num_qubits#

The number of qubits in the quantum register.

Type:

int

qregsizes#

The sizes of the quantum registers.

Type:

list of int

Examples

>>> from mimiqcircuits import *
>>> c=Circuit()
>>> c.push(QFT(2),1,2)
3-qubit circuit with 1 instructions:
└── QFT @ q[1,2]
class mimiqcircuits.Reset[source]#

Bases: Operation

Reset operation.

Quantum operation that resets the status of one qubit to the \(\ket{0}\) state.

This operation is non-reversible.

Examples

Adding Reset operation to the Circuit (The args can be: range, list, tuple, set or int)

>>> from mimiqcircuits import *
>>> c= Circuit()
>>> c.push(Reset(), 0)
1-qubit circuit with 1 instructions:
└── Reset @ q[0]

>>> from mimiqcircuits import *
>>> c= Circuit()
>>> c.push(Reset(),(0,1,2))
3-qubit circuit with 3 instructions:
├── Reset @ q[0]
├── Reset @ q[1]
└── Reset @ q[2]
asciiwidth(qubits, _)[source]#
control(num_qubits)[source]#
static from_json(d)[source]#
inverse()[source]#
iswrapper()[source]#
power(pwr)[source]#
mimiqcircuits.control(*args)[source]#
mimiqcircuits.gatedecl(name)[source]#
mimiqcircuits.inverse(op)[source]#
mimiqcircuits.load_results(filename)[source]#

Loads QCSResults from a ProtoBuf file.

mimiqcircuits.parallel(*args)[source]#
mimiqcircuits.plothistogram(results, num_outcomes=15, mimiqstyle=True, nobitstrings=False)[source]#

Plots the histogram of the obtained classical states’ occurrences.

Parameters:
  • results – a QCSResults object.

  • num_states (int) – the maximum number of bitstrings plotted (default 15)

Raises:

TypeError – If a non QCSResults object is passed.

mimiqcircuits.power(*args)[source]#
mimiqcircuits.save_results(filename, results)[source]#

Saves the results to a ProtoBuf file.