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

Support any two qubit gates #235

Draft
wants to merge 32 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c845d37
🔥 Remove assert in countGates
JoachimMarin Feb 13, 2023
d526398
✨ Preserve operation type for two qubit gates
JoachimMarin Feb 13, 2023
27b1b20
🚧 Generalize naming for two-qubit gates
JoachimMarin Feb 13, 2023
7002c93
🎨 Rename cnots to twoQubitGates
JoachimMarin Feb 13, 2023
03f4214
🎨 pre-commit fixes
pre-commit-ci[bot] Feb 13, 2023
5f49023
:sparkles: Case distinction for flipping gates
JoachimMarin Feb 20, 2023
4e8648a
🎨 pre-commit fixes
pre-commit-ci[bot] Feb 20, 2023
6d33c87
✨ Function for gate reversal cost
JoachimMarin Mar 4, 2023
3b05b62
:rewind: Assume cnot gates in distance table
JoachimMarin Mar 5, 2023
7b38085
:white_check_mark: Add direction reverse python tests
JoachimMarin Mar 5, 2023
e7127dd
:bulb: Add python test descriptions
JoachimMarin Mar 6, 2023
6dfbb94
🚨 Fix ruff warnings for python tests
JoachimMarin Mar 6, 2023
4016c86
Merge remote-tracking branch 'upstream/main' into support-any-two-qub…
JoachimMarin Mar 6, 2023
ff3929c
🚨 Fix missing return on unexpected enum value
JoachimMarin Mar 6, 2023
91b7969
✅ Remove InstructionSet import
JoachimMarin Mar 6, 2023
219eda2
✅ Use gate objects for python tests
JoachimMarin Mar 7, 2023
2bd795e
🩹 fix Python typing
burgholzer Mar 7, 2023
88a82ee
🩹 silence an external Qiskit warning from the tests
burgholzer Mar 7, 2023
90764c3
Merge remote-tracking branch 'origin/main' into support-any-two-qubit…
burgholzer Mar 7, 2023
f0f19e3
♻️ restructure tests
burgholzer Mar 7, 2023
e71fb87
🐛 Prevent reversals with swaps in exact mapper
JoachimMarin Mar 11, 2023
45deaab
Update include/Mapper.hpp
burgholzer Mar 11, 2023
e43c357
🚨 some `const`
burgholzer Mar 11, 2023
3c982bc
🚚 rename `insertFlippedGate` method
burgholzer Mar 11, 2023
80609be
♻️ refactor condition to simplify code
burgholzer Mar 11, 2023
44d81c8
⚡ add missing conditional skip statement
burgholzer Mar 11, 2023
31e73b3
🚸 add additional sanity check
burgholzer Mar 11, 2023
a33e1d1
🚸 add `const` version of the mapped circuit getter
burgholzer Mar 11, 2023
12ab7fa
♻️ simplify tests
burgholzer Mar 11, 2023
0aec519
🐛 fix coupling limit computation for directed architectures
burgholzer Mar 11, 2023
8897aa4
🧪 Add direction reverse tests for heuristic mapper
JoachimMarin Mar 14, 2023
34cc4bd
✨ Update heuristic algorithm for direction reverse
JoachimMarin Mar 14, 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
16 changes: 8 additions & 8 deletions include/MappingResults.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ struct MappingResults {
std::uint16_t qubits = 0;
std::size_t gates = 0;
std::size_t singleQubitGates = 0;
std::size_t cnots = 0;
std::size_t twoQubitGates = 0;
std::size_t layers = 0;

// info in output circuit
Expand Down Expand Up @@ -62,14 +62,14 @@ struct MappingResults {
circuit["qubits"] = input.qubits;
circuit["gates"] = input.gates;
circuit["single_qubit_gates"] = input.singleQubitGates;
circuit["cnots"] = input.cnots;
circuit["cnots"] = input.twoQubitGates;

auto& mappedCirc = resultJSON["mapped_circuit"];
mappedCirc["name"] = output.name;
mappedCirc["qubits"] = output.qubits;
mappedCirc["gates"] = output.gates;
mappedCirc["single_qubit_gates"] = output.singleQubitGates;
mappedCirc["cnots"] = output.cnots;
mappedCirc["cnots"] = output.twoQubitGates;
if (!mappedCircuit.empty()) {
mappedCirc["qasm"] = mappedCircuit;
}
Expand Down Expand Up @@ -100,11 +100,11 @@ struct MappingResults {
virtual std::string csv() {
std::stringstream ss{};
ss << input.name << ";" << input.qubits << ";" << input.gates << ";"
<< input.singleQubitGates << ";" << input.cnots << ";" << architecture
<< ";" << output.name << ";" << output.qubits << ";" << output.gates
<< ";" << output.singleQubitGates << ";" << output.cnots << ";"
<< output.swaps << ";" << output.directionReverse << ";"
<< output.teleportations << ";";
<< input.singleQubitGates << ";" << input.twoQubitGates << ";"
<< architecture << ";" << output.name << ";" << output.qubits << ";"
<< output.gates << ";" << output.singleQubitGates << ";"
<< output.twoQubitGates << ";" << output.swaps << ";"
<< output.directionReverse << ";" << output.teleportations << ";";
if (timeout) {
ss << "TO";
} else {
Expand Down
3 changes: 2 additions & 1 deletion mqt/qmap/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ PYBIND11_MODULE(pyqmap, m) {
.def_readwrite("gates", &MappingResults::CircuitInfo::gates)
.def_readwrite("single_qubit_gates",
&MappingResults::CircuitInfo::singleQubitGates)
.def_readwrite("cnots", &MappingResults::CircuitInfo::cnots)
.def_readwrite("two_qubit_gates",
&MappingResults::CircuitInfo::twoQubitGates)
.def_readwrite("layers", &MappingResults::CircuitInfo::layers)
.def_readwrite("swaps", &MappingResults::CircuitInfo::swaps)
.def_readwrite("direction_reverse",
Expand Down
7 changes: 3 additions & 4 deletions src/Mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,18 +280,17 @@ void Mapper::countGates(decltype(qcMapped.cbegin()) it,
if (g->getType() == qc::SWAP) {
if (architecture.bidirectional()) {
info.gates += GATES_OF_BIDIRECTIONAL_SWAP;
info.cnots += GATES_OF_BIDIRECTIONAL_SWAP;
info.twoQubitGates += GATES_OF_BIDIRECTIONAL_SWAP;
} else {
info.gates += GATES_OF_UNIDIRECTIONAL_SWAP;
info.cnots += GATES_OF_BIDIRECTIONAL_SWAP;
info.twoQubitGates += GATES_OF_BIDIRECTIONAL_SWAP;
info.singleQubitGates += GATES_OF_DIRECTION_REVERSE;
}
} else if (g->getControls().empty()) {
++info.singleQubitGates;
++info.gates;
} else {
assert(g->getType() == qc::X);
++info.cnots;
++info.twoQubitGates;
++info.gates;
}
continue;
Expand Down
51 changes: 29 additions & 22 deletions src/exact/ExactMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,38 +275,45 @@ void ExactMapper::map(const Configuration& settings) {
op->getParameter().at(0), op->getParameter().at(1),
op->getParameter().at(2));
} else {
const Edge cnot = {locations.at(static_cast<std::size_t>(gate.control)),
locations.at(gate.target)};
const Edge controlledGate = {
locations.at(static_cast<std::size_t>(gate.control)),
locations.at(gate.target)};

if (architecture.getCouplingMap().find(cnot) ==
if (architecture.getCouplingMap().find(controlledGate) ==
architecture.getCouplingMap().end()) {
const Edge reverse = {cnot.second, cnot.first};
const Edge reverse = {controlledGate.second, controlledGate.first};
if (architecture.getCouplingMap().find(reverse) ==
architecture.getCouplingMap().end()) {
throw QMAPException(
"Invalid CNOT: " + std::to_string(reverse.first) + "-" +
std::to_string(reverse.second));
throw QMAPException("Invalid controlled gate " + op->getName() +
": " + std::to_string(reverse.first) + "-" +
std::to_string(reverse.second));
}
if (settings.verbose) {
std::cout
<< i
<< ": Added (direction-reversed) cnot with control and target: "
<< cnot.first << " " << cnot.second << std::endl;
std::cout << i << ": Added (direction-reversed) controlled gate "
<< op->getName()
<< " with control and target: " << controlledGate.first
<< " " << controlledGate.second << std::endl;
}
qcMapped.h(reverse.first);
qcMapped.h(reverse.second);
qcMapped.x(reverse.second,
qc::Control{static_cast<qc::Qubit>(reverse.first)});
qcMapped.emplace_back<qc::StandardOperation>(
qcMapped.getNqubits(),
qc::Control{static_cast<qc::Qubit>(reverse.first)},
reverse.second, op->getType(), op->getParameter().at(0),
op->getParameter().at(1), op->getParameter().at(2));
qcMapped.h(reverse.second);
qcMapped.h(reverse.first);
burgholzer marked this conversation as resolved.
Show resolved Hide resolved
} else {
if (settings.verbose) {
std::cout << i
<< ": Added cnot with control and target: " << cnot.first
<< " " << cnot.second << std::endl;
std::cout << i << ": Added controlled gate " << op->getName()
<< " with control and target: " << controlledGate.first
<< " " << controlledGate.second << std::endl;
}
qcMapped.x(cnot.second,
qc::Control{static_cast<qc::Qubit>(cnot.first)});
qcMapped.emplace_back<qc::StandardOperation>(
qcMapped.getNqubits(),
qc::Control{static_cast<qc::Qubit>(controlledGate.first)},
controlledGate.second, op->getType(), op->getParameter().at(0),
op->getParameter().at(1), op->getParameter().at(2));
}
}
}
Expand Down Expand Up @@ -354,7 +361,7 @@ void ExactMapper::map(const Configuration& settings) {

// 10) re-count gates
results.output.singleQubitGates = 0U;
results.output.cnots = 0U;
results.output.twoQubitGates = 0U;
results.output.gates = 0U;
countGates(qcMapped, results.output);

Expand Down Expand Up @@ -762,9 +769,9 @@ number of variables: (|L|-1) * m!
// quickly determine cost
choiceResults.output.singleQubitGates =
choiceResults.input.singleQubitGates;
choiceResults.output.cnots = choiceResults.input.cnots;
choiceResults.output.gates =
choiceResults.output.singleQubitGates + choiceResults.output.cnots;
choiceResults.output.twoQubitGates = choiceResults.input.twoQubitGates;
choiceResults.output.gates = choiceResults.output.singleQubitGates +
choiceResults.output.twoQubitGates;
assert(choiceResults.output.swaps == 0U);
assert(choiceResults.output.directionReverse == 0U);
// swaps
Expand Down
26 changes: 16 additions & 10 deletions src/heuristic/HeuristicMapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,30 +94,36 @@ void HeuristicMapper::map(const Configuration& configuration) {
gateidx++;
}
} else {
const Edge cnot = {
const Edge controlledGate = {
locations.at(static_cast<std::uint16_t>(gate.control)),
locations.at(gate.target)};
if (architecture.getCouplingMap().find(cnot) ==
if (architecture.getCouplingMap().find(controlledGate) ==
architecture.getCouplingMap().end()) {
const Edge reverse = {cnot.second, cnot.first};
const Edge reverse = {controlledGate.second, controlledGate.first};
if (architecture.getCouplingMap().find(reverse) ==
architecture.getCouplingMap().end()) {
throw QMAPException(
"Invalid CNOT: " + std::to_string(reverse.first) + "-" +
std::to_string(reverse.second));
throw QMAPException("Invalid controlled gate " + op->getName() +
": " + std::to_string(reverse.first) + "-" +
std::to_string(reverse.second));
}
qcMapped.h(reverse.first);
qcMapped.h(reverse.second);
qcMapped.x(reverse.second,
qc::Control{static_cast<qc::Qubit>(reverse.first)});
qcMapped.emplace_back<qc::StandardOperation>(
qcMapped.getNqubits(),
qc::Control{static_cast<qc::Qubit>(reverse.first)},
reverse.second, op->getType(), op->getParameter().at(0),
op->getParameter().at(1), op->getParameter().at(2));
qcMapped.h(reverse.second);
qcMapped.h(reverse.first);

results.output.directionReverse++;
gateidx += 5;
} else {
qcMapped.x(cnot.second,
qc::Control{static_cast<qc::Qubit>(cnot.first)});
qcMapped.emplace_back<qc::StandardOperation>(
qcMapped.getNqubits(),
qc::Control{static_cast<qc::Qubit>(controlledGate.first)},
controlledGate.second, op->getType(), op->getParameter().at(0),
op->getParameter().at(1), op->getParameter().at(2));
gateidx++;
}
}
Expand Down