18#include <tkassert/Assert.hpp>
29 PauliACVertex new_vert = boost::add_vertex(tensor, pac_graph);
34 bool conflict = !tensor.conflicting_qubits(pac_graph[v]).empty();
35 if (conflict) boost::add_edge(new_vert, v, pac_graph);
39 if (!tensor.commutes_with(pac_graph[v])) {
40 boost::add_edge(new_vert, v, pac_graph);
59class AbstractGraphData {
62 explicit AbstractGraphData(
const PauliACGraph& pac_graph);
72 std::map<SpPauliString, std::size_t>
77 const VertexMap& get_vertex_map()
const;
81 VertexMap m_vertex_map;
84std::size_t AbstractGraphData::get_vertex_id(
86 const auto citer = m_vertex_map.find(pauli_string);
87 if (citer != m_vertex_map.cend()) {
91 const auto new_id = m_vertex_map.size();
92 m_vertex_map[pauli_string] = new_id;
96const AbstractGraphData::VertexMap& AbstractGraphData::get_vertex_map()
const {
100const graphs::AdjacencyData& AbstractGraphData::get_adjacency_data()
const {
101 return m_adjacency_data;
104AbstractGraphData::AbstractGraphData(
const PauliACGraph& pac_graph)
105 : m_adjacency_data(boost::num_vertices(pac_graph)) {
106 const auto vertex_iterators = boost::vertices(pac_graph);
107 for (
auto v_iter = vertex_iterators.first; v_iter != vertex_iterators.second;
115 const auto this_vertex_id = get_vertex_id(pac_graph[*v_iter]);
116 const auto neighbour_iterators =
117 boost::adjacent_vertices(*v_iter, pac_graph);
119 for (
auto n_iter = neighbour_iterators.first;
120 n_iter != neighbour_iterators.second; ++n_iter) {
121 m_adjacency_data.add_edge(
122 this_vertex_id, get_vertex_id(pac_graph[*n_iter]));
127static std::map<unsigned, std::list<SpPauliString>>
128get_partitioned_paulis_for_exhaustive_method(
const PauliACGraph& pac_graph) {
129 const AbstractGraphData data(pac_graph);
130 const graphs::GraphColouringResult colouring =
131 graphs::GraphColouringRoutines ::get_colouring(data.get_adjacency_data());
133 TKET_ASSERT(data.get_vertex_map().size() == colouring.colours.size());
135 std::map<unsigned, std::list<SpPauliString>> colour_map;
137 for (
const auto& entry : data.get_vertex_map()) {
139 const std::size_t
id = entry.second;
140 TKET_ASSERT(
id < colouring.colours.size());
143 const std::size_t colour = colouring.colours[
id];
144 TKET_ASSERT(colour < colouring.number_of_colours);
146 colour_map[colour].push_back(vertex);
148 if (!colour_map.empty()) {
149 TKET_ASSERT(colour_map.size() == 1 + colour_map.crbegin()->first);
150 TKET_ASSERT(colour_map.cbegin()->first == 0);
155static std::map<unsigned, std::list<SpPauliString>>
156get_partitioned_paulis_for_largest_first_method(
const PauliACGraph& pac_graph) {
157 std::vector<unsigned> order_vec(boost::num_vertices(pac_graph));
158 std::iota(order_vec.begin(), order_vec.end(), 0);
160 std::sort(order_vec.begin(), order_vec.end(), [&](
unsigned i,
unsigned j) {
161 return (boost::out_degree(i, pac_graph) > boost::out_degree(j, pac_graph));
165 std::vector<unsigned> colour_vec(boost::num_vertices(pac_graph));
166 boost::iterator_property_map<
168 boost::property_map<PauliACGraph, boost::vertex_index_t>::const_type>
170 &colour_vec.front(), boost::get(boost::vertex_index, pac_graph));
171 boost::sequential_vertex_coloring(
173 boost::make_iterator_property_map(
174 order_vec.begin(), boost::identity_property_map()),
177 std::map<unsigned, std::list<SpPauliString>> colour_map;
179 unsigned v_colour = colour_prop_map[v];
180 colour_map[v_colour].push_back(pac_graph[v]);
185std::map<unsigned, std::list<SpPauliString>>
189 return get_partitioned_paulis_for_largest_first_method(pac_graph);
192 return get_partitioned_paulis_for_exhaustive_method(pac_graph);
195 throw std::logic_error(
196 "Lazy graph colouring should never reach this point");
199 throw std::logic_error(
"Unknown graph colouring method");
204static std::list<std::list<SpPauliString>>
205get_term_sequence_for_lazy_colouring_method(
207 std::list<std::list<SpPauliString>> terms;
210 terms.push_back({qpt});
214 bool found_bin =
false;
215 for (std::list<SpPauliString>& qpt_list : terms) {
216 bool viable_bin =
true;
220 bool conflict = !qpt.conflicting_qubits(qpt2).empty();
221 if (conflict) viable_bin =
false;
225 if (!qpt.commutes_with(qpt2)) viable_bin =
false;
229 throw UnknownPauliPartitionStrat();
233 if (viable_bin ==
false)
break;
236 qpt_list.push_back(qpt);
242 if (found_bin ==
false) {
243 terms.push_back({qpt});
249static std::list<std::list<SpPauliString>>
250get_term_sequence_with_constructed_dependency_graph(
253 std::list<std::list<SpPauliString>> terms;
254 PauliPartitionerGraph pp(strings, strat);
255 std::map<unsigned, std::list<SpPauliString>> colour_map =
256 pp.partition_paulis(method);
258 for (
const std::pair<
const unsigned, std::list<SpPauliString>>& colour_pair :
260 terms.push_back(colour_pair.second);
270 return get_term_sequence_for_lazy_colouring_method(strings, strat);
275 return get_term_sequence_with_constructed_dependency_graph(
276 strings, strat, method);
278 throw std::logic_error(
"term_sequence : unknown graph colouring method");
PauliPartitionerGraph(const std::list< SpPauliString > &strings, PauliPartitionStrat strat)
std::map< unsigned, std::list< SpPauliString > > partition_paulis(GraphColourMethod method) const
PauliTensor<PauliContainer, CoeffType>
Data for an undirected graph.
detail::vertex< T > vertex
Defines tket::DeviceCharacterisation, used in NoiseAwarePlacement and in commute_SQ_gates_through_SWA...
PauliPartitionStrat
A choice of strategies to partition Pauli tensors into sets.
@ CommutingSets
Sets of mutually commuting tensors; requires O(n^2) CXs for diagonalisation.
@ NonConflictingSets
Sets of tensors with no conflicting Paulis; requires no CXs for diagonalisation.
GraphColourMethod
A choice of methods to perform graph colouring for Pauli partitioning.
@ LargestFirst
Builds the graph and then greedily colours by iterating through the vertices, with the highest degree...
@ Lazy
Lazy: does not build the graph before performing the colouring; partitions while iterating through th...
@ Exhaustive
Builds the graph, then colours it using the minimum possible number of colours.
boost::graph_traits< PauliACGraph >::vertex_descriptor PauliACVertex
boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS, SpPauliString > PauliACGraph
A PauliACGraph is a graph where each vertex is a Pauli tensor, and an edge corresponds to anticommuti...
PauliTensor< QubitPauliMap, no_coeff_t > SpPauliString
std::list< std::list< SpPauliString > > term_sequence(const std::list< SpPauliString > &strings, PauliPartitionStrat strat, GraphColourMethod method)
Partitions a QubitOperator into lists of mutually commuting gadgets.