tensorcircuit.basecircuitΒΆ

Quantum circuit: common methods for all circuit classes as MixIn

Note

  • Supports qubit (d = 2) and qudit (d >= 2) systems.

  • For string-encoded samples/counts when d <= 36, digits use base-d characters 0-9A-Z (A = 10, …, Z = 35).

class tensorcircuit.basecircuit.BaseCircuit[source]ΒΆ

Bases: AbstractCircuit

static all_zero_nodes(n: int, prefix: str = 'qb-', dim: int = 2) List[Node][source]ΒΆ
amplitude(l: str | Any) Any[source]ΒΆ

Returns the amplitude of the circuit given the bitstring l. For state simulator, it computes \(\langle l\vert \psi\rangle\), for density matrix simulator, it computes \(Tr(\rho \vert l\rangle \langle 1\vert)\) Note how these two are different up to a square operation.

Example:

>>> c = tc.Circuit(2)
>>> c.X(0)
>>> c.amplitude("10")
array(1.+0.j, dtype=complex64)
>>> c.CNOT(0, 1)
>>> c.amplitude("11")
array(1.+0.j, dtype=complex64)
Parameters:

l (Union[str, Tensor]) – The bitstring of 0 and 1s.

Returns:

The amplitude of the circuit.

Return type:

tn.Node.tensor

amplitude_before(l: str | Any) List[Gate][source]ΒΆ

Returns the tensornetwor nodes for the amplitude of the circuit given the bitstring l. For state simulator, it computes \(\langle l\vert \psi\rangle\), for density matrix simulator, it computes \(Tr(\rho \vert l\rangle \langle 1\vert)\) Note how these two are different up to a square operation.

Parameters:

l (Union[str, Tensor]) – The bitstring of 0 and 1s.

Returns:

The tensornetwork nodes for the amplitude of the circuit.

Return type:

List[Gate]

append(c: AbstractCircuit, indices: List[int] | None = None) AbstractCircuitΒΆ

append circuit c before

Example:

>>> c1 = tc.Circuit(2)
>>> c1.H(0)
>>> c1.H(1)
>>> c2 = tc.Circuit(2)
>>> c2.cnot(0, 1)
>>> c1.append(c2)
<tensorcircuit.circuit.Circuit object at 0x7f8402968970>
>>> c1.draw()
    β”Œβ”€β”€β”€β”
q_0:─ H β”œβ”€β”€β– β”€β”€
    β”œβ”€β”€β”€β”€β”Œβ”€β”΄β”€β”
q_1:─ H β”œβ”€ X β”œ
    β””β”€β”€β”€β”˜β””β”€β”€β”€β”˜
Parameters:
  • c (BaseCircuit) – The other circuit to be appended

  • indices (Optional[List[int]], optional) – the qubit indices to which c is appended on. Defaults to None, which means plain concatenation.

Returns:

The composed circuit

Return type:

BaseCircuit

append_from_qir(qir: List[Dict[str, Any]], allow_channel: bool = False) NoneΒΆ

Apply the ciurict in form of quantum intermediate representation after the current cirucit.

Example:

>>> c = tc.Circuit(3)
>>> c.H(0)
>>> c.to_qir()
[{'gatef': h, 'gate': Gate(...), 'index': (0,), 'name': 'h', 'split': None, 'mpo': False}]
>>> c2 = tc.Circuit(3)
>>> c2.CNOT(0, 1)
>>> c2.to_qir()
[{'gatef': cnot, 'gate': Gate(...), 'index': (0, 1), 'name': 'cnot', 'split': None, 'mpo': False}]
>>> c.append_from_qir(c2.to_qir())
>>> c.to_qir()
[{'gatef': h, 'gate': Gate(...), 'index': (0,), 'name': 'h', 'split': None, 'mpo': False},
 {'gatef': cnot, 'gate': Gate(...), 'index': (0, 1), 'name': 'cnot', 'split': None, 'mpo': False}]
Parameters:
  • qir (List[Dict[str, Any]]) – The quantum intermediate representation.

  • allow_channel (bool, optional) – whether to allow channel in the qir, defaults to False

apply(gate: Gate | QuOperator, *index: int, name: str | None = None, split: Dict[str, Any] | None = None, mpo: bool = False, diagonal: bool = False, ir_dict: Dict[str, Any] | None = None) NoneΒΆ

An implementation of this method should also append gate directionary to self._qir

apply_general_gate(gate: Gate | QuOperator, *index: int, name: str | None = None, split: Dict[str, Any] | None = None, mpo: bool = False, diagonal: bool = False, ir_dict: Dict[str, Any] | None = None) None[source]ΒΆ

An implementation of this method should also append gate directionary to self._qir

static apply_general_gate_delayed(gatef: Callable[[], Gate], name: str | None = None, mpo: bool = False) Callable[[...], None]ΒΆ
static apply_general_variable_gate_delayed(gatef: Callable[[...], Any], name: str | None = None, mpo: bool = False, diagonal: bool = False) Callable[[...], None]ΒΆ
barrier_instruction(*index: List[int]) NoneΒΆ

add a barrier instruction flag, no effect on numerical simulation

Parameters:

index (List[int]) – the corresponding qubits

circuit_param: Dict[str, Any]ΒΆ
static coloring_copied_nodes(nodes: Sequence[Node], nodes0: Sequence[Node], is_dagger: bool = True, flag: str = 'inputs') None[source]ΒΆ

Tag copied nodes while preserving the original node’s identity for lightcone cancellation.

Parameters:
  • nodes (Sequence[tn.Node]) – A sequence of newly copied nodes.

  • nodes0 (Sequence[tn.Node]) – The sequence of original nodes from which nodes were copied.

  • is_dagger (bool, optional) – Whether the copied nodes represent conjugate operations, defaults to True.

  • flag (str, optional) – A label for the node type, defaults to β€œinputs”.

static coloring_nodes(nodes: Sequence[Node], is_dagger: bool = False, flag: str = 'inputs') None[source]ΒΆ

Tag nodes with metadata used for casual lightcone simplification and tracing.

Parameters:
  • nodes (Sequence[tn.Node]) – A sequence of tensornetwork nodes to tag.

  • is_dagger (bool, optional) – Whether the nodes represent conjugate operations (U^dagger), defaults to False.

  • flag (str, optional) – A label for the node type (e.g., β€œgate”, β€œinputs”, β€œoperator”), defaults to β€œinputs”.

cond_measure(index: int, status: float | None = None) AnyΒΆ

Measurement on z basis at index qubit based on quantum amplitude (not post-selection). The highlight is that this method can return the measured result as a int Tensor and thus maintained a jittable pipeline.

Example:

>>> c = tc.Circuit(2)
>>> c.H(0)
>>> r = c.cond_measurement(0)
>>> c.conditional_gate(r, [tc.gates.i(), tc.gates.x()], 1)
>>> c.expectation([tc.gates.z(), [0]]), c.expectation([tc.gates.z(), [1]])
# two possible outputs: (1, 1) or (-1, -1)

Note

In terms of DMCircuit, this method returns nothing and the density matrix after this method is kept in mixed state without knowing the measuremet resuslts

Parameters:

index (int) – the site index for the Z-basis measurement

Returns:

0 or 1 for Z-basis measurement outcome

Return type:

Tensor

cond_measurement(index: int, status: float | None = None) Any[source]ΒΆ

Measurement on z basis at index qubit based on quantum amplitude (not post-selection). The highlight is that this method can return the measured result as a int Tensor and thus maintained a jittable pipeline.

Example:

>>> c = tc.Circuit(2)
>>> c.H(0)
>>> r = c.cond_measurement(0)
>>> c.conditional_gate(r, [tc.gates.i(), tc.gates.x()], 1)
>>> c.expectation([tc.gates.z(), [0]]), c.expectation([tc.gates.z(), [1]])
# two possible outputs: (1, 1) or (-1, -1)

Note

In terms of DMCircuit, this method returns nothing and the density matrix after this method is kept in mixed state without knowing the measuremet resuslts

Parameters:

index (int) – the site index for the Z-basis measurement

Returns:

0 or 1 for Z-basis measurement outcome

Return type:

Tensor

conditional_gate(which: Any, kraus: Sequence[Gate], *index: int) NoneΒΆ

Apply which-th gate from kraus list, i.e. apply kraus[which]

Parameters:
  • which (Tensor) – Tensor of shape [] and dtype int

  • kraus (Sequence[Gate]) – A list of gate in the form of tc.gate or Tensor

  • index (int) – the qubit lines the gate applied on

copy() AbstractCircuitΒΆ
static copy_nodes(nodes: Sequence[Node], dangling: Sequence[Edge] | None = None, conj: bool | None = False) Tuple[List[Node], List[Edge]][source]ΒΆ

copy all nodes and dangling edges correspondingly

Returns:

depolarizing2_instruction(q1: int, q2: int, p: float, **kws: Any) NoneΒΆ

add a 2-qubit depolarizing instruction flag, no effect on numerical simulation

depolarizing_instruction(q: int, px: float | None = None, py: float | None = None, pz: float | None = None, **kws: Any) NoneΒΆ

add a depolarizing instruction flag, no effect on numerical simulation

detector_instruction(lookback_indices: Sequence[int], coords: Sequence[float] | None = None, **kws: Any) NoneΒΆ

add a detector instruction flag, no effect on numerical simulation

Parameters:

lookback_indices (Sequence[int]) – the corresponding measurement record indices

detector_probabilities() Any[source]ΒΆ

Calculate the joint probability distribution of all detectors in the circuit.

Returns:

A tensor representing the joint probability distribution.

Return type:

Tensor

diaggates = ['diagonal', 'rzm', 'cmz']ΒΆ
draw(**kws: Any) AnyΒΆ

Visualise the circuit. This method recevies the keywords as same as qiskit.circuit.QuantumCircuit.draw. More details can be found here: https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.draw.html. Interesting kws options include: ``idle_wires``(bool)

Example:

>>> c = tc.Circuit(3)
>>> c.H(1)
>>> c.X(2)
>>> c.CNOT(0, 1)
>>> c.draw(output='text')
q_0: ───────■──
     β”Œβ”€β”€β”€β”β”Œβ”€β”΄β”€β”
q_1: ─ H β”œβ”€ X β”œ
     β”œβ”€β”€β”€β”€β””β”€β”€β”€β”˜
q_2: ─ X β”œβ”€β”€β”€β”€β”€
     β””β”€β”€β”€β”˜
expectation(*ops: Tuple[Node, List[int]], reuse: bool = True, noise_conf: Any | None = None, nmc: int = 1000, status: Any | None = None, **kws: Any) AnyΒΆ
expectation_before(*ops: Tuple[Node, List[int]], reuse: bool = True, **kws: Any) List[Node][source]ΒΆ

Get the tensor network in the form of a list of nodes for the expectation calculation before the real contraction

Parameters:

reuse (bool, optional) – _description_, defaults to True

Raises:

ValueError – _description_

Returns:

_description_

Return type:

List[tn.Node]

expectation_ps(x: Sequence[int] | None = None, y: Sequence[int] | None = None, z: Sequence[int] | None = None, ps: Sequence[int] | None = None, reuse: bool = True, noise_conf: Any | None = None, nmc: int = 1000, status: Any | None = None, **kws: Any) AnyΒΆ

Shortcut for Pauli string expectation. x, y, z list are for X, Y, Z positions

Example:

>>> c = tc.Circuit(2)
>>> c.X(0)
>>> c.H(1)
>>> c.expectation_ps(x=[1], z=[0])
array(-0.99999994+0.j, dtype=complex64)
>>> c = tc.Circuit(2)
>>> c.cnot(0, 1)
>>> c.rx(0, theta=0.4)
>>> c.rx(1, theta=0.8)
>>> c.h(0)
>>> c.h(1)
>>> error1 = tc.channels.generaldepolarizingchannel(0.1, 1)
>>> error2 = tc.channels.generaldepolarizingchannel(0.06, 2)
>>> noise_conf = NoiseConf()
>>> noise_conf.add_noise("rx", error1)
>>> noise_conf.add_noise("cnot", [error2], [[0, 1]])
>>> c.expectation_ps(x=[0], noise_conf=noise_conf, nmc=10000)
(0.46274087-3.764033e-09j)
Parameters:
  • x (Optional[Sequence[int]], optional) – sites to apply X gate, defaults to None

  • y (Optional[Sequence[int]], optional) – sites to apply Y gate, defaults to None

  • z (Optional[Sequence[int]], optional) – sites to apply Z gate, defaults to None

  • ps (Optional[Sequence[int]], optional) – or one can apply a ps structures instead of x, y, z, e.g. [0, 1, 3, 0, 2, 2] for X_1Z_2Y_4Y_5 defaults to None, ps can overwrite x, y and z

  • reuse (bool, optional) – whether to cache and reuse the wavefunction, defaults to True

  • noise_conf (Optional[NoiseConf], optional) – Noise Configuration, defaults to None

  • nmc (int, optional) – repetition time for Monte Carlo sampling for noisfy calculation, defaults to 1000

  • status (Optional[Tensor], optional) – external randomness given by tensor uniformly from [0, 1], defaults to None, used for noisfy circuit sampling

Returns:

Expectation value

Return type:

Tensor

classmethod from_cirq(qc: Any, n: int | None = None, inputs: List[float] | None = None, circuit_params: Dict[str, Any] | None = None) AbstractCircuitΒΆ

Import Cirq Circuit object as a tc.Circuit object.

Example:

>>> import cirq
>>> c = cirq.Circuit()
>>> q = cirq.LineQubit.range(3)
>>> c.append(cirq.H(q[0]))
>>> c.append(cirq.CNOT(q[0], q[1]))
>>> tc_c = tc.Circuit.from_cirq(c)
Parameters:
  • qc (cirq.Circuit) – Cirq Circuit object

  • n (int) – The number of qubits for the circuit

  • inputs (Optional[List[float]], optional) – possible input wavefunction for tc.Circuit, defaults to None

  • circuit_params (Optional[Dict[str, Any]]) – kwargs given in Circuit.__init__ construction function, default to None.

Returns:

The same circuit but as tensorcircuit object

Return type:

Circuit

classmethod from_json(jsonstr: str, circuit_params: Dict[str, Any] | None = None) AbstractCircuitΒΆ

load json str as a Circuit

Parameters:
  • jsonstr (str) – _description_

  • circuit_params (Optional[Dict[str, Any]], optional) – Extra circuit parameters in the format of __init__, defaults to None

Returns:

_description_

Return type:

AbstractCircuit

classmethod from_json_file(file: str, circuit_params: Dict[str, Any] | None = None) AbstractCircuitΒΆ

load json file and convert it to a circuit

Parameters:
  • file (str) – filename

  • circuit_params (Optional[Dict[str, Any]], optional) – _description_, defaults to None

Returns:

_description_

Return type:

AbstractCircuit

classmethod from_openqasm(qasmstr: str, circuit_params: Dict[str, Any] | None = None, keep_measure_order: bool = False) AbstractCircuitΒΆ
classmethod from_openqasm_file(file: str, circuit_params: Dict[str, Any] | None = None, keep_measure_order: bool = False) AbstractCircuitΒΆ
classmethod from_qir(qir: List[Dict[str, Any]], circuit_params: Dict[str, Any] | None = None, allow_channel: bool = False) AbstractCircuitΒΆ

Restore the circuit from the quantum intermediate representation.

Example:

>>> c = tc.Circuit(3)
>>> c.H(0)
>>> c.rx(1, theta=tc.array_to_tensor(0.7))
>>> c.exp1(0, 1, unitary=tc.gates._zz_matrix, theta=tc.array_to_tensor(-0.2), split=split)
>>> len(c)
7
>>> c.expectation((tc.gates.z(), [1]))
array(0.764842+0.j, dtype=complex64)
>>> qirs = c.to_qir()
>>>
>>> c = tc.Circuit.from_qir(qirs, circuit_params={"nqubits": 3})
>>> len(c._nodes)
7
>>> c.expectation((tc.gates.z(), [1]))
array(0.764842+0.j, dtype=complex64)
Parameters:
  • qir (List[Dict[str, Any]]) – The quantum intermediate representation of a circuit.

  • circuit_params (Optional[Dict[str, Any]]) – Extra circuit parameters.

Returns:

The circuit have same gates in the qir.

Return type:

Circuit

classmethod from_qiskit(qc: Any, n: int | None = None, inputs: List[float] | None = None, circuit_params: Dict[str, Any] | None = None, binding_params: Sequence[float] | Dict[Any, float] | None = None) AbstractCircuitΒΆ

Import Qiskit QuantumCircuit object as a tc.Circuit object.

Example:

>>> from qiskit import QuantumCircuit
>>> qisc = QuantumCircuit(3)
>>> qisc.h(2)
>>> qisc.cswap(1, 2, 0)
>>> qisc.swap(0, 1)
>>> c = tc.Circuit.from_qiskit(qisc)
Parameters:
  • qc (QuantumCircuit in Qiskit) – Qiskit Circuit object

  • n (int) – The number of qubits for the circuit

  • inputs (Optional[List[float]], optional) – possible input wavefunction for tc.Circuit, defaults to None

  • circuit_params (Optional[Dict[str, Any]]) – kwargs given in Circuit.__init__ construction function, default to None.

  • binding_params (Optional[Union[Sequence[float], Dict[Any, float]]]) – (variational) parameters for the circuit. Could be either a sequence or dictionary depending on the type of parameters in the Qiskit circuit. For ParameterVectorElement use sequence. For Parameter use dictionary

Returns:

The same circuit but as tensorcircuit object

Return type:

Circuit

classmethod from_qsim_file(file: str, circuit_params: Dict[str, Any] | None = None) AbstractCircuitΒΆ
static front_from_nodes(nodes: List[Node]) List[Edge][source]ΒΆ
gate_aliases = [['cnot', 'cx'], ['fredkin', 'cswap'], ['toffoli', 'ccnot'], ['toffoli', 'ccx'], ['any', 'unitary'], ['sd', 'sdg'], ['td', 'tdg']]ΒΆ
gate_count(gate_list: str | Sequence[str] | None = None) intΒΆ

count the gate number of the circuit

Example:

>>> c = tc.Circuit(3)
>>> c.h(0)
>>> c.multicontrol(0, 1, 2, ctrl=[0, 1], unitary=tc.gates._x_matrix)
>>> c.toffolli(1, 2, 0)
>>> c.gate_count()
3
>>> c.gate_count(["multicontrol", "toffoli"])
2
Parameters:

gate_list (Optional[Sequence[str]], optional) – gate name or gate name list to be counted, defaults to None (counting all gates)

Returns:

the total number of all gates or gates in the gate_list

Return type:

int

gate_count_by_condition(cond_func: Callable[[Dict[str, Any]], bool]) intΒΆ

count the number of gates that satisfy certain condition

Example:

>>> c = tc.Circuit(3)
>>> c.x(0)
>>> c.h(0)
>>> c.multicontrol(0, 1, 2, ctrl=[0, 1], unitary=tc.gates._x_matrix)
>>> c.gate_count_by_condition(lambda qir: qir["index"] == (0, ))
2
>>> c.gate_count_by_condition(lambda qir: qir["mpo"])
1
Parameters:

cond_func (Callable[[Dict[str, Any]], bool]) – the condition for counting the gate

Returns:

the total number of all gates which satisfy the condition

Return type:

int

gate_summary() Dict[str, int]ΒΆ

return the summary dictionary on gate type - gate count pair

Returns:

the gate count dict by gate type

Return type:

Dict[str, int]

get_positional_logical_mapping() Dict[int, int]ΒΆ

Get positional logical mapping dict based on measure instruction. This function is useful when we only measure part of the qubits in the circuit, to process the count result from partial measurement, we must be aware of the mapping, i.e. for each position in the count bitstring, what is the corresponding qubits (logical) defined on the circuit

Returns:

positional_logical_mapping

Return type:

Dict[int, int]

get_quvector() QuVector[source]ΒΆ

Get the representation of the output state in the form of QuVector while maintaining the circuit uncomputed

Returns:

QuVector representation of the output state from the circuit

Return type:

QuVector

initial_mapping(logical_physical_mapping: Dict[int, int], n: int | None = None, circuit_params: Dict[str, Any] | None = None) AbstractCircuitΒΆ

generate a new circuit with the qubit mapping given by logical_physical_mapping

Parameters:
  • logical_physical_mapping (Dict[int, int]) – how to map logical qubits to the physical qubits on the new circuit

  • n (Optional[int], optional) – number of qubit of the new circuit, can be different from the original one, defaults to None

  • circuit_params (Optional[Dict[str, Any]], optional) – _description_, defaults to None

Returns:

_description_

Return type:

AbstractCircuit

inputs: AnyΒΆ
inverse(circuit_params: Dict[str, Any] | None = None) AbstractCircuitΒΆ

inverse the circuit, return a new inversed circuit

EXAMPLE:

>>> c = tc.Circuit(2)
>>> c.H(0)
>>> c.rzz(1, 2, theta=0.8)
>>> c1 = c.inverse()
Parameters:

circuit_params (Optional[Dict[str, Any]], optional) – keywords dict for initialization the new circuit, defaults to None

Returns:

the inversed circuit

Return type:

Circuit

is_dm: boolΒΆ
is_mps: bool = FalseΒΆ
measure(*index: int, with_prob: bool = False, status: Any | None = None) Tuple[Any, Any]ΒΆ

Take measurement on the given site indices (computational basis). This method is jittable is and about 100 times faster than unjit version!

Parameters:
  • index (int) – Measure on which site (wire) index.

  • with_prob (bool, optional) – If true, theoretical probability is also returned.

  • status (Optional[Tensor]) – external randomness, with shape [index], defaults to None

Returns:

The sample output and probability (optional) of the quantum line.

Return type:

Tuple[Tensor, Tensor]

measure_instruction(*index: int) NoneΒΆ

add a measurement instruction flag, no effect on numerical simulation

Parameters:

index (int) – the corresponding qubits

measure_jit(*index: int, with_prob: bool = False, status: Any | None = None) Tuple[Any, Any][source]ΒΆ

Take measurement on the given site indices (computational basis). This method is jittable is and about 100 times faster than unjit version!

Parameters:
  • index (int) – Measure on which site (wire) index.

  • with_prob (bool, optional) – If true, theoretical probability is also returned.

  • status (Optional[Tensor]) – external randomness, with shape [index], defaults to None

Returns:

The sample output and probability (optional) of the quantum line.

Return type:

Tuple[Tensor, Tensor]

mpogates = ['multicontrol', 'mpo']ΒΆ
mr_instruction(q: int, p: float = 0.0, **kws: Any) NoneΒΆ

add a measure-reset instruction flag, no effect on numerical simulation

Parameters:

q (int) – the corresponding qubit

outcome_probability(state: Sequence[int]) Any[source]ΒΆ

Calculate the probability of a specific detector outcome bitstring.

Parameters:

state (Sequence[int]) – The detector outcome bitstring as a sequence of 0s and 1s.

Returns:

The probability of the given outcome.

Return type:

Tensor

pauli2_instruction(q1: int, q2: int, **kws: Any) NoneΒΆ

add a 2-qubit pauli instruction flag, no effect on numerical simulation

pauli_instruction(q: int, px: float | None = None, py: float | None = None, pz: float | None = None, **kws: Any) NoneΒΆ

add a pauli instruction flag, no effect on numerical simulation

perfect_sampling(status: Any | None = None) Tuple[str, float][source]ΒΆ

Sampling base-d strings (0-9A-Z when d <= 36) from the circuit output based on quantum amplitudes. Reference: arXiv:1201.3974.

Parameters:

status (Optional[Tensor]) – external randomness, with shape [nqubits], defaults to None

Returns:

Sampled base-d string and the corresponding theoretical probability.

Return type:

Tuple[str, float]

prepend(c: AbstractCircuit) AbstractCircuitΒΆ

prepend circuit c before

Parameters:

c (BaseCircuit) – The other circuit to be prepended

Returns:

The composed circuit

Return type:

BaseCircuit

probability() Any[source]ΒΆ

get the d^n length probability vector over computational basis

Returns:

probability vector of shape [dim**n]

Return type:

Tensor

projected_subsystem(traceout: Any, left: Tuple[int, ...]) Any[source]ΒΆ

remaining wavefunction or density matrix on sites in left, with other sites fixed to given digits (0..d-1) as indicated by traceout

Parameters:
  • traceout (Tensor) – can be jitted

  • left (Tuple) – cannot be jitted

Returns:

_description_

Return type:

Tensor

quvector() QuVectorΒΆ

Get the representation of the output state in the form of QuVector while maintaining the circuit uncomputed

Returns:

QuVector representation of the output state from the circuit

Return type:

QuVector

readouterror_bs(readout_error: Sequence[Any] | None = None, p: Any | None = None) Any[source]ΒΆ

Apply readout error to original probabilities of bit string and return the noisy probabilities.

Example:

>>> readout_error = []
>>> readout_error.append([0.9,0.75])  # readout error for qubit 0, [p0|0,p1|1]
>>> readout_error.append([0.4,0.7])   # readout error for qubit 1, [p0|0,p1|1]
Parameters:
  • readout_error (Optional[Sequence[Any]]. Tensor, List, Tuple) – list of readout error for each qubits.

  • p (Optional[Any]) – probabilities of bit string

Return type:

Tensor

replace_inputs(inputs: Any) None[source]ΒΆ

Replace the input state with the circuit structure unchanged.

Parameters:

inputs (Tensor) – Input wavefunction.

reset_instruction(*index: int) NoneΒΆ

add a reset instruction flag, no effect on numerical simulation

Parameters:

index (int) – the corresponding qubits

sample(batch: int | None = None, allow_state: bool = False, readout_error: Sequence[Any] | None = None, format: str | None = None, random_generator: Any | None = None, status: Any | None = None, jittable: bool = True) Any[source]ΒΆ

batched sampling from state or circuit tensor network directly

Parameters:
  • batch (Optional[int], optional) – number of samples, defaults to None

  • allow_state (bool, optional) – if true, we sample from the final state if memory allows, True is preferred, defaults to False

  • readout_error (Optional[Sequence[Any]]. Tensor, List, Tuple) – readout_error, defaults to None

  • format (Optional[str]) –

    sample format, defaults to None as backward compatibility check the doc in tensorcircuit.quantum.measurement_results() Six formats of measurement counts results:

    ”sample_int”: # np.array([0, 0])

    ”sample_bin”: # [np.array([1, 0]), np.array([1, 0])]

    ”count_vector”: # np.array([2, 0, 0, 0])

    ”count_tuple”: # (np.array([0]), np.array([2]))

    ”count_dict_bin”: # {β€œ00”: 2, β€œ01”: 0, β€œ10”: 0, β€œ11”: 0}

    for cases din [11, 36], use 0-9A-Z digits (e.g., β€˜A’ -> 10, …, β€˜Z’ -> 35);

    ”count_dict_int”: # {0: 2, 1: 0, 2: 0, 3: 0}

  • format – alias for the argument format

  • random_generator (Optional[Any], optional) – random generator, defaults to None

  • status (Optional[Tensor]) – external randomness given by tensor uniformly from [0, 1], if set, can overwrite random_generator, shape [batch] for allow_state=True and shape [batch, nqubits] for allow_state=False using perfect sampling implementation

  • jittable (bool, defaults true) – when converting to count, whether keep the full size. if false, may be conflict external jit, if true, may fail for large scale system with actual limited count results

Returns:

List (if batch) of tuple (binary configuration tensor and corresponding probability) if the format is None, and consistent with format when given

Return type:

Any

sample_detector(shots: int = 1, batch: int | None = None, allow_state: bool = False, status: Any | None = None, seed: int | None = None, **kws: Any) Any[source]ΒΆ

Sample detector outcomes from instruction-annotated circuits.

Parameters:
  • shots (int, optional) – Number of samples to draw, defaults to 1.

  • batch (int, optional) – Number of samples to process in a single batch, defaults to None (equal to shots).

  • allow_state (bool, optional) – If True, uses the full detector probability distribution for sampling (faster but memory-intensive); if False, uses an autoregressive sampling method based on the tensor network, defaults to False.

  • status (Optional[Tensor], optional) – Random numbers in [0, 1] used for sampling, defaults to None. If allow_state is True, shape should be [shots] or [shots, 1]; if allow_state is False, shape should be [shots, num_detectors].

  • seed (Optional[int], optional) – Random seed for sampling, defaults to None.

Returns:

A boolean tensor containing the sampled detector outcomes with shape [shots, num_detectors].

Return type:

Tensor

sample_expectation_ps(x: Sequence[int] | None = None, y: Sequence[int] | None = None, z: Sequence[int] | None = None, shots: int | None = None, random_generator: Any | None = None, status: Any | None = None, readout_error: Sequence[Any] | None = None, noise_conf: Any | None = None, nmc: int = 1000, statusc: Any | None = None, **kws: Any) Any[source]ΒΆ

Compute the expectation with given Pauli string with measurement shots numbers

Example:

>>> c = tc.Circuit(2)
>>> c.H(0)
>>> c.rx(1, theta=np.pi/2)
>>> c.sample_expectation_ps(x=[0], y=[1])
-0.99999976
>>> readout_error = []
>>> readout_error.append([0.9,0.75])
>>> readout_error.append([0.4,0.7])
>>> c.sample_expectation_ps(x=[0], y=[1],readout_error = readout_error)
>>> c = tc.Circuit(2)
>>> c.cnot(0, 1)
>>> c.rx(0, theta=0.4)
>>> c.rx(1, theta=0.8)
>>> c.h(0)
>>> c.h(1)
>>> error1 = tc.channels.generaldepolarizingchannel(0.1, 1)
>>> error2 = tc.channels.generaldepolarizingchannel(0.06, 2)
>>> readout_error = [[0.9, 0.75],[0.4, 0.7]]
>>> noise_conf = NoiseConf()
>>> noise_conf.add_noise("rx", error1)
>>> noise_conf.add_noise("cnot", [error2], [[0, 1]])
>>> noise_conf.add_noise("readout", readout_error)
>>> c.sample_expectation_ps(x=[0], noise_conf=noise_conf, nmc=10000)
0.44766843
Parameters:
  • x (Optional[Sequence[int]], optional) – index for Pauli X, defaults to None

  • y (Optional[Sequence[int]], optional) – index for Pauli Y, defaults to None

  • z (Optional[Sequence[int]], optional) – index for Pauli Z, defaults to None

  • shots (Optional[int], optional) – number of measurement shots, defaults to None, indicating analytical result

  • random_generator (Optional[Any]) – random_generator, defaults to None

  • status (Optional[Tensor]) – external randomness given by tensor uniformly from [0, 1], if set, can overwrite random_generator

  • readout_error (Optional[Sequence[Any]]. Tensor, List, Tuple) – readout_error, defaults to None. Overrided if noise_conf is provided.

  • noise_conf (Optional[NoiseConf], optional) – Noise Configuration, defaults to None

  • nmc (int, optional) – repetition time for Monte Carlo sampling for noisfy calculation, defaults to 1000

  • statusc (Optional[Tensor], optional) – external randomness given by tensor uniformly from [0, 1], defaults to None, used for noisfy circuit sampling

Returns:

[description]

Return type:

Tensor

select_gate(which: Any, kraus: Sequence[Gate], *index: int) NoneΒΆ

Apply which-th gate from kraus list, i.e. apply kraus[which]

Parameters:
  • which (Tensor) – Tensor of shape [] and dtype int

  • kraus (Sequence[Gate]) – A list of gate in the form of tc.gate or Tensor

  • index (int) – the qubit lines the gate applied on

sexpps(x: Sequence[int] | None = None, y: Sequence[int] | None = None, z: Sequence[int] | None = None, shots: int | None = None, random_generator: Any | None = None, status: Any | None = None, readout_error: Sequence[Any] | None = None, noise_conf: Any | None = None, nmc: int = 1000, statusc: Any | None = None, **kws: Any) AnyΒΆ

Compute the expectation with given Pauli string with measurement shots numbers

Example:

>>> c = tc.Circuit(2)
>>> c.H(0)
>>> c.rx(1, theta=np.pi/2)
>>> c.sample_expectation_ps(x=[0], y=[1])
-0.99999976
>>> readout_error = []
>>> readout_error.append([0.9,0.75])
>>> readout_error.append([0.4,0.7])
>>> c.sample_expectation_ps(x=[0], y=[1],readout_error = readout_error)
>>> c = tc.Circuit(2)
>>> c.cnot(0, 1)
>>> c.rx(0, theta=0.4)
>>> c.rx(1, theta=0.8)
>>> c.h(0)
>>> c.h(1)
>>> error1 = tc.channels.generaldepolarizingchannel(0.1, 1)
>>> error2 = tc.channels.generaldepolarizingchannel(0.06, 2)
>>> readout_error = [[0.9, 0.75],[0.4, 0.7]]
>>> noise_conf = NoiseConf()
>>> noise_conf.add_noise("rx", error1)
>>> noise_conf.add_noise("cnot", [error2], [[0, 1]])
>>> noise_conf.add_noise("readout", readout_error)
>>> c.sample_expectation_ps(x=[0], noise_conf=noise_conf, nmc=10000)
0.44766843
Parameters:
  • x (Optional[Sequence[int]], optional) – index for Pauli X, defaults to None

  • y (Optional[Sequence[int]], optional) – index for Pauli Y, defaults to None

  • z (Optional[Sequence[int]], optional) – index for Pauli Z, defaults to None

  • shots (Optional[int], optional) – number of measurement shots, defaults to None, indicating analytical result

  • random_generator (Optional[Any]) – random_generator, defaults to None

  • status (Optional[Tensor]) – external randomness given by tensor uniformly from [0, 1], if set, can overwrite random_generator

  • readout_error (Optional[Sequence[Any]]. Tensor, List, Tuple) – readout_error, defaults to None. Overrided if noise_conf is provided.

  • noise_conf (Optional[NoiseConf], optional) – Noise Configuration, defaults to None

  • nmc (int, optional) – repetition time for Monte Carlo sampling for noisfy calculation, defaults to 1000

  • statusc (Optional[Tensor], optional) – external randomness given by tensor uniformly from [0, 1], defaults to None, used for noisfy circuit sampling

Returns:

[description]

Return type:

Tensor

sgates = ['i', 'x', 'y', 'z', 'h', 't', 's', 'td', 'sd', 'wroot', 'cnot', 'cz', 'swap', 'cy', 'ox', 'oy', 'oz', 'toffoli', 'fredkin']ΒΆ
split: Dict[str, Any] | NoneΒΆ
static standardize_gate(name: str) strΒΆ

standardize the gate name to tc common gate sets

Parameters:

name (str) – non-standard gate name

Returns:

the standard gate name

Return type:

str

tex(**kws: Any) strΒΆ

Generate latex string based on quantikz latex package

Returns:

Latex string that can be directly compiled via, e.g. latexit

Return type:

str

to_cirq(enable_instruction: bool = False) AnyΒΆ

Translate tc.Circuit to a cirq circuit object.

Parameters:

enable_instruction (bool, defaults to False) – whether also export measurement and reset instructions

Returns:

A cirq circuit of this circuit.

to_graphviz(graph: Graph = None, include_all_names: bool = False, engine: str = 'neato') Graph[source]ΒΆ

Not an ideal visualization for quantum circuit, but reserve here as a general approach to show the tensornetwork [Deprecated, use Circuit.vis_tex or Circuit.draw instead]

to_json(file: str | None = None, simplified: bool = False) AnyΒΆ

circuit dumps to json

Parameters:
  • file (Optional[str], optional) – file str to dump the json to, defaults to None, return the json str

  • simplified (bool) – If False, keep all info for each gate, defaults to be False. If True, suitable for IO since less information is required

Returns:

None if dumps to file otherwise the json str

Return type:

Any

to_openqasm(**kws: Any) strΒΆ

transform circuit to openqasm via qiskit circuit, see https://qiskit.org/documentation/stubs/qiskit.circuit.QuantumCircuit.qasm.html for usage on possible options for kws

Returns:

circuit representation in openqasm format

Return type:

str

to_openqasm_file(file: str, **kws: Any) NoneΒΆ

save the circuit to openqasm file

Parameters:

file (str) – the file path to save the circuit

to_qir() List[Dict[str, Any]]ΒΆ

Return the quantum intermediate representation of the circuit.

Example:

>>> c = tc.Circuit(2)
>>> c.CNOT(0, 1)
>>> c.to_qir()
[{'gatef': cnot, 'gate': Gate(
    name: 'cnot',
    tensor:
        array([[[[1.+0.j, 0.+0.j],
                [0.+0.j, 0.+0.j]],

                [[0.+0.j, 1.+0.j],
                [0.+0.j, 0.+0.j]]],


            [[[0.+0.j, 0.+0.j],
                [0.+0.j, 1.+0.j]],

                [[0.+0.j, 0.+0.j],
                [1.+0.j, 0.+0.j]]]], dtype=complex64),
    edges: [
        Edge(Dangling Edge)[0],
        Edge(Dangling Edge)[1],
        Edge('cnot'[2] -> 'qb-1'[0] ),
        Edge('cnot'[3] -> 'qb-2'[0] )
    ]), 'index': (0, 1), 'name': 'cnot', 'split': None, 'mpo': False}]
Returns:

The quantum intermediate representation of the circuit.

Return type:

List[Dict[str, Any]]

to_qiskit(enable_instruction: bool = False, enable_inputs: bool = False) AnyΒΆ

Translate tc.Circuit to a qiskit QuantumCircuit object.

Parameters:
  • enable_instruction (bool, defaults to False) – whether also export measurement and reset instructions

  • enable_inputs (bool, defaults to False) – whether also export the inputs

Returns:

A qiskit object of this circuit.

vgates = ['r', 'cr', 'u', 'cu', 'rx', 'ry', 'rz', 'phase', 'rxx', 'ryy', 'rzz', 'cphase', 'crx', 'cry', 'crz', 'orx', 'ory', 'orz', 'iswap', 'any', 'exp', 'exp1', 'su4']ΒΆ
vis_tex(**kws: Any) strΒΆ

Generate latex string based on quantikz latex package

Returns:

Latex string that can be directly compiled via, e.g. latexit

Return type:

str