diff --git a/src/stim/cmd/command_help.cc b/src/stim/cmd/command_help.cc index 9eb214de..d0a600c6 100644 --- a/src/stim/cmd/command_help.cc +++ b/src/stim/cmd/command_help.cc @@ -290,7 +290,7 @@ void print_stabilizer_generators(Acc &out, const Gate &gate) { } void print_bloch_vector(Acc &out, const Gate &gate) { - if (!(gate.flags & GATE_IS_UNITARY) || (gate.flags & GATE_TARGETS_PAIRS)) { + if (!(gate.flags & GATE_IS_UNITARY) || !(gate.flags & GATE_IS_SINGLE_QUBIT_GATE)) { return; } @@ -343,7 +343,7 @@ void print_bloch_vector(Acc &out, const Gate &gate) { } void print_unitary_matrix(Acc &out, const Gate &gate) { - if (!(gate.flags & GATE_IS_UNITARY)) { + if (!gate.has_known_unitary_matrix()) { return; } auto matrix = gate.unitary(); diff --git a/src/stim/gates/gates.cc b/src/stim/gates/gates.cc index 2ee52a2b..a63c2992 100644 --- a/src/stim/gates/gates.cc +++ b/src/stim/gates/gates.cc @@ -267,6 +267,10 @@ std::array Gate::to_axis_angle() const { return {rx, ry, rz, acosf(rs) * 2}; } +bool Gate::has_known_unitary_matrix() const { + return (flags & GateFlags::GATE_IS_UNITARY) && (flags & (GateFlags::GATE_IS_SINGLE_QUBIT_GATE | GateFlags::GATE_TARGETS_PAIRS)); +} + std::vector>> Gate::unitary() const { if (unitary_data.size() != 2 && unitary_data.size() != 4) { throw std::out_of_range(std::string(name) + " doesn't have 1q or 2q unitary data."); diff --git a/src/stim/gates/gates.h b/src/stim/gates/gates.h index 32fba97b..ad145b75 100644 --- a/src/stim/gates/gates.h +++ b/src/stim/gates/gates.h @@ -258,7 +258,7 @@ struct Gate { template std::vector> flows() const { - if (flags & GateFlags::GATE_IS_UNITARY) { + if (has_known_unitary_matrix()) { auto t = tableau(); if (flags & GateFlags::GATE_TARGETS_PAIRS) { return { @@ -285,6 +285,12 @@ struct Gate { bool is_symmetric() const; GateType hadamard_conjugated(bool ignoring_sign) const; + /// Determines if the gate has a specified unitary matrix. + /// + /// Some unitary gates, such as SPP, don't have a specified matrix because the + /// matrix depends crucially on the targets. + bool has_known_unitary_matrix() const; + /// Converts a single qubit unitary gate into an euler-angles rotation. /// /// Returns: diff --git a/src/stim/gates/gates.pybind.cc b/src/stim/gates/gates.pybind.cc index fdb46139..af2b0c36 100644 --- a/src/stim/gates/gates.pybind.cc +++ b/src/stim/gates/gates.pybind.cc @@ -50,7 +50,7 @@ pybind11::object gate_tableau(const Gate &self) { return pybind11::none(); } pybind11::object gate_unitary_matrix(const Gate &self) { - if ((self.flags & GateFlags::GATE_IS_UNITARY) && (self.flags & (GateFlags::GATE_IS_SINGLE_QUBIT_GATE | GateFlags::GATE_TARGETS_PAIRS))) { + if (self.has_known_unitary_matrix()) { auto r = self.unitary(); auto n = r.size(); std::complex *buffer = new std::complex[n * n]; diff --git a/src/stim/py/stim_pybind_test.py b/src/stim/py/stim_pybind_test.py index 26ba4c46..368dca93 100644 --- a/src/stim/py/stim_pybind_test.py +++ b/src/stim/py/stim_pybind_test.py @@ -136,6 +136,13 @@ def test_main_write_to_file(): assert "Generated repetition_code" in f.read() +def test_main_help(capsys): + assert stim.main(command_line_args=["help"]) == 0 + captured = capsys.readouterr() + assert captured.err == "" + assert 'Available stim commands' in captured.out + + def test_main_redirects_stdout(capsys): assert stim.main(command_line_args=[ "gen",