Linear System Question

Hello,

I’ve seen topics regarding solving systems of linear equations and formulas for Ax=b with quantum algorithms that are solving for the x if we have A and b. I’m wondering if we are just wanting to apply x on a matrix A, how would we go about that in a quantum algorithm?

Thank you

Hi @movingwaters , welcome to the Forum :waving_hand:

This is a really good question! The answer depends on whether or not your matrix A is unitary.

First, remember that applying a gate to a quantum state is applying a matrix to that state, which itself is represented as a vector.

You would start with encoding your vector x into the quantum computer, for example using qp.AmplitudeEmbedding.

If the matrix A is unitary then you can directly implement it as a quantum gate. If the matrix’s dimensions are a power of two you can add it to your circuit with qp.QubitUnitary.

If your matrix A is non-unitary (general case) then you can use block encodings. This means embedding A as a sub-block of a larger unitary U, acting on a larger system which includes ancilla qubits. In practice we actually embed A/\alpha (where \alpha \geq |A|) so that the final unitary is actually unitary. You can learn more about Block Encodings and how to use them in PennyLane in the PennyLane Codebook.

The procedure is:

  1. Prepare ancilla qubits in |0\rangle
  2. Encode |x\rangle in the system register
  3. Apply the unitary U
  4. Measure the ancilla.

If you get |0\rangle, the system register holds A|x\rangle / \alpha (up to normalization)

The success probability is |A|x\rangle|^2 / \alpha^2, so amplitude amplification can boost this.

Here’s a full code example you can use.

import pennylane as qp
import numpy as np

# Define your matrix A and vector x
A = np.array([
    [0.3, 0.5],
    [0.1, 0.4]
])

x = np.array([0.6, 0.8])

# Normalize x (required for AmplitudeEmbedding)
x_norm = np.linalg.norm(x)
x_normalized = x / x_norm

# Create the block encoding operator
block_op = qp.BlockEncode(A, wires=[0, 1])

# Check PennyLane's auto-normalization factor
norm_factor = block_op.hyperparameters["norm"]
effective_norm = max(norm_factor, 1.0)

# Build the circuit
dev = qp.device("default.qubit")

@qp.qnode(dev)
def apply_A_to_x():
    # Wire 0 = ancilla, Wire 1 = system
    qp.AmplitudeEmbedding(x_normalized, wires=1)
    qp.BlockEncode(A, wires=[0, 1])
    return qp.state()

# Execute and post-select
statevector = apply_A_to_x()
post_selected = statevector[:2]  # ancilla = |0> subspace

# Recover A @ x
Ax_result = effective_norm * x_norm * post_selected
print(f"Quantum result: {Ax_result.real}")   # [0.58, 0.38]
print(f"Classical A@x:  {(A @ x).real}")     # [0.58, 0.38]

I hope this helps!

Hello,

Thank you for the explanation and example, it makes a lot of sense and is really cool to see how it all works!

1 Like