Skip to content

Commit

Permalink
Make CXMappingPass a StandardPass with round-trip serialization a…
Browse files Browse the repository at this point in the history
…nd deserialization (#1575)
  • Loading branch information
cqc-alec authored Sep 19, 2024
1 parent 0a99785 commit 9c62c9b
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 48 deletions.
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.3.24@tket/stable")
self.requires("tket/1.3.25@tket/stable")
self.requires("tklog/0.3.3@tket/stable")
self.requires("tkrng/0.3.3@tket/stable")
self.requires("tkassert/0.3.4@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 @@ -10,6 +10,8 @@ Features:
* DecomposeTK2 pass now has a json representation when it contains no functions.
* Add support for rendering multiple circuits at once.
* Add option to save circuit renderer options to pytket config.
* Make `CXMappingPass` into a `StandardPass` (with round-trip serialization and
deserialization).

Fixes:

Expand Down
52 changes: 10 additions & 42 deletions pytket/tests/passes_serialisation_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,16 @@ def nonparam_predicate_dict(name: str) -> Dict[str, Any]:
"allow_swaps": True,
}
),
"CXMappingPass": standard_pass_dict(
{
"name": "CXMappingPass",
"architecture": example_architecture,
"placement": example_placement,
"routing_config": example_routing_config,
"directed": True,
"delay_measures": True,
}
),
}

# non-parametrized passes that satisfy pass.from_dict(d).to_dict()==d
Expand Down Expand Up @@ -372,16 +382,6 @@ def nonparam_predicate_dict(name: str) -> Dict[str, Any]:
"delay_measures": True,
}
),
"CXMappingPass": standard_pass_dict(
{
"name": "CXMappingPass",
"architecture": example_architecture,
"placement": example_placement,
"routing_config": example_routing_config,
"directed": True,
"delay_measures": True,
}
),
"PauliSimp": standard_pass_dict(
{
"name": "PauliSimp",
Expand Down Expand Up @@ -726,38 +726,6 @@ def tk1_rep(a: ParamType, b: ParamType, c: ParamType) -> Circuit:
comppba_plac_pass.get_sequence()[1].to_dict()["StandardPass"]["name"]
== "PlacementPass"
)
# CXMappingPass
cxm_pass = CXMappingPass(arc, placer, directed_cx=True, delay_measures=True)
assert cxm_pass.to_dict()["pass_class"] == "SequencePass"
assert isinstance(cxm_pass, SequencePass)
p0 = cxm_pass.get_sequence()[0]
p1 = cxm_pass.get_sequence()[1]
assert p0.to_dict()["pass_class"] == "SequencePass"
assert p1.to_dict()["StandardPass"]["name"] == "DecomposeSwapsToCXs"
assert p1.to_dict()["StandardPass"]["directed"] == True
assert isinstance(p0, SequencePass)
p00 = p0.get_sequence()[0]
p01 = p0.get_sequence()[1]
assert p00.to_dict()["pass_class"] == "SequencePass"
assert p01.to_dict()["StandardPass"]["name"] == "RebaseCustom"
assert p01.to_dict()["StandardPass"]["basis_cx_replacement"] == cx.to_dict()
assert isinstance(p00, SequencePass)
p000 = p00.get_sequence()[0]
p001 = p00.get_sequence()[1]
assert p000.to_dict()["pass_class"] == "SequencePass"
assert p001.to_dict()["StandardPass"]["name"] == "DelayMeasures"
assert p001.to_dict()["StandardPass"]["allow_partial"] == False
assert isinstance(p000, SequencePass)
p0000 = p000.get_sequence()[0]
p0001 = p000.get_sequence()[1]
assert p0000.to_dict()["StandardPass"]["name"] == "RebaseCustom"
assert p0001.to_dict()["pass_class"] == "SequencePass"
assert isinstance(p0001, SequencePass)
p00010 = p0001.get_sequence()[0]
p00011 = p0001.get_sequence()[1]
assert p00010.to_dict()["StandardPass"]["name"] == "PlacementPass"
assert p00011.to_dict()["StandardPass"]["name"] == "RoutingPass"
assert check_arc_dict(arc, p00011.to_dict()["StandardPass"]["architecture"])

# RepeatWithMetricPass
def number_of_CX(circ: Circuit) -> int:
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.24"
version = "1.3.25"
package_type = "library"
license = "Apache 2"
homepage = "https://github.com/CQCL/tket"
Expand Down
1 change: 0 additions & 1 deletion tket/src/Predicates/CompilerPass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,6 @@ void from_json(const nlohmann::json& j, PassPtr& pp) {
bool delay_measures = content.at("delay_measures").get<bool>();
pp = gen_default_mapping_pass(arc, delay_measures);
} else if (passname == "CXMappingPass") {
// SEQUENCE PASS - DESERIALIZABLE ONLY
Architecture arc = content.at("architecture").get<Architecture>();
Placement::Ptr place = content.at("placement").get<Placement::Ptr>();
std::vector<RoutingMethodPtr> config = content.at("routing_config");
Expand Down
47 changes: 44 additions & 3 deletions tket/src/Predicates/PassGenerators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include <algorithm>
#include <memory>
#include <nlohmann/json_fwd.hpp>
#include <sstream>
#include <string>

Expand Down Expand Up @@ -480,14 +481,54 @@ PassPtr gen_cx_mapping_pass(
bool delay_measures) {
OpTypeSet gate_set = all_single_qubit_types();
gate_set.insert(OpType::CX);
PassPtr rebase_pass =
gen_rebase_pass(gate_set, CircPool::CX(), CircPool::tk1_to_tk1);
PassPtr rebase_pass = gen_auto_rebase_pass(gate_set);
PassPtr return_pass =
rebase_pass >> gen_full_mapping_pass(arc, placement_ptr, config);
if (delay_measures) return_pass = return_pass >> DelayMeasures();
return_pass = return_pass >> rebase_pass >>
gen_decompose_routing_gates_to_cxs_pass(arc, directed_cx);
return return_pass;
Transform t{[=](Circuit& circ, std::shared_ptr<unit_bimaps_t> maps) {
// Relabel all two-qubit gates
CompilationUnit cu(circ);
bool changed = rebase_pass->apply(cu);
circ = cu.get_circ_ref();
// Now try placement, falling back on "LinePlacement" if "GraphPlacement"
// fails
try {
changed |= placement_ptr->place(circ, maps);
} catch (const std::runtime_error& e) {
std::stringstream ss;
ss << "PlacementPass failed with message: " << e.what()
<< " Fall back to LinePlacement.";
tket_log()->warn(ss.str());
Placement::Ptr line_placement_ptr = std::make_shared<LinePlacement>(
placement_ptr->get_architecture_ref());
changed |= line_placement_ptr->place(circ, maps);
}
// Now route
MappingManager mm(std::make_shared<Architecture>(arc));
changed |= mm.route_circuit_with_maps(circ, config, maps);

// Now decompose routing gates to cx gates (this won't change maps)
CompilationUnit cu1(circ);
if (delay_measures) {
changed |= DelayMeasures()->apply(cu1);
}
changed |=
gen_decompose_routing_gates_to_cxs_pass(arc, directed_cx)->apply(cu1);
circ = cu1.get_circ_ref();
return changed;
}};
PassConditions conditions = return_pass->get_conditions();
nlohmann::json j;
j["name"] = "CXMappingPass";
j["architecture"] = arc;
j["placement"] = placement_ptr;
j["routing_config"] = config;
j["directed"] = directed_cx;
j["delay_measures"] = delay_measures;
return std::make_shared<StandardPass>(
conditions.first, t, conditions.second, j);
}

PassPtr gen_routing_pass(
Expand Down

0 comments on commit 9c62c9b

Please sign in to comment.