Skip to content

Commit

Permalink
Check liveness of bits when computing slice iterator (#1707)
Browse files Browse the repository at this point in the history
  • Loading branch information
cqc-alec authored Dec 3, 2024
1 parent c39f1cc commit 2b871b8
Show file tree
Hide file tree
Showing 14 changed files with 507 additions and 449 deletions.
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.52@tket/stable")
self.requires("tket/1.3.53@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
7 changes: 7 additions & 0 deletions pytket/docs/changelog.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Changelog
=========

1.37.0 (Unreleased)
-------------------

Fixes:

* Fix circuit iteration giving invalid slices in some cases.

1.36.0 (November 2024)
----------------------

Expand Down
14 changes: 14 additions & 0 deletions pytket/tests/classical_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1538,5 +1538,19 @@ def test_decompose_clexpbox_overwrite() -> None:
assert args1[1] == bits[0]


def test_depth_classical_only() -> None:
# https://github.com/CQCL/tket/issues/1673
set_bits = SetBitsOp([True, True])
multi_bit = MultiBitOp(set_bits, 2)
eq_pred_values = [True, False, False, True]
and_values = [bool(i) for i in [0, 0, 0, 1]]
circ = Circuit(4, 4, name="test")
circ.add_gate(multi_bit, [0, 1, 2, 3])
circ.add_c_predicate(eq_pred_values, [0, 1], 2, "EQ")
circ.add_c_modifier(and_values, [1], 2)
circ.measure_all()
assert circ.depth() == 4


if __name__ == "__main__":
test_wasm()
2 changes: 2 additions & 0 deletions tket/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ target_sources(tket
src/Circuit/Simulation/GateNode.cpp
src/Circuit/Simulation/GateNodesBuffer.cpp
src/Circuit/Simulation/PauliExpBoxUnitaryCalculator.cpp
src/Circuit/Slices.cpp
src/Circuit/StatePreparation.cpp
src/Circuit/SubcircuitFinder.cpp
src/Circuit/ThreeQubitConversion.cpp
Expand Down Expand Up @@ -319,6 +320,7 @@ target_sources(tket
include/tket/Circuit/ResourceData.hpp
include/tket/Circuit/Simulation/CircuitSimulator.hpp
include/tket/Circuit/Simulation/PauliExpBoxUnitaryCalculator.hpp
include/tket/Circuit/Slices.hpp
include/tket/Circuit/StatePreparation.hpp
include/tket/Circuit/ThreeQubitConversion.hpp
include/tket/Circuit/ToffoliBox.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.52"
version = "1.3.53"
package_type = "library"
license = "Apache 2"
homepage = "https://github.com/CQCL/tket"
Expand Down
71 changes: 2 additions & 69 deletions tket/include/tket/Circuit/Circuit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "Conditional.hpp"
#include "DAGDefs.hpp"
#include "ResourceData.hpp"
#include "Slices.hpp"
#include "tket/Gate/OpPtrFunctions.hpp"
#include "tket/Utils/Json.hpp"
#include "tket/Utils/SequencedContainers.hpp"
Expand All @@ -55,7 +56,6 @@ namespace tket {

typedef std::vector<EdgeVec> BundleVec;

typedef VertexVec Slice;
typedef std::vector<Slice> SliceVec;

typedef std::vector<VertPort> QPathDetailed;
Expand Down Expand Up @@ -108,11 +108,6 @@ typedef boost::multi_index::multi_index_container<
BoundaryElement, std::string, &BoundaryElement::reg_name>>>>
boundary_t;

typedef sequenced_map_t<UnitID, Edge> unit_frontier_t;
// typedef sequenced_map_t<Qubit, Edge> q_frontier_t;
typedef sequenced_map_t<Bit, EdgeVec> b_frontier_t;
// typedef sequenced_map_t<Bit, Edge> c_frontier_t;

typedef std::unordered_map<unsigned, unsigned> permutation_t;

/**
Expand Down Expand Up @@ -173,17 +168,6 @@ struct TraversalPoint {
Edge edge;
};

struct CutFrontier {
std::shared_ptr<Slice> slice;
std::shared_ptr<unit_frontier_t> u_frontier;
std::shared_ptr<b_frontier_t> b_frontier;
void init() {
slice = std::make_shared<Slice>();
u_frontier = std::make_shared<unit_frontier_t>();
b_frontier = std::make_shared<b_frontier_t>();
}
};

// list of error types to throw out
class CircuitInequality : public std::logic_error {
public:
Expand Down Expand Up @@ -253,53 +237,6 @@ class Circuit {
E_iterator &eend) const;

public:
/*SliceIterator class is used for lazy evaluation of slices */
class SliceIterator {
public: // these are currently public to allow skip_func slicing.
CutFrontier cut_;
std::shared_ptr<b_frontier_t> prev_b_frontier_;
const Circuit *circ_;

class Sliceholder {
private:
Slice current_slice_;

public:
explicit Sliceholder(Slice slice) : current_slice_(slice) {}
Slice operator*() const { return current_slice_; }
};

// take in an unsigned 'n' and a circuit and give the 'n'th slice
// note: n=0 gives an empty SliceIterator
// n=1 gives the first slice

SliceIterator(
const Circuit &circ, const std::function<bool(Op_ptr)> &skip_func);
explicit SliceIterator(const Circuit &circ);
SliceIterator() : cut_(), circ_() { cut_.init(); }
Slice operator*() const { return *cut_.slice; }
bool operator==(const SliceIterator &other) const {
return *cut_.slice == *other.cut_.slice;
}
bool operator!=(const SliceIterator &other) const {
return !(*this == other);
}
std::shared_ptr<const unit_frontier_t> get_u_frontier() const {
return cut_.u_frontier;
}
std::shared_ptr<const b_frontier_t> get_b_frontier() const {
return cut_.b_frontier;
}
std::shared_ptr<const b_frontier_t> get_prev_b_frontier() const {
return prev_b_frontier_;
}
// A postfix increment operator overload
Sliceholder operator++(int);
// A prefix increment operator overload
SliceIterator &operator++();
bool finished() const;
};

SliceIterator slice_begin() const;
static SliceIterator slice_end();
static const SliceIterator nullsit;
Expand Down Expand Up @@ -1164,14 +1101,10 @@ class Circuit {

// given current slice and a set of slices, returns the next slice
// O(q log^2(q!) alpha log(alpha!))
CutFrontier next_cut(
std::shared_ptr<const unit_frontier_t> u_frontier,
std::shared_ptr<const b_frontier_t> b_frontier) const;

CutFrontier next_cut(
std::shared_ptr<const unit_frontier_t> u_frontier,
std::shared_ptr<const b_frontier_t> b_frontier,
const std::function<bool(Op_ptr)> &skip_func) const;
const std::function<bool(Op_ptr)> &skip_func = 0) const;

// given current slice of quantum frontier, returns the next slice.
// ignore classical and boolean edges
Expand Down
91 changes: 91 additions & 0 deletions tket/include/tket/Circuit/Slices.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// 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 <memory>

#include "tket/Circuit/DAGDefs.hpp"
#include "tket/Utils/SequencedContainers.hpp"

namespace tket {

typedef VertexVec Slice;

typedef sequenced_map_t<UnitID, Edge> unit_frontier_t;
// typedef sequenced_map_t<Qubit, Edge> q_frontier_t;
typedef sequenced_map_t<Bit, EdgeVec> b_frontier_t;
// typedef sequenced_map_t<Bit, Edge> c_frontier_t;

struct CutFrontier {
std::shared_ptr<Slice> slice;
std::shared_ptr<unit_frontier_t> u_frontier;
std::shared_ptr<b_frontier_t> b_frontier;
void init() {
slice = std::make_shared<Slice>();
u_frontier = std::make_shared<unit_frontier_t>();
b_frontier = std::make_shared<b_frontier_t>();
}
};

class Circuit;

/*SliceIterator class is used for lazy evaluation of slices */
class SliceIterator {
public: // these are currently public to allow skip_func slicing.
CutFrontier cut_;
std::shared_ptr<b_frontier_t> prev_b_frontier_;
const Circuit *circ_;

class Sliceholder {
private:
Slice current_slice_;

public:
explicit Sliceholder(Slice slice) : current_slice_(slice) {}
Slice operator*() const { return current_slice_; }
};

// take in an unsigned 'n' and a circuit and give the 'n'th slice
// note: n=0 gives an empty SliceIterator
// n=1 gives the first slice

SliceIterator(
const Circuit &circ, const std::function<bool(Op_ptr)> &skip_func);
explicit SliceIterator(const Circuit &circ);
SliceIterator() : cut_(), circ_() { cut_.init(); }
Slice operator*() const { return *cut_.slice; }
bool operator==(const SliceIterator &other) const {
return *cut_.slice == *other.cut_.slice;
}
bool operator!=(const SliceIterator &other) const {
return !(*this == other);
}
std::shared_ptr<const unit_frontier_t> get_u_frontier() const {
return cut_.u_frontier;
}
std::shared_ptr<const b_frontier_t> get_b_frontier() const {
return cut_.b_frontier;
}
std::shared_ptr<const b_frontier_t> get_prev_b_frontier() const {
return prev_b_frontier_;
}
// A postfix increment operator overload
Sliceholder operator++(int);
// A prefix increment operator overload
SliceIterator &operator++();
bool finished() const;
};

} // namespace tket
4 changes: 3 additions & 1 deletion tket/src/Characterisation/Cycles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

#include <numeric>

#include "tket/Circuit/Slices.hpp"

namespace tket {

class CycleError : public std::logic_error {
Expand Down Expand Up @@ -314,7 +316,7 @@ std::vector<Cycle> CycleFinder::get_cycles() {
return (cycle_types_.find(op->get_type()) == cycle_types_.end());
};

Circuit::SliceIterator slice_iter(circ, skip_func);
SliceIterator slice_iter(circ, skip_func);
this->cycle_history.key = 0;

// initialization
Expand Down
Loading

0 comments on commit 2b871b8

Please sign in to comment.