zxcalc / pyzx

Python library for quantum circuit rewriting and optimisation using the ZX-calculus
Apache License 2.0
385 stars 116 forks source link

pyzx unable to optimize when circuit contains rx or sx gate #215

Open Zonaldo7 opened 6 months ago

Zonaldo7 commented 6 months ago

Using the most recent version of pyzx (0.8.0), with the following code

import pyzx as zx
from pyzx.circuit import Circuit, CNOT
c = Circuit(1)
c.add_gate('XPhase', 0, phase=3/4)
zx.draw(c)
zx.full_optimize(c.to_basic_gates())

and it returns with an error " Unknown gate XPhase(0,phase=0.75). Maybe simplify the gates with circuit.to_basic_gates()? "

jvdwetering commented 6 months ago

phase is expecting a Fraction, not a float. Try Fraction(3,4) instead.

dlyongemallo commented 6 months ago

The problem reproduces even with Fraction(3,4) or, for that matter, with Fraction(1,1).

It does seem like the parse_gate function, which throws the error, does not handle XPhase. It even (implicitly) says so in the comments: https://github.com/Quantomatic/pyzx/blob/4e1ab6edbb9c6de12155b4e3c26e709de1fa8a0e/pyzx/optimize.py#L405

(The comment must be out-of-date, though, because the logic supports the NOT gate, even though it's not listed in the comment.)

Zonaldo7 commented 6 months ago

Thanks for the clarification. Also, when reading a circuit from a .qasm file that includes RX gates, it shows the same error using the optimization function. After I further check in circuit.gate, it seems all the phases in XPhase gates have already been in the format of fractions. The .qasm file is shown as below.

OPENQASM 2.0;
include "qelib1.inc";
qreg q[3];
h q[0];
h q[1];
h q[2];
cx q[0],q[2];
rz(pi*1.79986) q[2];
cx q[0],q[2];
cx q[0],q[1];
cx q[1],q[2];
rz(pi*-3.59973) q[2];
cx q[1],q[2];
cx q[0],q[1];
rx(pi*0.545344) q[2];
rz(pi*-5.39959) q[1];
rx(pi*0.545344) q[0];
rx(pi*0.545344) q[1];

And the pyzx code is listed as follows.

import pyzx as zx
c_zx = zx.Circuit.from_qasm_file("qaoa.qasm")
zx.optimize.full_optimize(c_zx.to_basic_gates())

which returns an error:

Unknown gate XPhase(2,phase=8521/15625). Maybe simplify the gates with circuit.to_basic_gates()?

As a result, I utilize circuit.gate to check the phase of the XPhase gates

for g in c_zx.gates:
    if g.name == "XPhase":
        print(type(g.phase))

And the output is

<class 'fractions.Fraction'>
<class 'fractions.Fraction'>
<class 'fractions.Fraction'>