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

Clifford representation incorporating global phase #1667

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
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.13.0")
self.requires("tkassert/0.3.4@tket/stable")
self.requires("tket/1.3.46@tket/stable")
self.requires("tket/1.3.47@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
3 changes: 3 additions & 0 deletions tket/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,11 @@ target_sources(tket
src/Circuit/SubcircuitFinder.cpp
src/Circuit/ThreeQubitConversion.cpp
src/Circuit/ToffoliBox.cpp
src/Clifford/APState.cpp
src/Clifford/ChoiMixTableau.cpp
src/Clifford/SymplecticTableau.cpp
src/Clifford/UnitaryTableau.cpp
src/Converters/APStateConverters.cpp
src/Converters/ChoiMixTableauConverters.cpp
src/Converters/Gauss.cpp
src/Converters/PauliGraphConverters.cpp
Expand Down Expand Up @@ -322,6 +324,7 @@ target_sources(tket
include/tket/Circuit/StatePreparation.hpp
include/tket/Circuit/ThreeQubitConversion.hpp
include/tket/Circuit/ToffoliBox.hpp
include/tket/Clifford/APState.hpp
include/tket/Clifford/ChoiMixTableau.hpp
include/tket/Clifford/SymplecticTableau.hpp
include/tket/Clifford/UnitaryTableau.hpp
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.46"
version = "1.3.47"
package_type = "library"
license = "Apache 2"
homepage = "https://github.com/CQCL/tket"
Expand Down
146 changes: 146 additions & 0 deletions tket/include/tket/Clifford/APState.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Copyright 2019-2024 Cambridge Quantum Computing
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include "tket/OpType/OpType.hpp"
#include "tket/Utils/MatrixAnalysis.hpp"

namespace tket {

/**
* APState class for Clifford states with global phase tracking
*
* The "affine with phases" form of a Clifford state from ZX calculus (see
* Kissinger & van de Wetering, "Picturing Quantum Software") represents n-qubit
* Clifford states uniquely with the following data:
* - A binary (k,n) matrix A in reduced row echelon form. The leading columns of
* each row are referred to as "leading qubits", and the others as "free
* qubits". We apply H gates to all free qubits, then for each row of A we apply
* a CX targeted on the leading qubit and control by each other entry in the
* row.
* - A binary (k) vector B describing X gates applied to the leading qubits.
* - A Clifford phase polynomial Phi over the free qubits. Wlog this can be in
* the form of a symmetric, zero-diagonal, binary (n-k,n-k) matrix E describing
* CZ gates and a (n-k) vector P of integers mod 4 describing S gates.
*
* This gives a canonical statevector:
* \sum_{x, Ax=B} i^{\Phi(x)} |x>
*
* This canonical statevector fixes a reference phase from which we can track
* global phase with an additional parameter.
*
* When applying gates, qubits may switch between being leading and free
* (including those that aren't involved in the gate due to the need to reduce
* to the canonical form, e.g. reduced row echelon form for A). The updates are
* easiest to prove in the ZX calculus for the gateset (CZ, S i.e. pi/2 green
* phase, SX i.e. pi/2 red phase).
*
* To save on resizing the matrices and vectors, we will keep them at full size
* and just assert correctness that, e.g. every entry in A is either on the
* diagonal (to indicate the qubit is leading) or in the row of a leading qubit
* and a column of a later following qubit.
*/
class APState {
public:
/**
* An upper triangular matrix whose diagonal entries indicate leading qubits
* and off-diagonal entries represent a CX gate from the column qubit
* (necessarily a free qubit) to the row qubit.
*
* If a diagonal entry is 0 (it is a free qubit), then every entry in the row
* is 0. If a diagonal entry is 1 (it is a leading qubit), all other entries
* in the column are 0.
*/
MatrixXb A;

/**
* A vector indicating X gates on leading qubits.
*
* Must be 0 on every free qubit.
*/
VectorXb B;

/**
* A symmetric, zero diagonal matrix whose entries indicate CZs between free
* qubits.
*
* Every diagonal entry must be 0.
* The column and row for each leading qubit must be 0.
*/
MatrixXb E;

/**
* A vector indicating S^{P(i)} on qubit i which must be free.
*
* Must be 0 on every leading qubit.
*/
Eigen::VectorXi P;

/**
* The global phase term (in half-turns).
*/
Expr phase;

/**
* Constructs a state in AP form from given data.
*/
APState(
const MatrixXb& A_, const VectorXb& B_, const MatrixXb& E_,
const Eigen::VectorXi& P_, const Expr& phase_);

/**
* Constructs the state |0>^{\otimes n_qubits} in AP form.
*/
APState(unsigned n_qubits);

/**
* Constructs the state in AP form from a given statevector.
*/
APState(const Eigen::VectorXcd& sv);

/**
* Verifies the internal correctness of the data structure. Throws an
* exception if the data structure is invalid.
*/
void verify();

/**
* Calculates the statevector of the state.
*/
Eigen::VectorXcd to_statevector();

/**
* Applies a CZ gate to the state. O(n^2) wrt number of qubits in the state.
*/
void apply_CZ(unsigned ctrl, unsigned trgt);

/**
* Applies an S gate to the state. O(n^2) wrt number of qubits in the state.
*/
void apply_S(unsigned q);

/**
* Applies a V gate to the state. O(n^2) wrt number of qubits in the state.
*/
void apply_V(unsigned q);

/**
* Applies an unparameterised Clifford gate to the state on the chosen qubits.
* O(n^2) wrt number of qubits in the state.
*/
void apply_gate(OpType type, const std::vector<unsigned>& qbs);
};

} // namespace tket
31 changes: 31 additions & 0 deletions tket/include/tket/Converters/Converters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#pragma once

#include "tket/Circuit/Circuit.hpp"
#include "tket/Clifford/APState.hpp"
#include "tket/Clifford/ChoiMixTableau.hpp"
#include "tket/Clifford/UnitaryTableau.hpp"
#include "tket/PauliGraph/PauliGraph.hpp"
Expand Down Expand Up @@ -45,6 +46,20 @@ Circuit unitary_rev_tableau_to_circuit(const UnitaryRevTableau &tab);
*/
ChoiMixTableau circuit_to_cm_tableau(const Circuit &circ);

/**
* Construct an APState for a given circuit.
* Assumes all input qubits are initialised in the |0> state.
* Will throw an exception if it contains non-Clifford gates.
*/
APState circuit_to_apstate(const Circuit &circ);

/**
* Construct a circuit producing the state described by the APState.
* Uses the standard circuit form implied by the ZX description of reduced
* AP-form (layered as X-H-CX-CZ-S).
*/
Circuit apstate_to_circuit(const APState &ap);

/**
* Constructs a circuit producing the same effect as a ChoiMixTableau.
* Since Circuit does not support distinct qubit addresses for inputs and
Expand Down Expand Up @@ -130,6 +145,22 @@ std::pair<Circuit, qubit_map_t> cm_tableau_to_unitary_extension_circuit(
const std::vector<Qubit> &post_names = {},
CXConfigType cx_config = CXConfigType::Snake);

/**
* Convert a SymplecticTableau describing a stabiliser state to reduced AP-form
* (i.e. an APState object). Since tableau methods do not track global phase, we
* set it to 0. Throws an exception if the tableau does not describe a pure
* state (i.e. it must have n commuting rows for n qubits).
*/
APState tableau_to_apstate(SymplecticTableau tab);

/**
* Convert an APState describing a stabiliser state into a tableau form,
* discarding the global phase information. This allows us to reuse tableau
* synthesis methods to synthesise APState objects (the result would need
* re-simulating as an APState to compare and deduce the required global phase).
*/
SymplecticTableau apstate_to_tableau(const APState &ap);

PauliGraph circuit_to_pauli_graph(const Circuit &circ);

/**
Expand Down
Loading
Loading