205 lines
No EOL
3.9 KiB
C++
205 lines
No EOL
3.9 KiB
C++
#include "QuantumCircuitReader.h"
|
|
|
|
#include "QuantumCircuit.h"
|
|
#include "Qubit.h"
|
|
#include "QuantumTerminal.h"
|
|
#include "BasicQuantumGates.h"
|
|
#include "QuantumWire.h"
|
|
|
|
#include "File.h"
|
|
#include "StringUtils.h"
|
|
#include "FileLogger.h"
|
|
|
|
std::unique_ptr<QuantumCircuit> QuantumCircuitReader::read(const Path& path)
|
|
{
|
|
File file(path);
|
|
return read(file.readText());
|
|
}
|
|
|
|
std::unique_ptr<QuantumCircuit> QuantumCircuitReader::read(const std::string& content)
|
|
{
|
|
auto circuit = std::make_unique<QuantumCircuit>();
|
|
mWorkingCircuit = circuit.get();
|
|
|
|
std::size_t cursor = 0;
|
|
for (const auto& line : StringUtils::toLines(content))
|
|
{
|
|
onLine(line, cursor);
|
|
cursor++;
|
|
}
|
|
circuit->buildWireConnections();
|
|
return circuit;
|
|
}
|
|
|
|
void QuantumCircuitReader::onLine(const std::string& line, std::size_t jdx)
|
|
{
|
|
mWorkingString.clear();
|
|
std::size_t cursor = 0;
|
|
|
|
while (cursor < line.size())
|
|
{
|
|
const auto c = line[cursor];
|
|
MLOG_INFO("Working char: " << std::string(1, c));
|
|
|
|
if (c == '|')
|
|
{
|
|
if (cursor + 1 < line.size())
|
|
{
|
|
if (line[cursor + 1] == '-')
|
|
{
|
|
onVertialQuantumWire({ cursor, jdx });
|
|
}
|
|
else if (auto ket = checkForKet(line.substr(cursor + 1, line.size() - cursor)); !ket.empty())
|
|
{
|
|
onKet({ cursor, jdx }, ket);
|
|
cursor += ket.size() + 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mWorkingString += c;
|
|
}
|
|
}
|
|
else if (c == '-')
|
|
{
|
|
if (cursor + 1 < line.size())
|
|
{
|
|
const auto end_id = getWireEnd(line.substr(cursor, line.size() - cursor));
|
|
MLOG_INFO("Wire: " << cursor << " with length " << end_id);
|
|
cursor += end_id - 1;
|
|
}
|
|
else
|
|
{
|
|
mWorkingString += c;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (cursor + 1 < line.size())
|
|
{
|
|
auto gate = checkForGate(line.substr(cursor, line.size() - cursor));
|
|
onGate({ cursor, jdx }, gate);
|
|
cursor += gate.size() - 1;
|
|
}
|
|
else
|
|
{
|
|
mWorkingString += c;
|
|
}
|
|
}
|
|
cursor++;
|
|
}
|
|
onLineEnd();
|
|
}
|
|
|
|
void QuantumCircuitReader::onLineEnd()
|
|
{
|
|
auto output_terminal = std::make_unique<QuantumTerminal>(QuantumTerminal::TerminalType::OUTPUT);
|
|
|
|
auto wire = std::make_unique<QuantumWire>(mWorkingElement, output_terminal.get());
|
|
mWorkingCircuit->addQuantumWire(std::move(wire));
|
|
|
|
mWorkingCircuit->addOutputTerminal(std::move(output_terminal));
|
|
|
|
mWorkingElement = nullptr;
|
|
}
|
|
|
|
void QuantumCircuitReader::onGate(Location loc, const std::string value)
|
|
{
|
|
MLOG_INFO("Got gate: " << value);
|
|
|
|
QuantumGatePtr gate;
|
|
|
|
if (value == "X")
|
|
{
|
|
gate = std::make_unique<XQuantumGate>();
|
|
}
|
|
else if (value == "Z")
|
|
{
|
|
gate = std::make_unique<ZQuantumGate>();
|
|
}
|
|
|
|
if (gate)
|
|
{
|
|
auto wire = std::make_unique<QuantumWire>(mWorkingElement, gate.get());
|
|
mWorkingCircuit->addQuantumWire(std::move(wire));
|
|
|
|
mWorkingElement = gate.get();
|
|
mWorkingCircuit->addLogicGate(std::move(gate));
|
|
}
|
|
}
|
|
|
|
std::string QuantumCircuitReader::checkForGate(const std::string& segment)
|
|
{
|
|
std::string working_string;
|
|
for (const auto c : segment)
|
|
{
|
|
if (c == '-')
|
|
{
|
|
break;
|
|
}
|
|
working_string += c;
|
|
}
|
|
return working_string;
|
|
}
|
|
|
|
void QuantumCircuitReader::onKet(Location loc, const std::string value)
|
|
{
|
|
MLOG_INFO("Got input state: " << value);
|
|
Qubit qubit;
|
|
if (value == "1")
|
|
{
|
|
qubit = Qubit({ 0.0, 0.0 }, { 1.0, 0.0 });
|
|
}
|
|
|
|
auto input_terminal = std::make_unique<QuantumTerminal>(QuantumTerminal::TerminalType::INPUT);
|
|
|
|
mWorkingElement = input_terminal.get();
|
|
mWorkingCircuit->addInputTerminal(std::move(input_terminal));
|
|
}
|
|
|
|
std::size_t QuantumCircuitReader::getWireEnd(const std::string& segment)
|
|
{
|
|
std::size_t idx = 0;
|
|
for (const auto c : segment)
|
|
{
|
|
if (c != '-')
|
|
{
|
|
break;
|
|
}
|
|
idx++;
|
|
}
|
|
return idx;
|
|
}
|
|
|
|
std::string QuantumCircuitReader::checkForKet(const std::string& segment)
|
|
{
|
|
std::string working_string;
|
|
bool found{ false };
|
|
|
|
for (const auto c : segment)
|
|
{
|
|
if (c == '>')
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
working_string += c;
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
{
|
|
return working_string;
|
|
}
|
|
else
|
|
{
|
|
return {};
|
|
}
|
|
}
|
|
|
|
void QuantumCircuitReader::onVertialQuantumWire(Location loc)
|
|
{
|
|
|
|
} |