Skip to content

Commit

Permalink
feat(assertion-tools): ✨ Add assertion suggestion to CLI Frontend
Browse files Browse the repository at this point in the history
  • Loading branch information
DRovara committed Oct 18, 2024
1 parent 2fd11d3 commit f5b30b0
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 14 deletions.
8 changes: 7 additions & 1 deletion include/frontend/cli/CliFrontEnd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ class CliFrontEnd {
std::string currentCode;

/**
* @brief Print the current state (state vector etc.) in the command line.
* @brief Print the current state of the simulation.
* @param state The simulation state.
* @param inspecting The instruction that is currently inspected (or -1ULL if
* nothing is being inspected).
* @param codeOnly If true, only the code is displayed, not the state.
*/
void printState(SimulationState* state, size_t inspecting,
bool codeOnly = false);
Expand All @@ -50,4 +54,6 @@ class CliFrontEnd {
* @brief Initialize the code for running it at a later time.
*/
void initCode(const char* code);

void suggestUpdatedAssertions(SimulationState* state);
};
9 changes: 7 additions & 2 deletions src/backend/dd/DDSimDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,19 @@
#include "common/Span.hpp"
#include "common/parsing/AssertionParsing.hpp"
#include "common/parsing/AssertionTools.hpp"
#include "common/parsing/CodePreprocessing.hpp"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iterator>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

/**
Expand Down Expand Up @@ -689,8 +693,9 @@ size_t dddiagnosticsSuggestNewAssertions(Diagnostics* self,
assertionString << qubit + ", ";
}
const auto string =
assertionString.str().substr(0, assertionString.str().size() - 2);
strcpy(assertions[index], string.c_str());
assertionString.str().substr(0, assertionString.str().size() - 2) +
";\n";
strncpy(assertions[index], string.c_str(), string.length());
index++;
if (index == count) {
return index;
Expand Down
96 changes: 89 additions & 7 deletions src/frontend/cli/CliFrontEnd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@
#include "backend/diagnostics.h"
#include "common.h"

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <set>
#include <string>
#include <vector>

Expand Down Expand Up @@ -54,6 +57,7 @@ void CliFrontEnd::run(const char* code, SimulationState* state) {
std::cout << "get <variable>\t";
std::cout << "reset\t";
std::cout << "inspect\t";
std::cout << "assertions\t";
std::cout << "exit\n\n";
wasError = false;
}
Expand Down Expand Up @@ -104,6 +108,8 @@ void CliFrontEnd::run(const char* code, SimulationState* state) {
const auto count = state->getDiagnostics(state)->potentialErrorCauses(
state->getDiagnostics(state), problems.data(), problems.size());
std::cout << count << " potential problems found\n";
} else if (command == "assertions") {
suggestUpdatedAssertions(state);
} else {
wasError = true;
}
Expand All @@ -127,13 +133,89 @@ std::vector<std::string> getBitStrings(size_t numQubits) {
return bitStrings;
}

/**
* @brief Print the current state of the simulation.
* @param state The simulation state.
* @param inspecting The instruction that is currently inspected (or -1ULL if
* nothing is being inspected).
* @param codeOnly If true, only the code is displayed, not the state.
*/
void CliFrontEnd::suggestUpdatedAssertions(SimulationState* state) {
auto* diagnostics = state->getDiagnostics(state);
std::string newCode = currentCode;
const size_t count = 10;
std::vector<std::array<char, 256>> newAssertions(count);
std::vector<char*> newAssertionsPointers(count);
std::transform(newAssertions.begin(), newAssertions.end(),
newAssertionsPointers.begin(),
[](std::array<char, 256>& arr) { return arr.data(); });
std::vector<size_t> newPositions(count);

size_t found = diagnostics->suggestNewAssertions(
diagnostics, newPositions.data(), newAssertionsPointers.data(), count);
std::set<size_t> coveredPositions;
for (size_t i = found - 1; i != -1ULL; i--) {
size_t start = 0;
size_t end = 0;
state->getInstructionPosition(state, newPositions[i], &start, &end);
if (coveredPositions.find(newPositions[i]) == coveredPositions.end()) {
coveredPositions.insert(newPositions[i]);
newCode.erase(start, end - start + 1);
}
newCode.insert(start, newAssertions[i].data());
}

state->resetSimulation(state);
state->loadCode(state, newCode.c_str());
size_t errors = 0;
state->runAll(state, &errors);

std::vector<size_t> beforeMove(count);
std::vector<size_t> afterMove(count);
diagnostics = state->getDiagnostics(state);
found = diagnostics->suggestAssertionMovements(diagnostics, beforeMove.data(),
afterMove.data(), count);

for (size_t i = 0; i < found; i++) {
size_t start = 0;
size_t end = 0;
state->getInstructionPosition(state, beforeMove[i], &start, &end);
if (end < newCode.length() - 1 &&
(newCode[end + 1] == '\n' || newCode[end + 1] == ' ')) {
end++;
}
const std::string assertion = newCode.substr(start, end - start + 1);
newCode.erase(start, end - start + 1);
state->getInstructionPosition(state, afterMove[i], &start, &end);
newCode.insert(start, assertion);
for (size_t j = i + 1; j < found; j++) {
if (beforeMove[j] > beforeMove[i]) {
beforeMove[j]--;
}
if (beforeMove[j] > afterMove[i]) {
beforeMove[j]++;
}
if (afterMove[j] > afterMove[i]) {
afterMove[j]++;
}
if (afterMove[j] > beforeMove[i]) {
afterMove[j]--;
}
}
state->loadCode(state, newCode.c_str());
}

std::cout << "Code with updated assertions is:\n";
std::cout << "------------------------------------------------------------\n";
std::cout << newCode << "\n";
std::cout << "------------------------------------------------------------\n";

state->resetSimulation(state);

std::cout << "Accept? [y/n]: ";
std::string command;
std::getline(std::cin, command);

if (command == "y") {
currentCode = newCode;
} else {
state->loadCode(state, currentCode.c_str());
}
}

void CliFrontEnd::printState(SimulationState* state, size_t inspecting,
bool codeOnly) {
std::vector<size_t> highlightIntervals;
Expand Down
8 changes: 4 additions & 4 deletions test/test_assertion_creation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ TEST_F(AssertionCreationTest, CreateEntanglementAssertionFromBigAssertion) {
)");

const std::set<std::pair<size_t, std::string>> expected = {
{3, "assert-ent q[1], q[2]"},
{3, "assert-ent q[0], q[2]"},
{3, "assert-ent q[0], q[1]"}};
{3, "assert-ent q[1], q[2];\n"},
{3, "assert-ent q[0], q[2];\n"},
{3, "assert-ent q[0], q[1];\n"}};
checkNewAssertions(expected, 1);
}

Expand All @@ -81,6 +81,6 @@ TEST_F(AssertionCreationTest, CreateEntanglementAssertionFromTreeSimple) {
)");

const std::set<std::pair<size_t, std::string>> expected = {
{3, "assert-ent q[1], q[2]"}};
{3, "assert-ent q[1], q[2];\n"}};
checkNewAssertions(expected, 1);
}

0 comments on commit f5b30b0

Please sign in to comment.