Skip to content

qiu_quantum_computing.phase_propagator.direct

Direct phase circuits, applying e^(i coef x^k) for powers k up to 3.

The integer x encoded by a basis state is a weighted sum of its bits, see qubit_encoding. Expanding x^k with x_i^2 = x_i for bits gives a sum of products of at most k bits, each applied as a (multi-)controlled phase gate.

Classes:

Functions:

Attributes:

DIRECT_PHASES module-attribute

DIRECT_PHASES: dict[int, type[DirectPhase]] = {phase.exponent: phase for phase in (Order1DirectPhase, Order2DirectPhase, Order3DirectPhase)}

The direct phase circuits by exponent.

DirectPhase

DirectPhase(num_qubits: int, coef: float, ordering: IndexOrdering)

Bases: QuantumCircuit

Base class of the circuits applying e^(i coef x^exponent).

Subclasses define the exponent and apply the phases for the bit weights in _apply_phases.

Parameters:

  • num_qubits (int) –

    The number of qubits encoding the integers.

  • coef (float) –

    The coefficient of the phase.

  • ordering (IndexOrdering) –

    The index ordering encoding the integers, see qubit_encoding.

Attributes:

  • exponent (int) –

    The power of the encoded integer in the phase.

  • coef (float) –

    The coefficient of the phase.

  • ordering (IndexOrdering) –

    The index ordering encoding the integers in the basis states.

Source code in packages/qiu-quantum-computing/src/qiu_quantum_computing/phase_propagator/direct.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def __init__(self, num_qubits: int, coef: float, ordering: IndexOrdering) -> None:
    """Initialize the phase circuit.

    Args:
        num_qubits: The number of qubits encoding the integers.
        coef: The coefficient of the phase.
        ordering: The index ordering encoding the integers, see `qubit_encoding`.
    """
    super().__init__(num_qubits, name=f"direct_phase_{self.exponent}")
    self.coef = coef
    self.ordering = IndexOrdering(ordering)

    flip_msb = is_msb_flipped(self.ordering)
    if flip_msb:
        self.x(num_qubits - 1)
    self._apply_phases(coef, bit_weights(num_qubits, self.ordering))
    if flip_msb:
        self.x(num_qubits - 1)

exponent class-attribute

exponent: int

The power of the encoded integer in the phase.

Not named power, which would shadow QuantumCircuit.power.

coef instance-attribute

coef: float = coef

The coefficient of the phase.

ordering instance-attribute

ordering: IndexOrdering = IndexOrdering(ordering)

The index ordering encoding the integers in the basis states.

Order1DirectPhase

Order1DirectPhase(num_qubits: int, coef: float, ordering: IndexOrdering)

Bases: DirectPhase

The phase circuit e^(i coef x), with x = sum_i w_i x_i.

Attributes:

Source code in packages/qiu-quantum-computing/src/qiu_quantum_computing/phase_propagator/direct.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def __init__(self, num_qubits: int, coef: float, ordering: IndexOrdering) -> None:
    """Initialize the phase circuit.

    Args:
        num_qubits: The number of qubits encoding the integers.
        coef: The coefficient of the phase.
        ordering: The index ordering encoding the integers, see `qubit_encoding`.
    """
    super().__init__(num_qubits, name=f"direct_phase_{self.exponent}")
    self.coef = coef
    self.ordering = IndexOrdering(ordering)

    flip_msb = is_msb_flipped(self.ordering)
    if flip_msb:
        self.x(num_qubits - 1)
    self._apply_phases(coef, bit_weights(num_qubits, self.ordering))
    if flip_msb:
        self.x(num_qubits - 1)

exponent class-attribute instance-attribute

exponent = 1

Order2DirectPhase

Order2DirectPhase(num_qubits: int, coef: float, ordering: IndexOrdering)

Bases: DirectPhase

The phase circuit e^(i coef x^2).

With x^2 = sum_i w_i^2 x_i + 2 sum_(j<i) w_i w_j x_i x_j.

Attributes:

Source code in packages/qiu-quantum-computing/src/qiu_quantum_computing/phase_propagator/direct.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def __init__(self, num_qubits: int, coef: float, ordering: IndexOrdering) -> None:
    """Initialize the phase circuit.

    Args:
        num_qubits: The number of qubits encoding the integers.
        coef: The coefficient of the phase.
        ordering: The index ordering encoding the integers, see `qubit_encoding`.
    """
    super().__init__(num_qubits, name=f"direct_phase_{self.exponent}")
    self.coef = coef
    self.ordering = IndexOrdering(ordering)

    flip_msb = is_msb_flipped(self.ordering)
    if flip_msb:
        self.x(num_qubits - 1)
    self._apply_phases(coef, bit_weights(num_qubits, self.ordering))
    if flip_msb:
        self.x(num_qubits - 1)

exponent class-attribute instance-attribute

exponent = 2

Order3DirectPhase

Order3DirectPhase(num_qubits: int, coef: float, ordering: IndexOrdering)

Bases: DirectPhase

The phase circuit e^(i coef x^3).

With x^3 = sum_i w_i^3 x_i + 3 sum_(j<i) (w_i^2 w_j + w_i w_j^2) x_i x_j + 6 sum_(k<j<i) w_i w_j w_k x_i x_j x_k.

Attributes:

Source code in packages/qiu-quantum-computing/src/qiu_quantum_computing/phase_propagator/direct.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
def __init__(self, num_qubits: int, coef: float, ordering: IndexOrdering) -> None:
    """Initialize the phase circuit.

    Args:
        num_qubits: The number of qubits encoding the integers.
        coef: The coefficient of the phase.
        ordering: The index ordering encoding the integers, see `qubit_encoding`.
    """
    super().__init__(num_qubits, name=f"direct_phase_{self.exponent}")
    self.coef = coef
    self.ordering = IndexOrdering(ordering)

    flip_msb = is_msb_flipped(self.ordering)
    if flip_msb:
        self.x(num_qubits - 1)
    self._apply_phases(coef, bit_weights(num_qubits, self.ordering))
    if flip_msb:
        self.x(num_qubits - 1)

exponent class-attribute instance-attribute

exponent = 3

polynomial_phase_circuit

polynomial_phase_circuit(signal: PolynomialSignal) -> QuantumCircuit

Return the circuit applying e^(i signal(x)) to the basis states of its axis.

The phase of the basis state |k> is the signal at the axis value of the sample k, i.e. e^(i alpha x_k^power).

Parameters:

  • signal (PolynomialSignal) –

    A monomial of power at most 3, on an axis of 2**n samples.

Returns:

Raises:

  • TypeError –

    If the signal is not a PolynomialSignal, e.g. a sum of monomials, whose circuits are composed instead.

  • NotImplementedError –

    If its power is larger than 3.

Source code in packages/qiu-quantum-computing/src/qiu_quantum_computing/phase_propagator/direct.py
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
def polynomial_phase_circuit(signal: PolynomialSignal) -> QuantumCircuit:
    """Return the circuit applying `e^(i signal(x))` to the basis states of its axis.

    The phase of the basis state `|k>` is the signal at the axis value of the
    sample `k`, i.e. `e^(i alpha x_k^power)`.

    Args:
        signal: A monomial of power at most 3, on an axis of `2**n` samples.

    Returns:
        The phase circuit on `n` qubits.

    Raises:
        TypeError: If the signal is not a `PolynomialSignal`, e.g. a sum of monomials,
            whose circuits are composed instead.
        NotImplementedError: If its power is larger than 3.
    """
    if not isinstance(signal, PolynomialSignal):
        raise TypeError(
            "Direct phase circuits need a PolynomialSignal, i.e. a monomial, got "
            f"{type(signal).__name__}; compose the circuits of its monomials instead."
        )
    num_qubits = num_qubits_of(signal.axis)

    if signal.power == 0:
        circuit = QuantumCircuit(num_qubits, name="direct_phase_0")
        circuit.global_phase = signal.alpha
        return circuit

    phase = DIRECT_PHASES.get(signal.power)
    if phase is None:
        raise NotImplementedError(
            f"Direct phase circuits exist for powers up to 3, got {signal.power}."
        )
    return phase(num_qubits, signal.effective_alpha, signal.axis.ordering)