Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "deps/libqasm"]
path = deps/libqasm
url = https://github.com/QE-Lab/libqasm.git
30 changes: 24 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,19 @@ TWOQGATETIMES = $(BENCHMARKS_DIR)twoQGateTimes
THREEQGATETIMES = $(BENCHMARKS_DIR)threeQGateTimes
EPR = $(BENCHMARKS_DIR)epr

# cQASM Interface $(LIBQASM_INCL:%=-I%)
INTERFACE_DEPS = $(SRC_DIR)qInterface.hpp
RQXINTERFACE_DEPS = $(SRC_DIR)rQXInterface.hpp
INTERFACE = $(SRC_DIR)qInterface
RQXINTERFACE = $(SRC_DIR)rQXInterface
LIBQASM_INCL = deps/libqasm/src/cqasm/include deps/libqasm/src/cqasm/tree-gen/include deps/libqasm/pybuild/cbuild/src/cqasm/include deps/libqasm/pybuild/cbuild/src/cqasm/tree-gen deps/libqasm/pybuild/cbuild/src/cqasm/func-gen


# list of object files
objectFiles = $(TARGET).o $(QUBITLAYER).o $(EXAMPLES).o $(SINGLEQGATETIMES).o $(TWOQGATETIMES).o $(THREEQGATETIMES).o $(EPR).o $(TESTS).o
objectFiles = $(TARGET).o $(QUBITLAYER).o $(EXAMPLES).o $(SINGLEQGATETIMES).o $(TWOQGATETIMES).o $(THREEQGATETIMES).o $(EPR).o $(TESTS).o $(RQXINTERFACE).o

#list of executables
executables = $(TARGET) $(SINGLEQGATETIMES) $(TWOQGATETIMES) $(THREEQGATETIMES) $(EPR) $(TESTS)
executables = $(TARGET) $(SINGLEQGATETIMES) $(TWOQGATETIMES) $(THREEQGATETIMES) $(EPR) $(TESTS)

# debug directory
DEBUG = main.dSYM
Expand All @@ -62,13 +70,13 @@ BENCHMARKS_STRING = "Running\ benchmarks..."

all: $(TARGET)

$(TARGET): $(TARGET).o $(QUBITLAYER).o $(EXAMPLES).o
@printf "%b" "$(CYAN)$(LINK_STRING) $(NO_COLOR)$(TARGET).o $(QUBITLAYER).o $(EXAMPLES).o "
@$(CXX) $(CXXFLAGS) -o $(TARGET) $(TARGET).o $(QUBITLAYER).o $(EXAMPLES).o
$(TARGET): $(TARGET).o $(QUBITLAYER).o $(EXAMPLES).o $(INTERFACE).o $(RQXINTERFACE).o deps/libqasm/lib/libcqasm.so deps/libqasm/lib/libtree-lib.so
@printf "%b" "$(CYAN)$(LINK_STRING) $(NO_COLOR)$(TARGET).o $(QUBITLAYER).o $(EXAMPLES).o $(RQXINTERFACE).o \n"
@$(CXX) $(CXXFLAGS) -o $(TARGET) $(TARGET).o $(QUBITLAYER).o $(EXAMPLES).o $(RQXINTERFACE).o $(INTERFACE).o deps/libqasm/lib/libcqasm.so deps/libqasm/lib/libtree-lib.so
@printf "%b" "$(GREEN)$(OK_STRING)\n"
@printf "%b" "$(GREEN)$(SUCCESS_STRING)$(NO_COLOR)\n";

$(TARGET).o: $(TARGET).cpp $(TARGET_DEPS) $(QLAYER_DEPS)
$(TARGET).o: $(TARGET).cpp $(TARGET_DEPS) $(QLAYER_DEPS) $(RQXINTERFACE_DEPS) $(INTERFACE_DEPS)
@printf "%b" "$(BLUE)$(COM_STRING) $(NO_COLOR)$(@) "
@$(CXX) $(CXXFLAGS) -c $(TARGET).cpp -o $(TARGET).o
@printf "%b" "$(GREEN)$(OK_STRING)\n"
Expand All @@ -83,6 +91,16 @@ $(EXAMPLES).o: $(EXAMPLES).cpp $(TARGET_DEPS) $(QLAYER_DEPS) $(EXAMPLES_DEPS)
@$(CXX) $(CXXFLAGS) -c $(EXAMPLES).cpp -o $(EXAMPLES).o
@printf "%b" "$(GREEN)$(OK_STRING)\n"

$(INTERFACE).o: $(INTERFACE).cpp $(TARGET_DEPS) $(QLAYER_DEPS) $(RQXINTERFACE_DEPS) $(INTERFACE_DEPS)
@printf "%b" "$(BLUE)$(COM_STRING) $(NO_COLOR)$(@) "
@$(CXX) $(CXXFLAGS) -o $(INTERFACE).o -c $(INTERFACE).cpp
@printf "%b" "$(GREEN)$(OK_STRING)\n"

$(RQXINTERFACE).o: $(RQXINTERFACE).cpp $(TARGET_DEPS) $(QLAYER_DEPS) $(RQXINTERFACE_DEPS) $(INTERFACE_DEPS)
@printf "%b" "$(BLUE)$(COM_STRING) $(NO_COLOR)$(@) "
@$(CXX) $(CXXFLAGS) -lcqasm -o $(RQXINTERFACE).o -c $(RQXINTERFACE).cpp
@printf "%b" "$(GREEN)$(OK_STRING)\n"

benchmark:
@make singleQBenchmark
@make twoQBenchmark
Expand Down
1 change: 1 addition & 0 deletions deps/libqasm
Submodule libqasm added at 95d346
99 changes: 97 additions & 2 deletions src/QubitLayer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <complex>
#include <iostream>
#include <cmath>
#include <random>
#include "QubitLayer.hpp"

QubitLayer::QubitLayer(unsigned int numQubits, qubitLayer *qL){
Expand All @@ -12,11 +13,13 @@ QubitLayer::QubitLayer(unsigned int numQubits, qubitLayer *qL){
qEven_ = new qubitLayer[numStates];
qOdd_ = new qubitLayer[numStates];
// if input is provided then use that to fill the input qubit state
if (!(qL == nullptr))
if (!(qL == nullptr)){
for (int row = 0; row < numStates; row++)
qEven_[row] = qL[row];
else
}
else{
qEven_[0] = {1,0};
}
}

QubitLayer::~QubitLayer(){
Expand Down Expand Up @@ -212,6 +215,98 @@ void QubitLayer::mcphase(int *controls, int numControls, int target){
updateLayer();
}

// void QubitLayer::prepz(int* target, int numTargets){
// // Set probability of target bit being |0> to 1 and of being |1> to 0
// for (int i = 0; i < numTargets; i++)
// {
// parity ? qOdd_[target[i]] = -qEven_[i] : qEven_[target[i]] = -qOdd_[i];

// }
// updateLayer();
// }


void QubitLayer::measure(int target){
// Calculate total probability of a bit being zero or one, when measured

// Generate random measurement result

// Set probability of all states with bit in other state to 0

// Add probability of all states with the bit in other state to the probability of the bit in the measurement sate

// |00> 0.3
// |01> 0.2
// |10> 0.4
// |11> 0.1
// measure 1st bit
// prob zero: 0.5
// prob one: 0.5
// -> set 1
// |10> 0.7
// |11> 0.3
std::cout << "Measure bit " << target << std::endl;
precision probZero{0};
precision probOne{0};
for (unsigned long long int i = 0; i < numStates; i++)
{
if (checkZeroState(i))
{
std::bitset<maxQubits> state = i;
if (state.test(target))
{
probOne += parity ? abs(qEven_[i]) * abs(qEven_[i]) : abs(qOdd_[i]) * abs(qOdd_[i]);
}
else
{
probZero += parity ? abs(qEven_[i]) * abs(qEven_[i]) : abs(qOdd_[i]) * abs(qOdd_[i]);
}
}
}
std::cout << "probOne: " << probOne << ", probZero: " << probZero << std::endl;
bool result = random_number_gen(probOne);
std::cout << "Measurement result of qubit " << target << " is " << result << std::endl;

for (unsigned long long int i = 0; i < numStates; i++)
{
if (checkZeroState(i))
{
std::bitset<maxQubits> state = i;
// If state i contains the bit in the measured state, normalize the probability
if (state.test(target) == result)
{
state.flip(target); // Get the corresponding state where the measured bit has the opposite value
double probNormal = parity ? std::sqrt(abs(qEven_[i]) * abs(qEven_[i]) + abs(qEven_[state.to_ulong()]) * abs(qEven_[state.to_ulong()])) : \
std::sqrt(abs(qOdd_[i]) * abs(qOdd_[i]) + abs(qOdd_[state.to_ulong()]) * abs(qOdd_[state.to_ulong()]));
// std::cout << "Total probability will be " << probNormal << std::endl;
// std::cout << "parity ? qEven_[i] : qOdd_[i] " << (parity ? qEven_[i] : qOdd_[i]) << std::endl;
parity ? qOdd_[i] = (qEven_[i])*probNormal/std::sqrt(abs(qEven_[i]) * abs(qEven_[i])) : qEven_[i] = (qOdd_[i])*probNormal/std::sqrt(abs(qOdd_[i]) * abs(qOdd_[i]));

std::cout << "State " << state.flip(target) << " will have prob " << (parity ? abs(qOdd_[i]) * abs(qOdd_[i]) : abs(qEven_[i]) * abs(qEven_[i]) ) << std::endl;
}
// Else the probabilty of this state is zero
else
{
std::cout << "State " << state << " will have prob 0" << std::endl;
parity ? qOdd_[i] = 0 : qEven_[i] = 0;
}
}
}

updateLayer();
}

// Returns a 1 with the probability dof threshold
int QubitLayer::random_number_gen(double threshold)
{
std::random_device rd;
std::uniform_real_distribution<double> distribution(0.0f, 1.0f);
std::mt19937 engine(rd());
double value = distribution(engine);
std::cout << "[Random number generation] value: " << value << " threshold: " << threshold << std::endl;
return (value < threshold) ? 1 : 0;
}

qProb QubitLayer::getMaxAmplitude(){
std::bitset<maxQubits> state;
qProb result;
Expand Down
6 changes: 5 additions & 1 deletion src/QubitLayer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ class QubitLayer{
void mcnot(int *controls, int numControls, int target);
void cphase(int control, int target);
void mcphase(int *controls, int numControls, int target);
// void prepz(int *targets, int numTargets);
void measure(int target);
int random_number_gen(double threshold);
qProb getMaxAmplitude();
void printMeasurement();
void printQubits();
Expand All @@ -43,4 +46,5 @@ class QubitLayer{
bool parity = true;
};

#endif
#endif

20 changes: 13 additions & 7 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@
#include <complex>
#include <chrono>
#include "QubitLayer.hpp"
#include "../examples/qAlgorithms.hpp"

#include "rQXInterface.hpp"
#include "../examples/qAlgorithms.hpp"
int main(){
auto start = std::chrono::steady_clock::now();
QubitLayer q = grover(2, 0);
auto stop = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count();
std::cout << "Execution time: " << duration << " µs" << std::endl;
q.printMeasurement();
// auto start = std::chrono::steady_clock::now();
// QubitLayer q = grover(2, 0);
// auto stop = std::chrono::steady_clock::now();
// auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start).count();
// std::cout << "Execution time: " << duration << " µs" << std::endl;
// q.printMeasurement();
rQXInterface interface;
interface.set_qasm("tests/bell.qasm");
interface.execute();


}
7 changes: 7 additions & 0 deletions src/qInterface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "qInterface.hpp"

// qInterface::qInterface(){
// };

qInterface::~qInterface(){
};
17 changes: 17 additions & 0 deletions src/qInterface.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#ifndef INTERFACE_H
#define INTERFACE_H
#include <complex>

class qInterface{
public:
virtual int execute() = 0;
virtual int set_state(int* state_vec) = 0;
virtual int add_circuit() = 0;
virtual int* get_state() = 0;
virtual int set_qasm(std::string path) = 0;
virtual ~qInterface();
// qInterface();

};

#endif
128 changes: 128 additions & 0 deletions src/rQXInterface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include <complex>
#include "rQXInterface.hpp"
#include "QubitLayer.hpp"
#include <cqasm.hpp>

rQXInterface::rQXInterface(){

};

// Calls individual gates and keeps track of qubit state and measurement results etc.
int rQXInterface::execute()
{
QubitLayer q(_numQubits);
// DEBUG
// std::cout << "printQubits in execute()" << std::endl;
// q.printQubits();
for (auto subcircuit : _program->subcircuits)
{
// subcircuit name
// subcircuit iterations
std::cout << subcircuit->name << "\n";

execute_circuit(subcircuit, q);
}

q.printMeasurement();

return 0;
};

int rQXInterface::set_state(int *state_vec)
{
return 0;
};
int rQXInterface::add_circuit()
{
return 0;
};

int rQXInterface::execute_circuit(tree::base::One<cqasm::semantic::Subcircuit> circuit, QubitLayer qubitLayer)
{
// DEBUG
// std::cout << "printQubits in execute_circuit()" << std::endl;
// qubitLayer.printQubits();
for (auto line : circuit->bundles)
{
// operation size: parallel or single
// operation name
// operation parameters: qubits (as_qubit_refs(), size,

if (line.size() == 1) // a single operation
{
auto operation = line->items[0];
std::string name = operation->name;
std::cout << "gate: " << name << "\n";
// std::cout << "operands: " << operation->operands << "\n";

// auto parameter_0 = operation->operands[0]->as_qubit_refs();
// // auto parameter_0 = operation->operands[0];
// std::cout << "parameter_0: " << parameter_0->index[0]->value << "\n";

if (name == "hadamard" || name == "h")
{
auto parameter_0 = operation->operands[0]->as_qubit_refs();
qubitLayer.hadamard(parameter_0->index[0]->value);
} else if (name == "identity" || name == "i")
{

} else if (name == "x"){
auto parameter_0 = operation->operands[0]->as_qubit_refs();
qubitLayer.pauliX(parameter_0->index[0]->value);
} else if (name == "y"){
auto parameter_0 = operation->operands[0]->as_qubit_refs();
qubitLayer.pauliY(parameter_0->index[0]->value);
} else if (name == "z"){
auto parameter_0 = operation->operands[0]->as_qubit_refs();
qubitLayer.pauliZ(parameter_0->index[0]->value);
} else if (name == "rx"){
auto parameter_0 = operation->operands[0]->as_qubit_refs();
auto parameter_1 = operation->operands[1]->as_const_real();
qubitLayer.rx(parameter_0->index[0]->value, parameter_1->value);
} else if (name == "ry"){
auto parameter_0 = operation->operands[0]->as_qubit_refs();
auto parameter_1 = operation->operands[1]->as_const_real();
qubitLayer.ry(parameter_0->index[0]->value, parameter_1->value);
} else if (name == "rz"){
auto parameter_0 = operation->operands[0]->as_qubit_refs();
auto parameter_1 = operation->operands[1]->as_const_real();
qubitLayer.rz(parameter_0->index[0]->value, parameter_1->value);
} else if (name == "cnot"){
auto parameter_0 = operation->operands[0]->as_qubit_refs();
auto parameter_1 = operation->operands[1]->as_qubit_refs();
qubitLayer.rx(parameter_0->index[0]->value, parameter_1->index[0]->value);
} else if (name == "toffoli"){
auto parameter_0 = operation->operands[0]->as_qubit_refs();
auto parameter_1 = operation->operands[1]->as_qubit_refs();
auto parameter_2 = operation->operands[2]->as_qubit_refs();
qubitLayer.toffoli(parameter_0->index[0]->value, parameter_1->index[0]->value, parameter_2->index[0]->value);
} else if (name == "measure"){
auto parameter_0 = operation->operands[0]->as_qubit_refs();
qubitLayer.measure(parameter_0->index[0]->value);
} else {
std::cout << "gate name: " << name << " unknown" << std::endl;
}
// DEBUG
qubitLayer.printQubits();
};
};
return 0;
};

int *rQXInterface::get_state()
{
return 0;
};
int rQXInterface::set_qasm(std::string path)
{
auto result = cqasm::analyze(path, "1.0");
std::cout << "Analysis successful"
<< "\n";
_numQubits = result->num_qubits;
std::cout << "Number of qubits:" << _numQubits << "\n";

_program = result;
return 0;
};

rQXInterface::~rQXInterface(){};
Loading