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

Unitary Synthesis of ChoiMixTableau for Diagonalisation #941

Merged
merged 69 commits into from
Nov 7, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
e994992
Copy files over from refactor/pauligraph
willsimmons1465 Jul 18, 2023
a701314
Make identity pauli gadget still have correct qubits
willsimmons1465 Jul 18, 2023
099d036
Remove unused line
willsimmons1465 Jul 18, 2023
181f296
Merge branch 'develop' into feature/choimix_unitary_synth
willsimmons1465 Jul 27, 2023
e423323
Rewrite ChoiMixTableauConverter to make easier to follow
willsimmons1465 Aug 1, 2023
b66c13b
Merge branch 'develop' into feature/choimix_unitary_synth
willsimmons1465 Aug 1, 2023
2b35553
Combine diagonalisation steps
willsimmons1465 Aug 2, 2023
c82bc7d
Remove separate methods for solving post, init, and collapse spaces
willsimmons1465 Aug 2, 2023
492a657
Split method into sections again for readability
willsimmons1465 Aug 2, 2023
b4d0560
Rewrite header description
willsimmons1465 Aug 2, 2023
1bc1dc6
Merge branch 'develop' into feature/choimix_unitary_synth
willsimmons1465 Aug 2, 2023
972f659
Bump tket version
willsimmons1465 Aug 2, 2023
5ad5410
Remove unused function
willsimmons1465 Aug 3, 2023
4d06f72
Add tests for coverage
willsimmons1465 Aug 3, 2023
7441ab7
Fix failing coverage tests
willsimmons1465 Aug 3, 2023
bf9e9da
Make gadget synthesis only use CXs to comply with test analysis
willsimmons1465 Aug 3, 2023
069d2ae
Synthesising gadget pairs with a consistent CXConfigType varies perfo…
willsimmons1465 Aug 3, 2023
801ef6d
Merge branch 'develop' into feature/choimix_unitary_synth
willsimmons1465 Aug 14, 2023
c1e63cb
Apply suggestions from code review
willsimmons1465 Aug 15, 2023
25e476b
Update tket/src/Converters/ChoiMixTableauConverters.cpp
willsimmons1465 Aug 15, 2023
1aa8c58
Merge branch 'feature/choimix_unitary_synth' of https://github.com/CQ…
willsimmons1465 Aug 15, 2023
4de8442
Implement most reviewer feedback
willsimmons1465 Aug 21, 2023
ec4010a
Merge branch 'develop' into feature/choimix_unitary_synth
willsimmons1465 Aug 22, 2023
f8bb506
Bump tket version number
willsimmons1465 Aug 22, 2023
8602444
Doxygen error and formatting
willsimmons1465 Aug 22, 2023
435ec8c
Initial implementation attempt
willsimmons1465 Sep 11, 2023
eeaddfc
Solve a bunch of linker errors
willsimmons1465 Sep 18, 2023
a95a372
Test comparators
willsimmons1465 Sep 18, 2023
7461c23
Test multiplications
willsimmons1465 Sep 18, 2023
9f99654
Tested hashing
willsimmons1465 Sep 18, 2023
7022419
Refactor Utils, OpType, Ops, Gate, Clifford
willsimmons1465 Sep 18, 2023
90f3de2
Refactored source and tests; some tests fail
willsimmons1465 Oct 2, 2023
b57a87a
Fix test errors
willsimmons1465 Oct 9, 2023
90ac4d4
Binders compile, failing json validation
willsimmons1465 Oct 10, 2023
3f419c5
Attempt to make serialisation backwards compatible
willsimmons1465 Oct 10, 2023
e9aa9b8
Fix remaining serialisation bugs
willsimmons1465 Oct 10, 2023
f08ddc8
Merge branch 'develop' into refactor/paulistring
willsimmons1465 Oct 10, 2023
291ae9a
Merge branch 'develop' into refactor/paulistring
willsimmons1465 Oct 16, 2023
e592255
Fixed it!
willsimmons1465 Oct 16, 2023
79a0bfa
Rename PauliStrings2 to PauliTensor
willsimmons1465 Oct 16, 2023
11d4dba
Remove old PauliStrings
willsimmons1465 Oct 16, 2023
f2d6bf5
Rename test_PauliString2
willsimmons1465 Oct 16, 2023
c453580
Rename file references
willsimmons1465 Oct 16, 2023
1d73aca
File references in CMakeLists
willsimmons1465 Oct 16, 2023
8b21d98
Bump tket version number
willsimmons1465 Oct 16, 2023
cf8177e
Run formatter
willsimmons1465 Oct 16, 2023
2452223
Fix binder errors
willsimmons1465 Oct 16, 2023
ac176f0
Merge branch 'develop' into refactor/paulistring
willsimmons1465 Oct 16, 2023
8c0cf89
Compiler errors on other OSs on CI
willsimmons1465 Oct 16, 2023
4a2088a
Merge branch 'refactor/paulistring' into feature/choimix_unitary_synth
willsimmons1465 Oct 16, 2023
d058b0c
More merge conflicts from deleted files
willsimmons1465 Oct 16, 2023
6b5e118
Fix stub changes
willsimmons1465 Oct 16, 2023
67b12e6
Test coverage
willsimmons1465 Oct 26, 2023
073364d
Fix comparison issue
willsimmons1465 Oct 26, 2023
ae49a76
Remove commented out code
willsimmons1465 Oct 26, 2023
ed900cb
Implement reviewer feedback
willsimmons1465 Oct 30, 2023
93e6673
Merge branch 'develop' into refactor/paulistring
willsimmons1465 Oct 30, 2023
6f796ee
Bump tket version numbers
willsimmons1465 Oct 30, 2023
999f67d
Docs formatting error on CI
willsimmons1465 Oct 30, 2023
fc7d345
Retain fix from merge conflict
willsimmons1465 Oct 30, 2023
0c5fb1f
Merge branch 'refactor/paulistring' into feature/choimix_unitary_synth
willsimmons1465 Oct 30, 2023
592f925
Fix merge bugs
willsimmons1465 Nov 6, 2023
cc41a6c
Merge branch 'develop' into feature/choimix_unitary_synth
willsimmons1465 Nov 6, 2023
1cb4d84
Error in merge
willsimmons1465 Nov 6, 2023
6202371
Bump tket version number
willsimmons1465 Nov 6, 2023
cba457c
Missing TKET_ASSERTs from reviewer suggestions
willsimmons1465 Nov 6, 2023
83b70d4
Test Z,X,H methods on UnitaryTableau for coverage
willsimmons1465 Nov 6, 2023
c7d7f81
Mixed initialisation test didn't actually use them
willsimmons1465 Nov 6, 2023
25e7dda
Remove unused function
willsimmons1465 Nov 7, 2023
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 @@ -32,7 +32,7 @@ def package(self):
cmake.install()

def requirements(self):
self.requires("tket/1.2.30@tket/stable")
self.requires("tket/1.2.31@tket/stable")
self.requires("tklog/0.3.3@tket/stable")
self.requires("tkrng/0.3.3@tket/stable")
self.requires("tkassert/0.3.3@tket/stable")
Expand Down
6 changes: 3 additions & 3 deletions pytket/tests/ansatz_sequence_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ def test_nontrivial_sequence() -> None:
GraphColourMethod.Exhaustive: (3, 28, 20, 19),
},
PauliPartitionStrat.NonConflictingSets: {
GraphColourMethod.LargestFirst: (6, 28, 28, 28),
GraphColourMethod.Lazy: (6, 28, 28, 26),
GraphColourMethod.Exhaustive: (6, 28, 28, 26),
GraphColourMethod.LargestFirst: (6, 28, 28, 26),
GraphColourMethod.Lazy: (6, 28, 28, 28),
GraphColourMethod.Exhaustive: (6, 28, 28, 28),
},
}

Expand Down
2 changes: 0 additions & 2 deletions tket/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,6 @@ target_sources(tket
src/ZX/MBQCRewrites.cpp
src/ZX/ZXRWSequences.cpp
src/Converters/ChoiMixTableauConverters.cpp
src/Converters/PauliGadget.cpp
src/Converters/PauliGraphConverters.cpp
src/Converters/Gauss.cpp
src/Converters/PhasePoly.cpp
Expand Down Expand Up @@ -344,7 +343,6 @@ target_sources(tket
include/tket/ZX/ZXGenerator.hpp
include/tket/Converters/Converters.hpp
include/tket/Converters/Gauss.hpp
include/tket/Converters/PauliGadget.hpp
include/tket/Converters/PhasePoly.hpp
include/tket/Converters/UnitaryTableauBox.hpp
include/tket/Placement/NeighbourPlacements.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.2.30"
version = "1.2.31"
package_type = "library"
license = "Apache 2"
homepage = "https://github.com/CQCL/tket"
Expand Down
10 changes: 8 additions & 2 deletions tket/include/tket/Circuit/CircUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ std::pair<Circuit, Complex> decompose_2cx_VD(const Eigen::Matrix4cd& U);
*/
std::pair<Circuit, Complex> decompose_2cx_DV(const Eigen::Matrix4cd& U);

Expr pauli_angle_convert_or_throw(Complex pauliCoeff, const Expr& angle);
cqc-alec marked this conversation as resolved.
Show resolved Hide resolved

/**
* Construct a phase gadget
*
Expand All @@ -127,12 +129,16 @@ Circuit phase_gadget(
* \f$ e^{-\frac12 i \pi t \sigma_0 \otimes \sigma_1 \otimes \cdots} \f$
* where \f$ \sigma_i \in \{I,X,Y,Z\} \f$ are the Pauli operators.
*
* @param paulis Pauli operators
* @param pauli Pauli operators
* @param t angle in half-turns
* @param cx_config CX configuration
*/
Circuit pauli_gadget(
const std::vector<Pauli>& paulis, const Expr& t,
QubitPauliTensor pauli, Expr t,
cqc-alec marked this conversation as resolved.
Show resolved Hide resolved
CXConfigType cx_config = CXConfigType::Snake);

Circuit pauli_gadget_pair(
cqc-alec marked this conversation as resolved.
Show resolved Hide resolved
QubitPauliTensor pauli0, Expr t0, QubitPauliTensor pauli1, Expr t1,
CXConfigType cx_config = CXConfigType::Snake);

/**
Expand Down
12 changes: 12 additions & 0 deletions tket/include/tket/Circuit/PauliExpBoxes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,4 +214,16 @@ class PauliExpCommutingSetBox : public Box {
CXConfigType cx_config_;
};

void append_single_pauli_gadget_as_pauli_exp_box(
cqc-alec marked this conversation as resolved.
Show resolved Hide resolved
Circuit &circ, const QubitPauliTensor &pauli, Expr angle,
CXConfigType cx_config);

void append_pauli_gadget_pair_as_box(
Circuit &circ, const QubitPauliTensor &pauli0, Expr angle0,
const QubitPauliTensor &pauli1, Expr angle1, CXConfigType cx_config);

void append_commuting_pauli_gadget_set_as_box(
Circuit &circ, const std::list<std::pair<QubitPauliTensor, Expr>> &gadgets,
CXConfigType cx_config);

} // namespace tket
13 changes: 10 additions & 3 deletions tket/include/tket/Clifford/ChoiMixTableau.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ class ChoiMixTableau {
* When mapped to a sparse readable representation, independent
* QubitPauliTensor objects are used for each segment, so we no longer expect
* their individual phases to be +-1, instead only requiring this on their
* product.
* product. get_row() will automatically transpose the input segment term so
* it is presented as RxS s.t. SCR = C.
*
* Columns of the tableau are indexed by pair of Qubit id and a tag to
* distinguish input vs output. Rows are not maintained in any particular
Expand Down Expand Up @@ -93,6 +94,7 @@ class ChoiMixTableau {
* Construct a tableau directly from its rows.
* Each row is represented as a product of QubitPauliTensors where the first
* is over the input qubits and the second is over the outputs.
* A row RxS is a pair s.t. SCR = C
*/
explicit ChoiMixTableau(const std::list<row_tensor_t>& rows);
/**
Expand Down Expand Up @@ -123,12 +125,17 @@ class ChoiMixTableau {
*/
unsigned get_n_outputs() const;

qubit_vector_t input_qubits() const;
qubit_vector_t output_qubits() const;
cqc-alec marked this conversation as resolved.
Show resolved Hide resolved

/**
* Read off a row as a Pauli string
* Read off a row as a Pauli string.
* Returns a pair of Pauli strings RxS such that SCR = C
*/
row_tensor_t get_row(unsigned i) const;
/**
* Combine rows into a single row
* Combine rows into a single row.
* Returns a pair of Pauli strings RxS such that SCR = C
*/
row_tensor_t get_row_product(const std::vector<unsigned>& rows) const;

Expand Down
20 changes: 1 addition & 19 deletions tket/include/tket/Clifford/SymplecticTableau.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,6 @@

namespace tket {

// Forward declare friend classes for converters
class ChoiMixTableau;
class UnitaryTableau;
class UnitaryRevTableau;
class Circuit;

/**
* Boolean encoding of Pauli
* <x, z> = <false, false> ==> I
Expand Down Expand Up @@ -173,7 +167,6 @@ class SymplecticTableau {
*/
void gaussian_form();

private:
cqc-alec marked this conversation as resolved.
Show resolved Hide resolved
/**
* Number of rows
*/
Expand All @@ -196,6 +189,7 @@ class SymplecticTableau {
*/
SymplecticTableau conjugate() const;

private:
/**
* Helper methods for manipulating the tableau when applying gates
*/
Expand All @@ -206,18 +200,6 @@ class SymplecticTableau {
void col_mult(
const MatrixXb::ColXpr &a, const MatrixXb::ColXpr &b, bool flip,
MatrixXb::ColXpr &w, VectorXb &pw);

friend class UnitaryTableau;
friend class ChoiMixTableau;
friend Circuit unitary_tableau_to_circuit(const UnitaryTableau &tab);
friend std::pair<Circuit, unit_map_t> cm_tableau_to_circuit(
const ChoiMixTableau &tab);
friend std::ostream &operator<<(std::ostream &os, const UnitaryTableau &tab);
friend std::ostream &operator<<(
std::ostream &os, const UnitaryRevTableau &tab);

friend void to_json(nlohmann::json &j, const SymplecticTableau &tab);
friend void from_json(const nlohmann::json &j, SymplecticTableau &tab);
};

JSON_DECL(SymplecticTableau)
Expand Down
143 changes: 141 additions & 2 deletions tket/include/tket/Converters/Converters.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,148 @@ ChoiMixTableau circuit_to_cm_tableau(const Circuit &circ);
* Since Circuit does not support distinct qubit addresses for inputs and
* outputs, also returns a map from the output qubit IDs in the tableau to their
* corresponding outputs in the circuit
*
* If synth_type == ChoiMixSynthType::exact, the circuit produced will be the
cqc-alec marked this conversation as resolved.
Show resolved Hide resolved
* (possibly non-unitary) channel whose stabilisers are exactly those of the
* tableau and no more, using initialisations, post-selections, discards,
* resets, and collapses to ensure this.
*
* If synth_type == ChoiMixSynthType::unitary, the circuit produced will be a
* unitary whose stabilisers include all rows of the tableau and possibly more.
* This is useful when we are treating the ChoiMixTableau as a means to encode a
* diagonalisation problem, since we are generally looking for a unitary as we
* may wish to apply the inverse afterwards (e.g. conjugating some rotations to
* implement a set of Pauli gadgets).
*
* Not every ChoiMixTableau can be extended to a unitary by just adding rows,
* e.g. if it requires any initialisation or post-selections. In this case, we
* call a qubit "spare" if its column in the tableau is Pauli::I in every row.
* If there are more inputs than outputs, then we also suppose there are
* additional spare output qubits which we will name the same as some qubits
* that only appear in the inputs, or vice versa. The synthesis guarantees that,
* if we take the unitary, initialise all spare inputs, and post-select on all
* spare outputs, every row from the original tableau is a stabiliser for the
* remaining projector. When the tableau does not contain enough spare qubits,
* an error is thrown. If it would be useful to automatically extend with
* additional qubits to guarantee a synthesis, or treat such rows in a different
* way, please submit a feature request.
*
* Example 1:
* ZXI -> III
* YYZ -> III
* This becomes a diagonalisation circuit followed by post-selections. For
* unitary synthesis, each row could be mapped to an arbitrary diagonal string
* over the outputs.
*
* Example 2:
* Z -> ZZ
* X -> IY
* Z -> -XX
* Combining the first and last rows reveals an initialisation is required for I
* -> YY. Since there are two output qubits, at least one of them does not
* already exist in the input fragment so we can freely add an extra qubit on
* the input side, initialise it and apply a unitary mapping IZ -> YY. For
* unitary synthesis, this could manifest as either altering the first row to ZZ
* -> ZZ or the last row to ZZ -> -XX.
*
* Example 3:
* ZX -> IZ
* II -> ZI
* We require an initialised qubit for the final row, but both input and output
* spaces only have q[0] and q[1], of which both inputs need to be open for the
* first row. In exact synthesis, we can obtain an initialised qubit by
* resetting a qubit after reducing the first row to only a single qubit. In
* unitary synthesis, the reset is not permitted and there are not enough qubits
* to have a designated initialised qubit, so an exception is thrown. However,
* if the input and output qubits had different names (e.g. inputs q[0], q[1],
* outputs p[0], p[1]), then the synthesised circuit may have up to four qubits
* and there are then enough to use a separate initialised qubit.
*/
std::pair<Circuit, unit_map_t> cm_tableau_to_circuit(
const ChoiMixTableau &circ);

/**
* Constructs a circuit producing the same effect as a ChoiMixTableau.
* Since Circuit does not support distinct qubit addresses for inputs and
* outputs, also returns a map from the output qubit IDs in the tableau to their
* corresponding outputs in the circuit.
*
* The circuit produced will be the (possibly non-unitary) channel whose
* stabilisers are exactly those of the tableau and no more, using
* initialisations, post-selections, discards, resets, and collapses to ensure
* this. It will automatically reuse qubits so no more qubits will be needed
* than max(tab.get_n_inputs(), tab.get_n_outputs()).
*
* Example 1:
* ZXI -> ()
* YYZ -> ()
* This becomes a diagonalisation circuit followed by post-selections.
*
* Example 2:
* Z -> ZZ
* X -> IY
* Z -> -XX
* Combining the first and last rows reveals an initialisation is required for I
* -> YY. Since there are two output qubits, at least one of them does not
* already exist in the input fragment so we can freely add an extra qubit on
* the input side, initialise it and apply a unitary mapping IZ -> YY.
*
* Example 3:
* ZX -> IZ
* II -> ZI
* We require an initialised qubit for the final row, but both input and output
* spaces only have q[0] and q[1], of which both inputs need to be open for the
* first row. We can obtain an initialised qubit by resetting a qubit after
* reducing the first row to only a single qubit.
*/
std::pair<Circuit, qubit_map_t> cm_tableau_to_exact_circuit(
const ChoiMixTableau &tab, CXConfigType cx_config = CXConfigType::Snake);

/**
* We define a unitary extension of a ChoiMixTableau to be a unitary circuit
* whose stabilizer group contain all the rows of the ChoiMixTableau and
* possibly more. This is useful when we are treating the ChoiMixTableau as a
* means to encode a diagonalisation problem, since we are generally looking for
* a unitary as we may wish to apply the inverse afterwards (e.g. conjugating
* some rotations to implement a set of Pauli gadgets).
*
* Not every ChoiMixTableau can be extended to a unitary by just adding rows,
* e.g. if it requires any initialisation or post-selections. In this case, the
* unitary circuit is extended with additional input qubits which are assumed to
* be zero-initialised, and additional output qubits which are assumed to be
* post-selected. The synthesis guarantees that, if we take the unitary,
* initialise all designated inputs, and post-select on all designated outputs,
* every row from the original tableau is a stabiliser for the remaining
* projector. When not enough additional qubit names are provided, an error is
* thrown.
*
*
* Example 1:
* ZXI -> ()
* YYZ -> ()
* Since, in exact synthesis, at least two post-selections would be required, we
* pick two names from post_names. This is then a diagonalisation circuit which
* maps each row to an arbitrary diagonal string over post_names.
*
* Example 2:
* Z -> ZZ
* X -> IY
* Z -> -XX
* Combining the first and last rows reveals an initialisation is required for I
* -> YY. We extend the inputs with a qubit from init_names. The initialisation
* can manifest as either altering the first row to ZZ -> ZZ or the last row to
* ZZ -> -XX.
*
* Example 3:
* ZX -> IZ
* II -> ZI
* We require an initialised qubit for the final row, but both input and output
* spaces only have q[0] and q[1], of which both inputs need to be open for the
* first row. Unlike exact synthesis, we cannot reuse qubits, so the returned
* circuit will be over 3 qubits, extending with a name from init_names.
*/
std::pair<Circuit, qubit_map_t> cm_tableau_to_unitary_extension_circuit(
const ChoiMixTableau &tab, const std::vector<Qubit> &init_names = {},
const std::vector<Qubit> &post_names = {},
CXConfigType cx_config = CXConfigType::Snake);

PauliGraph circuit_to_pauli_graph(const Circuit &circ);

Expand Down
Loading