Skip to content

Commit

Permalink
feat: ✨ Zero-Control diagnosis now works correctly into custom gate d…
Browse files Browse the repository at this point in the history
…efinitions
  • Loading branch information
DRovara committed Sep 17, 2024
1 parent 8a02304 commit fc5c418
Show file tree
Hide file tree
Showing 9 changed files with 84 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ Thumbs.db
/distro/main.fmf
/distro/plans/main.fmf
/distro/tests/main.fmf
experiments/

/docs/**/build
.vs
Expand Down
3 changes: 3 additions & 0 deletions include/backend/dd/DDSimDiagnostics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ struct DDDiagnostics {

DDSimulationState* simulationState;
std::map<size_t, std::set<size_t>> zeroControls;
std::map<size_t, std::set<size_t>> nonZeroControls;
};

size_t dddiagnosticsGetNumQubits(Diagnostics* self);
Expand All @@ -25,6 +26,8 @@ Result dddiagnosticsGetDataDependencies(Diagnostics* self, size_t instruction,
bool* instructions);
Result dddiagnosticsGetInteractions(Diagnostics* self, size_t beforeInstruction,
size_t qubit, bool* qubitsAreInteracting);
Result dddiagnosticsGetZeroControlInstructions(Diagnostics* self,
bool* instructions);
size_t dddiagnosticsPotentialErrorCauses(Diagnostics* self, ErrorCause* output,
size_t count);

Expand Down
1 change: 1 addition & 0 deletions include/backend/diagnostics.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct Diagnostics {
bool* instructions);
Result (*getInteractions)(Diagnostics* self, size_t beforeInstruction,
size_t qubit, bool* qubitsAreInteracting);
Result (*getZeroControlInstructions)(Diagnostics* self, bool* instructions);
size_t (*potentialErrorCauses)(Diagnostics* self, ErrorCause* output,
size_t count);
};
Expand Down
26 changes: 26 additions & 0 deletions src/backend/dd/DDSimDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Result createDDDiagnostics(DDDiagnostics* self, DDSimulationState* state) {
self->interface.getInstructionCount = dddiagnosticsGetInstructionCount;
self->interface.getInteractions = dddiagnosticsGetInteractions;
self->interface.getDataDependencies = dddiagnosticsGetDataDependencies;
self->interface.getZeroControlInstructions =
dddiagnosticsGetZeroControlInstructions;
self->interface.potentialErrorCauses = dddiagnosticsPotentialErrorCauses;

return self->interface.init(&self->interface);
Expand Down Expand Up @@ -213,6 +215,10 @@ size_t tryFindZeroControls(DDDiagnostics* diagnostics, size_t instruction,
if (diagnostics->zeroControls.find(i) == diagnostics->zeroControls.end()) {
continue;
}
if (diagnostics->nonZeroControls.find(i) !=
diagnostics->nonZeroControls.end()) {
continue;
}
const auto& zeroControls = diagnostics->zeroControls[i];
if (!zeroControls.empty()) {
outputs[index].type = ErrorCauseType::ControlAlwaysZero;
Expand Down Expand Up @@ -247,6 +253,20 @@ bool isAlwaysZero(const Statevector& sv, size_t qubit, bool checkOne = false) {
return true;
}

Result dddiagnosticsGetZeroControlInstructions(Diagnostics* self,
bool* instructions) {
auto* ddd = toDDDiagnostics(self);
const Span<bool> instructionSpan(instructions,
dddiagnosticsGetInstructionCount(self));
for (size_t i = 0; i < dddiagnosticsGetInstructionCount(self); i++) {
instructionSpan[i] =
(ddd->nonZeroControls.find(i) == ddd->nonZeroControls.end()) &&
(ddd->zeroControls.find(i) != ddd->zeroControls.end());
}

return OK;
}

void dddiagnosticsOnStepForward(DDDiagnostics* diagnostics,
size_t instruction) {
auto* ddsim = diagnostics->simulationState;
Expand All @@ -273,6 +293,12 @@ void dddiagnosticsOnStepForward(DDDiagnostics* diagnostics,
diagnostics->zeroControls[instruction] = std::set<size_t>();
}
diagnostics->zeroControls[instruction].insert(qubit);
} else {
if (diagnostics->nonZeroControls.find(instruction) ==
diagnostics->nonZeroControls.end()) {
diagnostics->nonZeroControls[instruction] = std::set<size_t>();
}
diagnostics->nonZeroControls[instruction].insert(qubit);
}
}
}
1 change: 1 addition & 0 deletions src/mqt/debug/pydebug.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class Diagnostics:
def get_instruction_count(self) -> int: ...
def get_data_dependencies(self, instruction: int) -> list[int]: ...
def get_interactions(self, before_instruction: int, qubit: int) -> list[int]: ...
def get_zero_control_instructions(self) -> list[int]: ...
def potential_error_causes(self) -> list[ErrorCause]: ...

def create_ddsim_simulation_state() -> SimulationState: ...
Expand Down
15 changes: 15 additions & 0 deletions src/python/InterfaceBindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,21 @@ void bindDiagnostics(py::module& m) {
}
return result;
})
.def("get_zero_control_instructions",
[](Diagnostics* self) {
std::vector<uint8_t> instructions(self->getInstructionCount(self));
// NOLINTBEGIN(cppcoreguidelines-pro-type-reinterpret-cast)
checkOrThrow(self->getZeroControlInstructions(
self, reinterpret_cast<bool*>(instructions.data())));
// NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast)
std::vector<size_t> result;
for (size_t i = 0; i < instructions.size(); i++) {
if (instructions[i] != 0) {
result.push_back(i);
}
}
return result;
})
.def("potential_error_causes", [](Diagnostics* self) {
size_t nextSize = 10;
while (true) {
Expand Down
19 changes: 19 additions & 0 deletions test/circuits/zero-controls-with-jumps.qasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
qreg q[3];

x q[0];

gate test1 q0, q1 {
cx q0, q1;
}

gate test2 q0, q1 {
cx q0, q1;
}

test1 q[2], q[1];
test1 q[1], q[2];

test2 q[0], q[2];
test2 q[1], q[2];

cx q[1], q[2];
8 changes: 8 additions & 0 deletions test/python/test_diagnosis.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,11 @@ def test_missing_interaction() -> None:
causes = [x for x in s.get_diagnostics().potential_error_causes() if x.type == ErrorCauseType.MissingInteraction]
assert len(causes) == 1
assert causes[0].instruction == 4


def test_zero_control_listing() -> None:
"""Test the zero-control list."""
s = load_instance("control-always-zero")
s.run_simulation()
zero_controls = s.get_diagnostics().get_zero_control_instructions()
assert zero_controls == [3, 12]
10 changes: 10 additions & 0 deletions test/test_diagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,13 @@ TEST_F(DiagnosticsTest, RequestZeroProblems) {
diagnostics->potentialErrorCauses(diagnostics, problems.data(), 0);
ASSERT_EQ(count, 0);
}

TEST_F(DiagnosticsTest, ZeroControlsWithJumps) {
loadFromFile("zero-controls-with-jumps");
state->runSimulation(state);
std::array<bool, 13> zeroControls{};
diagnostics->getZeroControlInstructions(diagnostics, zeroControls.data());
for (size_t i = 0; i < zeroControls.size(); i++) {
ASSERT_FALSE(zeroControls.at(i) ^ (i == 3 || i == 12));
}
}

0 comments on commit fc5c418

Please sign in to comment.