Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add conditional parameter to gate counting #1662

Merged
merged 7 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions pytket/binders/circuit/Circuit/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,15 +472,22 @@ void def_circuit(py::class_<Circuit, std::shared_ptr<Circuit>> &pyCircuit) {
"\n\n:return: the circuit depth")
.def(
"n_gates_of_type",
[](const Circuit &circ, const OpType &_type) {
return circ.count_gates(_type);
[](const Circuit &circ, const OpType &_type, const bool conditional) {
if (conditional) {
return circ.count_gates(_type) +
circ.count_gates_conditional(_type);
} else {
return circ.count_gates(_type);
}
},
"Returns the number of vertices in the dag of a given "
"operation type.\n\n>>> c.CX(0,1)\n>>> c.H(0)\n>>> "
"c.CX(0,1)\n>>> c.n_gates_of_type(OpType.CX)\n2\n\n:param "
"type: The operation type to search for\n:return: the "
"number of operations matching `type`",
py::arg("type"))
"type: The operation type to search for\n:param "
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"type: The operation type to search for\n:param "
"type: The operation type to search for\n\n:param "

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 127a9cc

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this for the return, too.

"conditional: if set to true, conditional gates will "
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think include_conditional would be a better name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 127a9cc

"be counted, too\n:return: the number of operations "
"matching `type`",
py::arg("type"), py::arg("conditional") = false)
.def(
"n_1qb_gates",
[](const Circuit &circ) { return circ.count_n_qubit_gates(1); },
Expand Down
2 changes: 1 addition & 1 deletion pytket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def requirements(self):
self.requires("pybind11_json/0.2.14")
self.requires("symengine/0.12.0")
self.requires("tkassert/0.3.4@tket/stable")
self.requires("tket/1.3.39@tket/stable")
self.requires("tket/1.3.40@tket/stable")
self.requires("tklog/0.3.3@tket/stable")
self.requires("tkrng/0.3.3@tket/stable")
self.requires("tktokenswap/0.3.9@tket/stable")
Expand Down
2 changes: 2 additions & 0 deletions pytket/docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Fixes:
* Fix `maxwidth` parameter of `circuit_from_qasm_str`
* Add `scratch_reg_resize_pass` to `circuit_from_qasm_str`
* Reject incompete classical registers in pytket to qasm conversion
* Add parameter `conditional` to `n_gates_of_type` to include
conditional gates in the count

1.34.0 (October 2024)
---------------------
Expand Down
3 changes: 2 additions & 1 deletion pytket/pytket/_tket/circuit.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2235,7 +2235,7 @@ class Circuit:
"""
Returns the number of vertices in the dag with two quantum edges.Ignores Input, Create, Output, Discard, Reset, Measure and Barrier vertices.
"""
def n_gates_of_type(self, type: OpType) -> int:
def n_gates_of_type(self, type: OpType, conditional: bool = False) -> int:
"""
Returns the number of vertices in the dag of a given operation type.

Expand All @@ -2246,6 +2246,7 @@ class Circuit:
2

:param type: The operation type to search for
:param conditional: if set to true, conditional gates will be counted, too
:return: the number of operations matching `type`
"""
def n_nqb_gates(self, size: int) -> int:
Expand Down
16 changes: 16 additions & 0 deletions pytket/tests/circuit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1265,6 +1265,22 @@ def test_counting_n_qubit_gates() -> None:
assert c.n_nqb_gates(5) == 1


def test_counting_conditional_gates() -> None:
c = Circuit(5, 2).X(0).H(1).Y(2).Z(3).S(4).CX(0, 1).CX(1, 2).CX(2, 3).CX(3, 4)
c.add_gate(OpType.H, [Qubit(0)], condition=Bit(0))
c.add_gate(OpType.H, [Qubit(1)], condition=(Bit(0) & Bit(1)))
c.add_gate(OpType.CX, [Qubit(0), Qubit(1)], condition=Bit(1))
assert c.n_gates_of_type(OpType.H, conditional=True) == 3
assert c.n_gates_of_type(OpType.H, conditional=False) == 1
assert c.n_gates_of_type(OpType.H) == 1
assert c.n_gates_of_type(OpType.X, conditional=True) == 1
assert c.n_gates_of_type(OpType.X, conditional=False) == 1
assert c.n_gates_of_type(OpType.X) == 1
assert c.n_gates_of_type(OpType.CX, conditional=True) == 5
assert c.n_gates_of_type(OpType.CX, conditional=False) == 4
assert c.n_gates_of_type(OpType.CX) == 4


def test_qcontrol_box_constructors() -> None:
# only one argument
qcbox1 = QControlBox(Op.create(OpType.S))
Expand Down
2 changes: 1 addition & 1 deletion tket/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

class TketConan(ConanFile):
name = "tket"
version = "1.3.39"
version = "1.3.40"
package_type = "library"
license = "Apache 2"
homepage = "https://github.com/CQCL/tket"
Expand Down
1 change: 1 addition & 0 deletions tket/include/tket/Circuit/Circuit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1119,6 +1119,7 @@ class Circuit {
std::map<OpType, unsigned> op_counts() const;

unsigned count_gates(const OpType &op_type) const;
unsigned count_gates_conditional(const OpType &op_type) const;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should just add an optional argument to count_gates() to make it count conditionals as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in 127a9cc

VertexSet get_gates_of_type(const OpType &op_type) const;

/**
Expand Down
13 changes: 13 additions & 0 deletions tket/src/Circuit/macro_circ_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@ unsigned Circuit::count_gates(const OpType& op_type) const {
return counter;
}

unsigned Circuit::count_gates_conditional(const OpType& op_type) const {
unsigned counter = 0;
BGL_FORALL_VERTICES(v, dag, DAG) {
if (get_OpType_from_Vertex(v) == OpType::Conditional &&
static_cast<const Conditional&>(*get_Op_ptr_from_Vertex(v))
.get_op()
->get_type() == op_type) {
++counter;
}
}
return counter;
}

VertexSet Circuit::get_gates_of_type(const OpType& op_type) const {
VertexSet vset;
BGL_FORALL_VERTICES(v, dag, DAG) {
Expand Down
19 changes: 19 additions & 0 deletions tket/test/src/Circuit/test_Circ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,25 @@ SCENARIO(
}
}

SCENARIO("test conditional count") {
GIVEN("conditional circ") {
Circuit circ;
register_t qreg = circ.add_q_register("qb", 2);
register_t creg = circ.add_c_register("b", 2);
circ.add_conditional_gate<UnitID>(OpType::H, {}, {qreg[1]}, {creg[0]}, 1);
circ.add_conditional_gate<UnitID>(OpType::H, {}, {qreg[1]}, {creg[0]}, 1);
circ.add_conditional_gate<UnitID>(OpType::H, {}, {qreg[1]}, {creg[0]}, 1);
circ.add_op<Qubit>(OpType::H, {Qubit(qreg[0])});
circ.add_op<Qubit>(OpType::H, {Qubit(qreg[0])});
REQUIRE(circ.n_qubits() == 2);
REQUIRE(circ.n_bits() == 2);
REQUIRE(circ.count_gates(OpType::CX) == 0);
REQUIRE(circ.count_gates(OpType::H) == 2);
REQUIRE(circ.count_gates_conditional(OpType::H) == 3);
REQUIRE(circ.count_gates_conditional(OpType::CX) == 0);
}
}

SCENARIO("Creating gates via Qubits and Registers") {
GIVEN("A purely quantum circuit") {
Circuit circ;
Expand Down
Loading