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

Feature/TwoQubitEncoding #342

Draft
wants to merge 38 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
5a32776
set the main structure
Jun 23, 2023
014f075
Merge branch 'main' into feature/avelsh
avelsh Jun 23, 2023
9c9256e
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 23, 2023
a7822e0
add SQG and TQG encoding
Jul 8, 2023
59393a8
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 8, 2023
cdd566e
update comments
Jul 13, 2023
716b8a6
Merge remote-tracking branch 'origin/feature/avelsh' into feature/avelsh
Jul 13, 2023
499b06e
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 13, 2023
d283ef8
update according to comments, rename two qubit encoder
Jul 30, 2023
77cc2a5
Merge remote-tracking branch 'origin/feature/avelsh' into feature/avelsh
Jul 30, 2023
7c7d542
🎨 pre-commit fixes
pre-commit-ci[bot] Jul 30, 2023
9b0155a
correct asssertTwoQubitGateConstr
Aug 9, 2023
c9c1a44
Merge remote-tracking branch 'origin/feature/avelsh' into feature/avelsh
Aug 9, 2023
0266b24
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 9, 2023
122dd5d
fix two qubit encoding
Aug 14, 2023
1c0a309
rename from STDepth to TQDepth
Aug 14, 2023
7ca3ec7
sync with upstream
Aug 14, 2023
dfea58a
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 14, 2023
cf12bef
remove addIdentityGateToTQGVariables func
Aug 14, 2023
c095997
set a new func for founding of a two qubit depth
Aug 16, 2023
b6e11dd
Merge remote-tracking branch 'origin/feature/avelsh' into feature/avelsh
Aug 16, 2023
b128086
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 16, 2023
e37653d
fix founding of phase and set the last layer of paulis
Aug 21, 2023
8d1da8f
remove irrelevant tests
Aug 21, 2023
d042b11
set bindings and small fixes
Sep 5, 2023
92c5df6
optimize the using of variables
Sep 6, 2023
727fba8
Merge branch 'main' into feature/avelsh
pehamTom Sep 9, 2023
0425bfc
Merge remote-tracking branch 'avelsh/feature/avelsh' into feature/avelsh
pehamTom Sep 9, 2023
bd9af05
🎨 pre-commit fixes
pre-commit-ci[bot] Sep 9, 2023
3a4c206
Added parsing of target metric for two_qubit_depth
pehamTom Sep 9, 2023
247e276
Merge remote-tracking branch 'avelsh/feature/avelsh' into feature/avelsh
pehamTom Sep 9, 2023
1b39f2b
update according comments
Sep 10, 2023
c8bb1d6
Merge remote-tracking branch 'origin/feature/avelsh' into feature/avelsh
Sep 10, 2023
a80fd55
🎨 pre-commit fixes
pre-commit-ci[bot] Sep 10, 2023
098d4d6
set a new extra SQG layer
Sep 18, 2023
caafb46
🎨 pre-commit fixes
pre-commit-ci[bot] Sep 18, 2023
31090be
create a new func pauliGateToIndex
Oct 10, 2023
292052b
Merge remote-tracking branch 'origin/feature/avelsh' into feature/avelsh
Oct 10, 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 extern/LogicBlocks
6 changes: 6 additions & 0 deletions include/cliffordsynthesis/CliffordSynthesizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ class CliffordSynthesizer {
return metric == TargetMetric::Depth;
}

static bool requiresTwoQubitEncoding(const TargetMetric metric) {
return metric == TargetMetric::TwoQubitDepth;
}

void determineInitialTimestepLimit(EncoderConfig& config);
std::pair<std::size_t, std::size_t> determineUpperBound(EncoderConfig config);
void runMaxSAT(const EncoderConfig& config);
Expand All @@ -92,6 +96,8 @@ class CliffordSynthesizer {
std::size_t upper);
void depthOptimalSynthesis(EncoderConfig config, std::size_t lower,
std::size_t upper);
void twoQubitDepthOptimalSynthesis(EncoderConfig config, std::size_t lower,
std::size_t upper);
void depthHeuristicSynthesis();
void twoQubitGateOptimalSynthesis(EncoderConfig config, std::size_t lower,
std::size_t upper);
Expand Down
11 changes: 8 additions & 3 deletions include/cliffordsynthesis/Configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ struct Configuration {
/// Settings for depth-optimal synthesis
bool minimizeGatesAfterDepthOptimization = false;

/// Settings for TwoQubitDepth-optimal synthesis
bool useTwoQubitEncoding = false;

/// Settings for two-qubit gate-optimal synthesis
bool tryHigherGateLimitForTwoQubitGateOptimization = false;
double gateLimitFactor = 1.1;
Expand All @@ -63,9 +66,10 @@ struct Configuration {
j["gate_limit_factor"] = gateLimitFactor;
j["minimize_gates_after_two_qubit_gate_optimization"] =
minimizeGatesAfterTwoQubitGateOptimization;
j["heuristic"] = heuristic;
j["split_size"] = splitSize;
j["n_threads_heuristic"] = nThreadsHeuristic;
j["use_two_qubit_encoding"] = useTwoQubitEncoding;
j["heuristic"] = heuristic;
j["split_size"] = splitSize;
j["n_threads_heuristic"] = nThreadsHeuristic;
if (!solverParameters.empty()) {
nlohmann::json solverParametersJson;
for (const auto& entry : solverParameters) {
Expand All @@ -77,6 +81,7 @@ struct Configuration {
}
j["solver_parameters"] = solverParametersJson;
}

return j;
}

Expand Down
14 changes: 10 additions & 4 deletions include/cliffordsynthesis/Results.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class Results {
setResultCircuit(qc);
setResultTableau(tableau);
setDepth(qc.getDepth());
setTwoQubitDepth(qc.getTwoQubitDepth());
setSingleQubitGates(qc.getNsingleQubitOps());
setTwoQubitGates(qc.getNindividualOps() - singleQubitGates);
setSolverResult(logicbase::Result::SAT);
Expand All @@ -39,8 +40,9 @@ class Results {
[[nodiscard]] std::size_t getSingleQubitGates() const {
return singleQubitGates;
}
[[nodiscard]] std::size_t getDepth() const { return depth; }
[[nodiscard]] double getRuntime() const { return runtime; }
[[nodiscard]] std::size_t getDepth() const { return depth; }
[[nodiscard]] std::size_t getTwoQubitDepth() const { return twoQubitDepth; }
[[nodiscard]] double getRuntime() const { return runtime; }
[[nodiscard]] logicbase::Result getSolverResult() const {
return solverResult;
}
Expand All @@ -52,6 +54,7 @@ class Results {
void setSingleQubitGates(const std::size_t g) { singleQubitGates = g; }
void setTwoQubitGates(const std::size_t g) { twoQubitGates = g; }
void setDepth(const std::size_t d) { depth = d; }
void setTwoQubitDepth(const std::size_t d) { twoQubitDepth = d; }
void setRuntime(const double t) { runtime = t; }
void setSolverResult(const logicbase::Result r) { solverResult = r; }
void setSolverCalls(const std::size_t c) { solverCalls = c; }
Expand Down Expand Up @@ -80,6 +83,7 @@ class Results {
resultJSON["single_qubit_gates"] = singleQubitGates;
resultJSON["two_qubit_gates"] = twoQubitGates;
resultJSON["depth"] = depth;
resultJSON["twoQubitDepth"] = twoQubitDepth;
resultJSON["runtime"] = runtime;
resultJSON["solver_calls"] = solverCalls;

Expand All @@ -96,8 +100,10 @@ class Results {
std::size_t singleQubitGates = std::numeric_limits<std::size_t>::max();
std::size_t twoQubitGates = std::numeric_limits<std::size_t>::max();
std::size_t depth = std::numeric_limits<std::size_t>::max();
double runtime = 0.0;
std::size_t solverCalls = 0U;
std::size_t twoQubitDepth = std::numeric_limits<std::size_t>::max();

double runtime = 0.0;
std::size_t solverCalls = 0U;

std::string resultTableau{};
std::string resultCircuit{};
Expand Down
7 changes: 6 additions & 1 deletion include/cliffordsynthesis/TargetMetric.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include <string>

namespace cs {
enum class TargetMetric { Gates, TwoQubitGates, Depth };
enum class TargetMetric { Gates, TwoQubitGates, Depth, TwoQubitDepth };

[[maybe_unused]] static inline std::string toString(const TargetMetric target) {
switch (target) {
Expand All @@ -19,6 +19,8 @@ enum class TargetMetric { Gates, TwoQubitGates, Depth };
return "two_qubit_gates";
case TargetMetric::Depth:
return "depth";
case TargetMetric::TwoQubitDepth:
return "two_qubit_depth";
}
return "Error";
}
Expand All @@ -34,6 +36,9 @@ targetMetricFromString(const std::string& target) {
if (target == "depth") {
return TargetMetric::Depth;
}
if (target == "two_qubit_depth") {
return TargetMetric::TwoQubitDepth;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please rename

return TargetMetric::Gates;
}
} // namespace cs
30 changes: 17 additions & 13 deletions include/cliffordsynthesis/encoding/GateEncoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ class GateEncoder {
};

// variable creation
void createSingleQubitGateVariables();
void createTwoQubitGateVariables();
virtual void createSingleQubitGateVariables();
virtual void createTwoQubitGateVariables();

// encode the relation between the tableaus and the gates
virtual void encodeGates() {
Expand All @@ -52,13 +52,17 @@ class GateEncoder {
virtual void encodeSymmetryBreakingConstraints();

// extracting the circuit
void extractCircuitFromModel(Results& res, logicbase::Model& model);
virtual void extractCircuitFromModel(Results& res, logicbase::Model& model);

[[nodiscard]] auto* getVariables() { return &vars; }

static constexpr std::array<qc::OpType, 7> SINGLE_QUBIT_GATES = {
qc::OpType::None, qc::OpType::X, qc::OpType::Y, qc::OpType::Z,
qc::OpType::H, qc::OpType::S, qc::OpType::Sdag};
// TODO: set back
static constexpr std::array<qc::OpType, 4> SINGLE_QUBIT_GATES = {
qc::OpType::None, qc::OpType::H, qc::OpType::S, qc::OpType::SX};

// static constexpr std::array<qc::OpType, 7> SINGLE_QUBIT_GATES = {
// qc::OpType::None, qc::OpType::X, qc::OpType::Y, qc::OpType::Z,
// qc::OpType::H, qc::OpType::S, qc::OpType::Sdag};
Fixed Show fixed Hide fixed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, you can leave this like this at the moment.


Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think PAULI_GATES is a better name here.

[[nodiscard]] static constexpr std::size_t
gateToIndex(const qc::OpType type) {
Expand Down Expand Up @@ -130,9 +134,9 @@ class GateEncoder {
virtual void assertSingleQubitGateConstraints(std::size_t pos) = 0;
virtual void assertTwoQubitGateConstraints(std::size_t pos) = 0;
[[nodiscard]] static std::vector<TransformationFamily>
collectGateTransformations(std::size_t pos, std::size_t qubit,
const GateToTransformation& gateToTransformation);
void assertGatesImplyTransform(
collectGateTransformations(std::size_t pos, std::size_t qubit,
const GateToTransformation& gateToTransformation);
virtual void assertGatesImplyTransform(
std::size_t pos, std::size_t qubit,
const std::vector<TransformationFamily>& transformations);
virtual void assertZConstraints(std::size_t pos, std::size_t qubit);
Expand All @@ -142,10 +146,10 @@ class GateEncoder {
createTwoQubitGateConstraint(std::size_t pos, std::size_t ctrl,
std::size_t trgt) = 0;

void extractSingleQubitGatesFromModel(std::size_t pos,
logicbase::Model& model,
qc::QuantumComputation& qc,
std::size_t& nSingleQubitGates);
virtual void extractSingleQubitGatesFromModel(std::size_t pos,
logicbase::Model& model,
qc::QuantumComputation& qc,
std::size_t& nSingleQubitGates);
void extractTwoQubitGatesFromModel(std::size_t pos, logicbase::Model& model,
qc::QuantumComputation& qc,
std::size_t& nTwoQubitGates);
Expand Down
6 changes: 6 additions & 0 deletions include/cliffordsynthesis/encoding/SATEncoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ class SATEncoder {
// whether to use symmetry breaking
bool useSymmetryBreaking = false;

// whether to use two qubit encoding
bool useTwoQubitEncoding = false;

// the number of threads to pass to the SAT solver
std::size_t nThreads = 1U;

// an optional limit on the total number of gates
std::optional<std::size_t> gateLimit = std::nullopt;

Expand Down
77 changes: 77 additions & 0 deletions include/cliffordsynthesis/encoding/TwoQubitEncoder.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// Created by Velsh Aleksei on 16.06.23.
//

#pragma once

#include "cliffordsynthesis/encoding/GateEncoder.hpp"

#include <cstddef>
#include <optional>

namespace cs::encoding {

class TwoQubitEncoder : public GateEncoder {
public:
using GateEncoder::GateEncoder;

protected:
// define variables
logicbase::LogicTerm rChanges{};
logicbase::LogicMatrix xorHelpers{};
logicbase::LogicMatrix gP{};

static constexpr std::array<qc::OpType, 4> PAULI_GATES = {
qc::OpType::None, qc::OpType::X, qc::OpType::Y, qc::OpType::Z};

[[nodiscard]] constexpr std::size_t
paulieGateToIndex(const qc::OpType type) {
for (std::size_t i = 0; i < PAULI_GATES.size(); ++i) {
if (PAULI_GATES.at(i) == type) {
return i;
}
}
return 0;
}

// variable creation
virtual void createSingleQubitGateVariables() override;
virtual void createTwoQubitGateVariables() override;
void createPauliGateVariables();

// create constrains
[[nodiscard]] logicbase::LogicTerm
createTwoQubitGateConstraint(std::size_t pos, std::size_t ctrl,
std::size_t trgt) override;

// assert constrains
void assertConsistency() const override;
void assertGateConstraints() override;
void assertRConstraints(std::size_t pos, std::size_t qubit) override;
void assertSingleQubitGateConstraints(std::size_t pos) override;
void assertPauliGateConstraints(std::size_t pos);
void assertTwoQubitGateConstraints(std::size_t pos) override;
void assertSingleQubitGateOrderConstraints(std::size_t pos,
std::size_t qubit) override;
void assertTwoQubitGateOrderConstraints(std::size_t pos, std::size_t ctrl,
std::size_t trgt) override;

// collect TQG variables
void collectPauliGateVariables(std::size_t qubit,
logicbase::LogicVector& variables) const;

// extracting
void extractCircuitFromModel(Results& res, logicbase::Model& model) override;
void extractPauliGatesFromModel(logicbase::Model& model,
qc::QuantumComputation& qc,
std::size_t& nSingleQubitGates);

// helpers
void splitXorR(const logicbase::LogicTerm& changes, std::size_t pos);
virtual void assertGatesImplyTransform(
std::size_t pos, std::size_t qubit,
const std::vector<TransformationFamily>& transformations) override;
virtual void encodeSymmetryBreakingConstraints() override;
};

} // namespace cs::encoding
2 changes: 2 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ macro(ADD_SYNTHESIS_LIBRARY libname srcfile)
${PROJECT_SOURCE_DIR}/include/cliffordsynthesis/Configuration.hpp
${PROJECT_SOURCE_DIR}/include/cliffordsynthesis/encoding/GateEncoder.hpp
${PROJECT_SOURCE_DIR}/include/cliffordsynthesis/encoding/MultiGateEncoder.hpp
${PROJECT_SOURCE_DIR}/include/cliffordsynthesis/encoding/TwoQubitEncoder.hpp
${PROJECT_SOURCE_DIR}/include/cliffordsynthesis/encoding/ObjectiveEncoder.hpp
${PROJECT_SOURCE_DIR}/include/cliffordsynthesis/encoding/SATEncoder.hpp
${PROJECT_SOURCE_DIR}/include/cliffordsynthesis/encoding/SingleGateEncoder.hpp
Expand All @@ -70,6 +71,7 @@ macro(ADD_SYNTHESIS_LIBRARY libname srcfile)
${PROJECT_SOURCE_DIR}/include/utils.hpp
cliffordsynthesis/encoding/GateEncoder.cpp
cliffordsynthesis/encoding/MultiGateEncoder.cpp
cliffordsynthesis/encoding/TwoQubitEncoder.cpp
cliffordsynthesis/encoding/ObjectiveEncoder.cpp
cliffordsynthesis/encoding/SATEncoder.cpp
cliffordsynthesis/encoding/SingleGateEncoder.cpp
Expand Down
Loading