Skip to content

Quantum Phase Estimation

The quantum phase estimation (QPE) function estimates the phase of an eigenvector of a unitary function. More precisely, given a unitary function \(F\) and an input containing a quantum register with a state \(|\psi\rangle\) such that \(F(|\psi\rangle)=e^{2\pi i\nu}|\psi\rangle\), the phase estimation function outputs an estimation of \(\nu\) as a fixed-point binary number.

Phase estimation is frequently used as a subroutine in other quantum algorithms such as Shor's algorithm and quantum algorithms for solving linear systems of equations. Theoretical details are in Ref. [1].

Syntax

Function: PhaseEstimation

Parameters:

  • size: int
  • unitary: str
  • unitary_params: FunctionParams

The size argument provides the number of digits in the fixed-point representation of the phase.

The unitary argument may be omitted when using the SDK and should otherwise contain the name of the function \(F\).

The unitary_params argument provides the function parameters of the unitary function \(F\).

Example

This example shows how to perform a simple phase estimation:

  1. Initialize the state "10" over two qubits using XGate on the first qubit.
  2. Apply a phase estimation on the matrix.
\[ \begin{pmatrix} 0 & 0 & 0 & 0 \\ 0 & \tfrac{1}{4} & 0 & 0 \\ 0 & 0 & \tfrac{1}{2} & 0 \\ 0 & 0 & 0 & \tfrac{3}{4} \\ \end{pmatrix} \]

The output register is in the state "10", corresponding to the number 0.10. This is \(\frac{1}{2}\) in binary, implying that \(\nu=\frac{1}{2}\), as expected for input state "10".

{
  "logic_flow": [
    {
      "function": "XGate",
      "function_params": {},
      "outputs": {
        "TARGET": "x_qpe"
      }
    },
    {
      "function": "PhaseEstimation",
      "function_params": {
        "size": 2,
        "unitary": "Exponentiation",
        "unitary_params": {
          "pauli_operator": {
            "pauli_list": [
              ["ZI", -0.125],
              ["IZ", -0.25],
              ["II", 0.375]
            ]
          },
          "evolution_coefficient": -6.283185307179586
        }
      },
      "inputs": {
        "IN[0]": "x_qpe"
      }
    }
  ],
  "preferences": {
    "draw_at_level": -1
  }
}
from math import pi
from classiq.builtin_functions.exponentiation import PauliOperator
from classiq.builtin_functions import Exponentiation, PhaseEstimation, XGate
from classiq import Model

model = Model()
model.preferences.draw_image = True

x_qpe = model.XGate(params=XGate())
qpe_out = model.PhaseEstimation(
    params=PhaseEstimation(
        size=2,
        unitary_params=Exponentiation(
            pauli_operator=PauliOperator(
                pauli_list=[
                    ("ZI", -0.125),
                    ("IZ", -0.25),
                    ("II", 0.375),
                ]
            ),
            evolution_coefficient=-2 * pi,
        ),
    ),
    in_wires={"IN[0]": x_qpe["TARGET"]},
)
model.preferences.draw_at_level = -1
circuit = model.synthesize()
circuit.show_interactive()

 Mcx example

Using PhaseEstimation with Exponentiation

Specify parameters using the ExponentiationSpecification object, which bypasses the parameters of the Exponentiation. See Exponentiation.

PhaseEstimation:

  • exponentiation_specification: Optional[ExponentiationSpecification]

The exponentiation_specification takes one of these options:

ExponentiationSpecification:

  • scaling: Optional[ExponentiationScaling]
  • max_depths: Tuple[int, ...]

max_depths sets the depth of the ExponentiationConstraints directly for each qubit of the phase estimation, starting from the most significant bit.

scaling provides a rule for determining the depth.

ExponentiationScaling:

  • max_depth: int
  • max_depth_scaling_factor: float

max_depth determines the depth of the most significant bit.

max_depth_scaling_factor provides an exponential growth factor for consecutive qubits.

Inputting exponentiation_specification automatically sets ExponentiationOptimization.MINIMIZE_ERROR.

Using Custom Functions and Composite Functions

Define custom functions or composite functions in the unitary_params argument of PhaseEstimation. Make sure the input and output names are identical.

If using the textual model to provide a custom or composite function, you must define the inputs and outputs in the logic flow as defined in the function.

Define the parameters using the unitary_params argument of the CustomFunction:

  • input_decls: ArithmeticIODict
  • output_decls: ArithmeticIODict

Example

{
    "function_library": {
        "name": "my_library",
        "functions": [
            {
                "name": "my_custom_function",
                "implementations": [
                    {
                        "serialized_circuit": "OPENQASM 2.0;\ninclude \"qelib1.inc\";\nqreg q[1];\nh q[0];"
                    }
                ],
                "register_mapping": {
                    "output_registers": [{"name": "custom_output", "qubits": [0]}],
                    "input_registers": [{"name": "custom_input", "qubits": [0]}]
                }
            }
        ]
    },
    "logic_flow": [
        {
            "function": "PhaseEstimation",
            "function_params": {
                "unitary": "my_custom_function",
                "unitary_params": {
                    "input_decls": {"custom_input": {"size": 1}},
                    "output_decls": {"custom_output": {"size": 1}}
                },
                "size": 2
            }
        }
    ]
}
from classiq import FunctionLibrary, QReg, qfunc
from classiq.builtin_functions import PhaseEstimation
from classiq import Model


@qfunc
def my_custom(custom_input: QReg[1]) -> QReg[1]:
    return 'OPENQASM 2.0;\ninclude "qelib1.inc";\nqreg q[1];\nh q[0];\n'


func_library = FunctionLibrary()
func_library.add_function(my_custom)

qpe_params = PhaseEstimation(
    size=2, unitary="my_custom", unitary_params=func_library.get_function("my_custom")
)

model = Model()
model.include_library(func_library)
model.PhaseEstimation(params=qpe_params)

model.preferences.draw_at_level = -1
circuit = model.synthesize()
circuit.show_interactive()

 QPE_Custom example

References

[1] A. Yu. Kitaev Barenco et al, Quantum Measurements and the Abelian Stabilizer Problem, (1995). https://doi.org/10.48550/arXiv.quant-ph/9511026