Initial quantum circuit.
This commit is contained in:
parent
77ce58c612
commit
20c13c1cdf
38 changed files with 1153 additions and 14 deletions
|
@ -1,5 +1,7 @@
|
|||
#include "ComplexNumber.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
ComplexNumber::ComplexNumber(double real, double imaginary)
|
||||
: mReal(real),
|
||||
mImaginary(imaginary)
|
||||
|
@ -25,4 +27,9 @@ void ComplexNumber::setReal(double value)
|
|||
void ComplexNumber::setImaginary(double value)
|
||||
{
|
||||
mImaginary = value;
|
||||
}
|
||||
|
||||
double ComplexNumber::getMagnitude() const
|
||||
{
|
||||
return std::sqrt(mReal * mReal + mImaginary * mImaginary);
|
||||
}
|
|
@ -9,6 +9,8 @@ public:
|
|||
|
||||
double getImaginary() const;
|
||||
|
||||
double getMagnitude() const;
|
||||
|
||||
void setReal(double value);
|
||||
|
||||
void setImaginary(double value);
|
||||
|
|
0
plugins/quantum_computing/src/BasicQuantumGates.cpp
Normal file
0
plugins/quantum_computing/src/BasicQuantumGates.cpp
Normal file
21
plugins/quantum_computing/src/BasicQuantumGates.h
Normal file
21
plugins/quantum_computing/src/BasicQuantumGates.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "QuantumGate.h"
|
||||
|
||||
class XQuantumGate : public OneInOneOutQuantumGate
|
||||
{
|
||||
public:
|
||||
GateType getGateType() const override
|
||||
{
|
||||
return GateType::X;
|
||||
}
|
||||
};
|
||||
|
||||
class ZQuantumGate : public OneInOneOutQuantumGate
|
||||
{
|
||||
public:
|
||||
GateType getGateType() const override
|
||||
{
|
||||
return GateType::Z;
|
||||
}
|
||||
};
|
|
@ -1,31 +1,50 @@
|
|||
set(PLUGIN_NAME quantum_computing)
|
||||
|
||||
list(APPEND quantum_computing_HEADERS
|
||||
list(APPEND HEADERS
|
||||
QuantumCircuit.h
|
||||
BlochSphere.h
|
||||
QuantumState.h
|
||||
Qubit.h
|
||||
QuantumGate.h
|
||||
QuantumOperator.h
|
||||
QuantumCircuitReader.h
|
||||
QuantumCircuitElement.h
|
||||
QuantumWire.h
|
||||
QuantumTerminal.h
|
||||
BasicQuantumGates.h
|
||||
visuals/BlochSphereNode.h
|
||||
visuals/QuantumCircuitNode.h
|
||||
visuals/QuantumGateNode.h
|
||||
visuals/QuantumWireNode.h
|
||||
visuals/QuantumTerminalNode.h
|
||||
)
|
||||
|
||||
list(APPEND quantum_computing_LIB_INCLUDES
|
||||
list(APPEND SOURCES
|
||||
QuantumCircuit.cpp
|
||||
BlochSphere.cpp
|
||||
QuantumState.cpp
|
||||
Qubit.cpp
|
||||
QuantumGate.cpp
|
||||
QuantumOperator.cpp
|
||||
QuantumCircuitReader.cpp
|
||||
QuantumCircuitElement.cpp
|
||||
QuantumWire.cpp
|
||||
QuantumTerminal.cpp
|
||||
BasicQuantumGates.cpp
|
||||
visuals/BlochSphereNode.cpp
|
||||
visuals/QuantumCircuitNode.cpp
|
||||
visuals/QuantumGateNode.cpp
|
||||
visuals/QuantumWireNode.cpp
|
||||
visuals/QuantumTerminalNode.cpp
|
||||
visuals/BlochSphereNode.cpp
|
||||
)
|
||||
|
||||
add_library(${PLUGIN_NAME} SHARED ${quantum_computing_LIB_INCLUDES} ${quantum_computing_HEADERS})
|
||||
add_library(${PLUGIN_NAME} SHARED ${SOURCES} ${HEADERS})
|
||||
|
||||
target_include_directories(${PLUGIN_NAME} PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/visuals
|
||||
)
|
||||
target_link_libraries(${PLUGIN_NAME} PUBLIC core visual_elements ntk_math)
|
||||
target_link_libraries(${PLUGIN_NAME} PUBLIC core visual_elements ntk_math publishing)
|
||||
set_property(TARGET ${PLUGIN_NAME} PROPERTY FOLDER plugins)
|
||||
set_target_properties( ${PLUGIN_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
|
|
@ -0,0 +1,47 @@
|
|||
#include "QuantumCircuit.h"
|
||||
|
||||
#include "QuantumGate.h"
|
||||
|
||||
void QuantumCircuit::addInputTerminal(QuantumTerminalPtr terminal)
|
||||
{
|
||||
mInputTerminals.push_back(terminal.get());
|
||||
mElements.push_back(std::move(terminal));
|
||||
}
|
||||
|
||||
void QuantumCircuit::addOutputTerminal(QuantumTerminalPtr terminal)
|
||||
{
|
||||
mOutputTerminals.push_back(terminal.get());
|
||||
mElements.push_back(std::move(terminal));
|
||||
}
|
||||
|
||||
void QuantumCircuit::addQuantumWire(QuantumWirePtr wire)
|
||||
{
|
||||
mWires.push_back(wire.get());
|
||||
mElements.push_back(std::move(wire));
|
||||
}
|
||||
|
||||
void QuantumCircuit::addLogicGate(QuantumGatePtr gate)
|
||||
{
|
||||
mGates.push_back(gate.get());
|
||||
mElements.push_back(std::move(gate));
|
||||
}
|
||||
|
||||
const std::vector<QuantumTerminal*>& QuantumCircuit::getInputTerminals() const
|
||||
{
|
||||
return mInputTerminals;
|
||||
}
|
||||
|
||||
const std::vector<QuantumTerminal*>& QuantumCircuit::getOutputTerminals() const
|
||||
{
|
||||
return mOutputTerminals;
|
||||
}
|
||||
|
||||
const std::vector<QuantumGate*>& QuantumCircuit::getLogicGates() const
|
||||
{
|
||||
return mGates;
|
||||
}
|
||||
|
||||
const std::vector<QuantumWire*>& QuantumCircuit::getQuantumWires() const
|
||||
{
|
||||
return mWires;
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
|
||||
#include "QuantumCircuitElement.h"
|
||||
#include "QuantumGate.h"
|
||||
#include "QuantumTerminal.h"
|
||||
#include "QuantumWire.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class QuantumCircuit
|
||||
{
|
||||
public:
|
||||
void addInputTerminal(QuantumTerminalPtr terminal);
|
||||
|
||||
void addOutputTerminal(QuantumTerminalPtr terminal);
|
||||
|
||||
void addQuantumWire(QuantumWirePtr wire);
|
||||
|
||||
void addLogicGate(QuantumGatePtr gate);
|
||||
|
||||
const std::vector<QuantumTerminal*>& getInputTerminals() const;
|
||||
|
||||
const std::vector<QuantumTerminal*>& getOutputTerminals() const;
|
||||
|
||||
const std::vector<QuantumGate*>& getLogicGates() const;
|
||||
|
||||
const std::vector<QuantumWire*>& getQuantumWires() const;
|
||||
|
||||
private:
|
||||
std::vector<QuantumTerminal*> mInputTerminals;
|
||||
std::vector<QuantumTerminal*> mOutputTerminals;
|
||||
|
||||
std::vector<QuantumWire*> mWires;
|
||||
std::vector<QuantumGate*> mGates;
|
||||
|
||||
std::vector<std::unique_ptr<QuantumCircuitElement> > mElements;
|
||||
};
|
0
plugins/quantum_computing/src/QuantumCircuitElement.cpp
Normal file
0
plugins/quantum_computing/src/QuantumCircuitElement.cpp
Normal file
20
plugins/quantum_computing/src/QuantumCircuitElement.h
Normal file
20
plugins/quantum_computing/src/QuantumCircuitElement.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QuantumCircuitElement
|
||||
{
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
INPUT_TERMINAL,
|
||||
OUTPUT_TERMINAL,
|
||||
WIRE,
|
||||
GATE,
|
||||
UNKNOWN
|
||||
};
|
||||
|
||||
virtual ~QuantumCircuitElement() = default;
|
||||
|
||||
virtual QuantumCircuitElement::Type getType() const = 0;
|
||||
};
|
204
plugins/quantum_computing/src/QuantumCircuitReader.cpp
Normal file
204
plugins/quantum_computing/src/QuantumCircuitReader.cpp
Normal file
|
@ -0,0 +1,204 @@
|
|||
#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++;
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
40
plugins/quantum_computing/src/QuantumCircuitReader.h
Normal file
40
plugins/quantum_computing/src/QuantumCircuitReader.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
using Path = std::filesystem::path;
|
||||
|
||||
class QuantumCircuit;
|
||||
class QuantumCircuitElement;
|
||||
|
||||
class QuantumCircuitReader
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<QuantumCircuit> read(const Path& path);
|
||||
|
||||
std::unique_ptr<QuantumCircuit> read(const std::string& content);
|
||||
|
||||
private:
|
||||
using Location = std::pair<std::size_t, std::size_t>;
|
||||
|
||||
void onLine(const std::string& line, std::size_t jdx);
|
||||
|
||||
std::string checkForKet(const std::string& segment);
|
||||
|
||||
std::string checkForGate(const std::string& segment);
|
||||
|
||||
std::size_t getWireEnd(const std::string& segment);
|
||||
|
||||
void onGate(Location loc, const std::string value);
|
||||
|
||||
void onKet(Location loc, const std::string value);
|
||||
|
||||
void onLineEnd();
|
||||
|
||||
void onVertialQuantumWire(Location loc);
|
||||
|
||||
std::string mWorkingString;
|
||||
QuantumCircuitElement* mWorkingElement{ nullptr };
|
||||
QuantumCircuit* mWorkingCircuit{ nullptr };
|
||||
};
|
|
@ -0,0 +1,112 @@
|
|||
#include "QuantumGate.h"
|
||||
|
||||
NInMOutQuantumGate::NInMOutQuantumGate(std::size_t numIn, std::size_t numOut, std::vector<AbstractQuantumWire*> inputs, std::vector<AbstractQuantumWire*> outputs)
|
||||
: QuantumGate(),
|
||||
mNumIn(numIn),
|
||||
mNumOut(numOut)
|
||||
{
|
||||
if (inputs.size() == mNumIn)
|
||||
{
|
||||
mInputs = inputs;
|
||||
}
|
||||
else
|
||||
{
|
||||
mInputs = std::vector<AbstractQuantumWire*>(numIn, nullptr);
|
||||
}
|
||||
|
||||
if (outputs.size() == mNumOut)
|
||||
{
|
||||
mOutputs = outputs;
|
||||
}
|
||||
else
|
||||
{
|
||||
mOutputs = std::vector<AbstractQuantumWire*>(numOut, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t NInMOutQuantumGate::getNumInputs() const
|
||||
{
|
||||
return mNumIn;
|
||||
}
|
||||
|
||||
std::size_t NInMOutQuantumGate::getNumOutputs() const
|
||||
{
|
||||
return mNumOut;
|
||||
}
|
||||
|
||||
AbstractQuantumWire* NInMOutQuantumGate::getInput(std::size_t idx) const
|
||||
{
|
||||
if (idx < mNumIn)
|
||||
{
|
||||
return mInputs[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
AbstractQuantumWire* NInMOutQuantumGate::getOutput(std::size_t idx) const
|
||||
{
|
||||
if (idx < mNumOut)
|
||||
{
|
||||
return mOutputs[idx];
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void NInMOutQuantumGate::setAtInput(std::size_t idx, AbstractQuantumWire* value)
|
||||
{
|
||||
if (idx < mInputs.size())
|
||||
{
|
||||
mInputs[idx] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void NInMOutQuantumGate::setAtOutput(std::size_t idx, AbstractQuantumWire* value)
|
||||
{
|
||||
if (idx < mOutputs.size())
|
||||
{
|
||||
mOutputs[idx] = value;
|
||||
}
|
||||
}
|
||||
|
||||
TwoInOneOutQuantumGate::TwoInOneOutQuantumGate(AbstractQuantumWire* input0, AbstractQuantumWire* input1, AbstractQuantumWire* output)
|
||||
: NInMOutQuantumGate(2, 1, { input0, input1 }, { output })
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TwoInOneOutQuantumGate::setInput0(AbstractQuantumWire* input)
|
||||
{
|
||||
setAtInput(0, input);
|
||||
}
|
||||
|
||||
void TwoInOneOutQuantumGate::setInput1(AbstractQuantumWire* input)
|
||||
{
|
||||
setAtInput(1, input);
|
||||
}
|
||||
|
||||
void TwoInOneOutQuantumGate::setOutput(AbstractQuantumWire* output)
|
||||
{
|
||||
setAtOutput(0, output);
|
||||
}
|
||||
|
||||
OneInOneOutQuantumGate::OneInOneOutQuantumGate(AbstractQuantumWire* input, AbstractQuantumWire* output)
|
||||
: NInMOutQuantumGate(1, 1, { input }, { output })
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OneInOneOutQuantumGate::setInput(AbstractQuantumWire* input)
|
||||
{
|
||||
setAtInput(0, input);
|
||||
}
|
||||
|
||||
void OneInOneOutQuantumGate::setOutput(AbstractQuantumWire* output)
|
||||
{
|
||||
setAtOutput(0, output);
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
#include "QuantumCircuitElement.h"
|
||||
|
||||
#include "QuantumWire.h"
|
||||
#include <vector>
|
||||
|
||||
class QuantumGate : public QuantumCircuitElement
|
||||
{
|
||||
public:
|
||||
enum class GateType
|
||||
{
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
H,
|
||||
CNOT,
|
||||
CUSTOM
|
||||
};
|
||||
virtual ~QuantumGate() = default;
|
||||
|
||||
virtual std::size_t getNumInputs() const = 0;
|
||||
|
||||
virtual std::size_t getNumOutputs() const = 0;
|
||||
|
||||
virtual AbstractQuantumWire* getInput(std::size_t idx) const = 0;
|
||||
|
||||
virtual AbstractQuantumWire* getOutput(std::size_t idx) const = 0;
|
||||
|
||||
virtual GateType getGateType() const = 0;
|
||||
|
||||
Type getType() const override
|
||||
{
|
||||
return Type::GATE;
|
||||
}
|
||||
};
|
||||
using QuantumGatePtr = std::unique_ptr<QuantumGate>;
|
||||
|
||||
|
||||
class NInMOutQuantumGate : public QuantumGate
|
||||
{
|
||||
public:
|
||||
NInMOutQuantumGate(std::size_t numIn, std::size_t numOut, std::vector<AbstractQuantumWire*> inputs = {}, std::vector<AbstractQuantumWire*> outputs = {});
|
||||
|
||||
virtual ~NInMOutQuantumGate() = default;
|
||||
|
||||
std::size_t getNumInputs() const override;
|
||||
|
||||
std::size_t getNumOutputs() const override;
|
||||
|
||||
AbstractQuantumWire* getInput(std::size_t idx) const override;
|
||||
|
||||
AbstractQuantumWire* getOutput(std::size_t idx) const override;
|
||||
|
||||
void setAtInput(std::size_t idx, AbstractQuantumWire* value);
|
||||
|
||||
void setAtOutput(std::size_t idx, AbstractQuantumWire* value);
|
||||
|
||||
private:
|
||||
std::size_t mNumIn{ 1 };
|
||||
std::size_t mNumOut{ 1 };
|
||||
|
||||
std::vector<AbstractQuantumWire*> mInputs;
|
||||
std::vector<AbstractQuantumWire*> mOutputs;
|
||||
};
|
||||
|
||||
class TwoInOneOutQuantumGate : public NInMOutQuantumGate
|
||||
{
|
||||
public:
|
||||
TwoInOneOutQuantumGate(AbstractQuantumWire* input0 = nullptr, AbstractQuantumWire* input1 = nullptr, AbstractQuantumWire* output = nullptr);
|
||||
|
||||
void setInput0(AbstractQuantumWire* input);
|
||||
|
||||
void setInput1(AbstractQuantumWire* input);
|
||||
|
||||
void setOutput(AbstractQuantumWire* output);
|
||||
};
|
||||
|
||||
class OneInOneOutQuantumGate : public NInMOutQuantumGate
|
||||
{
|
||||
public:
|
||||
OneInOneOutQuantumGate(AbstractQuantumWire* input = nullptr, AbstractQuantumWire* output = nullptr);
|
||||
|
||||
void setInput(AbstractQuantumWire* input);
|
||||
|
||||
void setOutput(AbstractQuantumWire* output);
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
#include "QuantumState.h"
|
||||
|
||||
const std::vector<Qubit>& QuantumState::getData() const
|
||||
{
|
||||
return mState;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "Qubit.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
class QuantumState
|
||||
{
|
||||
const std::vector<Qubit>& getData() const;
|
||||
|
||||
private:
|
||||
std::vector<Qubit> mState;
|
||||
};
|
33
plugins/quantum_computing/src/QuantumTerminal.cpp
Normal file
33
plugins/quantum_computing/src/QuantumTerminal.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "QuantumTerminal.h"
|
||||
|
||||
QuantumTerminal::QuantumTerminal(TerminalType type, const std::string& label)
|
||||
: mLabel(label),
|
||||
mType(type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QuantumTerminal::Type QuantumTerminal::getType() const
|
||||
{
|
||||
return mType == TerminalType::INPUT ? Type::INPUT_TERMINAL : Type::OUTPUT_TERMINAL;
|
||||
}
|
||||
|
||||
const Qubit& QuantumTerminal::getValue() const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
QuantumWire* QuantumTerminal::getConnection() const
|
||||
{
|
||||
return mConnection;
|
||||
}
|
||||
|
||||
void QuantumTerminal::setConnection(QuantumWire* connection)
|
||||
{
|
||||
mConnection = connection;
|
||||
}
|
||||
|
||||
void QuantumTerminal::setValue(const Qubit& value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
38
plugins/quantum_computing/src/QuantumTerminal.h
Normal file
38
plugins/quantum_computing/src/QuantumTerminal.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include "QuantumCircuitElement.h"
|
||||
#include "Qubit.h"
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
class QuantumWire;
|
||||
|
||||
class QuantumTerminal : public QuantumCircuitElement
|
||||
{
|
||||
public:
|
||||
enum class TerminalType
|
||||
{
|
||||
INPUT,
|
||||
OUTPUT
|
||||
};
|
||||
|
||||
QuantumTerminal(TerminalType type, const std::string& label = {});
|
||||
|
||||
QuantumWire* getConnection() const;
|
||||
|
||||
Type getType() const override;
|
||||
|
||||
const Qubit& getValue() const;
|
||||
|
||||
void setConnection(QuantumWire* connection);
|
||||
|
||||
void setValue(const Qubit& value);
|
||||
|
||||
private:
|
||||
std::string mLabel;
|
||||
TerminalType mType;
|
||||
Qubit mValue;
|
||||
QuantumWire* mConnection{ nullptr };
|
||||
};
|
||||
using QuantumTerminalPtr = std::unique_ptr<QuantumTerminal>;
|
28
plugins/quantum_computing/src/QuantumWire.cpp
Normal file
28
plugins/quantum_computing/src/QuantumWire.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "QuantumWire.h"
|
||||
|
||||
QuantumWire::QuantumWire(QuantumCircuitElement* input, QuantumCircuitElement* output)
|
||||
: mInput(input),
|
||||
mOutput(output)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QuantumCircuitElement* QuantumWire::getInput() const
|
||||
{
|
||||
return mInput;
|
||||
}
|
||||
|
||||
QuantumCircuitElement* QuantumWire::getOutput() const
|
||||
{
|
||||
return mOutput;
|
||||
}
|
||||
|
||||
QuantumWire::Type QuantumWire::getType() const
|
||||
{
|
||||
return Type::WIRE;
|
||||
}
|
||||
|
||||
QuantumWire::WireType QuantumWire::getWireType() const
|
||||
{
|
||||
return WireType::QUANTUM;
|
||||
}
|
42
plugins/quantum_computing/src/QuantumWire.h
Normal file
42
plugins/quantum_computing/src/QuantumWire.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
#pragma once
|
||||
|
||||
#include "QuantumCircuitElement.h"
|
||||
|
||||
class AbstractQuantumWire : public QuantumCircuitElement
|
||||
{
|
||||
public:
|
||||
enum class WireType
|
||||
{
|
||||
QUANTUM,
|
||||
CLASSICAL
|
||||
};
|
||||
|
||||
virtual ~AbstractQuantumWire() = default;
|
||||
|
||||
virtual WireType getWireType() const = 0;
|
||||
};
|
||||
|
||||
class QuantumWire : public AbstractQuantumWire
|
||||
{
|
||||
public:
|
||||
QuantumWire(QuantumCircuitElement* input, QuantumCircuitElement* output);
|
||||
|
||||
QuantumCircuitElement* getInput() const;
|
||||
QuantumCircuitElement* getOutput() const;
|
||||
|
||||
Type getType() const override;
|
||||
WireType getWireType() const override;
|
||||
private:
|
||||
QuantumCircuitElement* mInput{ nullptr };
|
||||
QuantumCircuitElement* mOutput{ nullptr };
|
||||
};
|
||||
using QuantumWirePtr = std::unique_ptr<QuantumWire>;
|
||||
|
||||
class ClassicalWire : public AbstractQuantumWire
|
||||
{
|
||||
public:
|
||||
WireType getWireType() const override
|
||||
{
|
||||
return WireType::CLASSICAL;
|
||||
}
|
||||
};
|
|
@ -15,4 +15,14 @@ const ComplexNumber& Qubit::getAlpha() const
|
|||
const ComplexNumber& Qubit::getBeta() const
|
||||
{
|
||||
return mBeta;
|
||||
}
|
||||
|
||||
bool Qubit::isIn0State() const
|
||||
{
|
||||
return mAlpha.getReal() == 1.0 && mBeta.getMagnitude() == 0.0;
|
||||
}
|
||||
|
||||
bool Qubit::isIn1State() const
|
||||
{
|
||||
return mBeta.getReal() == 1.0 && mAlpha.getMagnitude() == 0.0;
|
||||
}
|
|
@ -5,11 +5,15 @@
|
|||
class Qubit
|
||||
{
|
||||
public:
|
||||
Qubit(const ComplexNumber& alpha, const ComplexNumber& beta);
|
||||
Qubit(const ComplexNumber& alpha = {1.0, 0.0}, const ComplexNumber& beta = { 0.0, 0.0 });
|
||||
|
||||
const ComplexNumber& getAlpha() const;
|
||||
|
||||
const ComplexNumber& getBeta() const;
|
||||
|
||||
bool isIn0State() const;
|
||||
|
||||
bool isIn1State() const;
|
||||
private:
|
||||
ComplexNumber mAlpha;
|
||||
ComplexNumber mBeta;
|
||||
|
|
44
plugins/quantum_computing/src/visuals/QuantumCircuitNode.cpp
Normal file
44
plugins/quantum_computing/src/visuals/QuantumCircuitNode.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "QuantumCircuitNode.h"
|
||||
|
||||
#include "QuantumCircuit.h"
|
||||
#include "QuantumTerminalNode.h"
|
||||
|
||||
QuantumCircuitNode::QuantumCircuitNode(const Transform& t)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QuantumCircuitNode::setContent(QuantumCircuit* circuit)
|
||||
{
|
||||
mContent = circuit;
|
||||
mContentDirty = true;
|
||||
}
|
||||
|
||||
void QuantumCircuitNode::update(SceneInfo* sceneInfo)
|
||||
{
|
||||
if (mContentDirty)
|
||||
{
|
||||
createOrUpdateGeometry(sceneInfo);
|
||||
mContentDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void QuantumCircuitNode::createOrUpdateGeometry(SceneInfo*)
|
||||
{
|
||||
double terminal_vertical_spacing = 100;
|
||||
double terminal_left_margin = 10;
|
||||
|
||||
double terminal_y = 10;
|
||||
for (auto terminal : mContent->getInputTerminals())
|
||||
{
|
||||
Point loc{ terminal_left_margin, terminal_y };
|
||||
auto terminal_node = std::make_unique<QuantumTerminalNode>(Transform(loc));
|
||||
|
||||
terminal_node->setContent(terminal);
|
||||
|
||||
addChild(terminal_node.get());
|
||||
|
||||
mInputTerminalNodes.push_back(std::move(terminal_node));
|
||||
terminal_y += terminal_vertical_spacing;
|
||||
}
|
||||
}
|
23
plugins/quantum_computing/src/visuals/QuantumCircuitNode.h
Normal file
23
plugins/quantum_computing/src/visuals/QuantumCircuitNode.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "AbstractVisualNode.h"
|
||||
|
||||
class QuantumCircuit;
|
||||
class QuantumTerminalNode;
|
||||
|
||||
class QuantumCircuitNode : public AbstractVisualNode
|
||||
{
|
||||
public:
|
||||
QuantumCircuitNode(const Transform& t = {});
|
||||
|
||||
void setContent(QuantumCircuit* circuit);
|
||||
|
||||
void update(SceneInfo* sceneInfo);
|
||||
private:
|
||||
void createOrUpdateGeometry(SceneInfo* sceneInfo);
|
||||
|
||||
bool mContentDirty{ true };
|
||||
QuantumCircuit* mContent{ nullptr };
|
||||
|
||||
std::vector<std::unique_ptr<QuantumTerminalNode> > mInputTerminalNodes;
|
||||
};
|
0
plugins/quantum_computing/src/visuals/QuantumGateNode.h
Normal file
0
plugins/quantum_computing/src/visuals/QuantumGateNode.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include "QuantumTerminalNode.h"
|
||||
|
||||
#include "QuantumTerminal.h"
|
||||
#include "EquationNode.h"
|
||||
#include "LatexMathExpression.h"
|
||||
|
||||
QuantumTerminalNode::QuantumTerminalNode(const Transform& transform)
|
||||
: AbstractVisualNode(transform)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void QuantumTerminalNode::setContent(QuantumTerminal* terminal)
|
||||
{
|
||||
mContent = terminal;
|
||||
mContentDirty = true;
|
||||
}
|
||||
|
||||
void QuantumTerminalNode::update(SceneInfo* sceneInfo)
|
||||
{
|
||||
if (mContentDirty)
|
||||
{
|
||||
createOrUpdateGeometry(sceneInfo);
|
||||
mContentDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
void QuantumTerminalNode::createOrUpdateGeometry(SceneInfo* sceneInfo)
|
||||
{
|
||||
if (!mLabel)
|
||||
{
|
||||
const auto value = mContent->getValue();
|
||||
std::string label;
|
||||
if (value.isIn0State())
|
||||
{
|
||||
label = "\\ket{0}";
|
||||
}
|
||||
else if(value.isIn1State())
|
||||
{
|
||||
label = "\\ket{1}";
|
||||
}
|
||||
else
|
||||
{
|
||||
label = "\\Psi";
|
||||
}
|
||||
|
||||
mLabelExpression = std::make_unique<LatexMathExpression>(label);
|
||||
mLabel = std::make_unique<EquationNode>();
|
||||
mLabel->setContent(mLabelExpression.get());
|
||||
|
||||
addChild(mLabel.get());
|
||||
}
|
||||
}
|
25
plugins/quantum_computing/src/visuals/QuantumTerminalNode.h
Normal file
25
plugins/quantum_computing/src/visuals/QuantumTerminalNode.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "AbstractVisualNode.h"
|
||||
|
||||
class QuantumTerminal;
|
||||
class EquationNode;
|
||||
class LatexMathExpression;
|
||||
|
||||
class QuantumTerminalNode : public AbstractVisualNode
|
||||
{
|
||||
public:
|
||||
QuantumTerminalNode(const Transform& transform);
|
||||
|
||||
void setContent(QuantumTerminal* terminal);
|
||||
|
||||
void update(SceneInfo* sceneInfo);
|
||||
private:
|
||||
void createOrUpdateGeometry(SceneInfo* sceneInfo);
|
||||
|
||||
QuantumTerminal* mContent{ nullptr };
|
||||
bool mContentDirty{ true };
|
||||
|
||||
std::unique_ptr<LatexMathExpression> mLabelExpression;
|
||||
std::unique_ptr<EquationNode> mLabel;
|
||||
};
|
0
plugins/quantum_computing/src/visuals/QuantumWireNode.h
Normal file
0
plugins/quantum_computing/src/visuals/QuantumWireNode.h
Normal file
|
@ -1,6 +1,7 @@
|
|||
|
||||
list(APPEND UNIT_TEST_FILES
|
||||
TestBlochSphereNode.cpp
|
||||
TestQuantumCircuitParsing.cpp
|
||||
)
|
||||
|
||||
add_executable(quantum_computing_unit_tests ${CMAKE_SOURCE_DIR}/test/test_runner.cpp ${UNIT_TEST_FILES})
|
||||
|
|
24
plugins/quantum_computing/test/TestQuantumCircuitParsing.cpp
Normal file
24
plugins/quantum_computing/test/TestQuantumCircuitParsing.cpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include "TestFramework.h"
|
||||
#include "TestUtils.h"
|
||||
#include "TestRenderUtils.h"
|
||||
|
||||
#include "QuantumCircuitReader.h"
|
||||
#include "QuantumCircuitNode.h"
|
||||
#include "QuantumCircuit.h"
|
||||
|
||||
|
||||
TEST_CASE(TestQuantumCircuitParsing, "quantum_computing")
|
||||
{
|
||||
QuantumCircuitReader reader;
|
||||
|
||||
auto circuit = reader.read(TestUtils::getTestDataDir() / "quantum_circuit.dat");
|
||||
|
||||
TestRenderer renderer(100, 100);
|
||||
|
||||
auto node = std::make_unique<QuantumCircuitNode>(Point(10, 10));
|
||||
|
||||
node->setContent(circuit.get());
|
||||
|
||||
renderer.getScene()->addNode(node.get());
|
||||
renderer.writeSvg(TestUtils::getTestOutputDir(__FILE__) / "circuit.svg");
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue