Commit cc69506e authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

fix to ir to graph visitor (adding s and t gates), added getPtrLike to heterogeneous map



Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 6d3252c4
......@@ -22,7 +22,6 @@ namespace external {
class PythonPluginLoader : public ExternalLanguagePluginLoader {
protected:
py::scoped_interpreter* guard;
void* libpython_handle;
public:
const std::string name() const override { return "python"; }
......
......@@ -23,7 +23,7 @@ bool PythonPluginLoader::load() {
if (!XACC_IS_APPLE){
libpython_handle = dlopen("@PYTHON_LIB_NAME@", RTLD_LAZY | RTLD_GLOBAL);
}
py::scoped_interpreter * guard = new py::scoped_interpreter();
py::initialize_interpreter();
try {
py::module sys = py::module::import("xacc");
sys.attr("loaded_from_cpp_dont_finalize") = true;
......@@ -38,7 +38,7 @@ bool PythonPluginLoader::load() {
bool PythonPluginLoader::unload() {
if (!XACC_IS_APPLE) {
xacc::debug("[PyPluginLoader] Unloading Python plugins");
delete guard;
py::finalize_interpreter();
int i = dlclose(libpython_handle);
if (i != 0) {
std::cout << "error closing python lib: " << i << "\n";
......
......@@ -38,38 +38,41 @@ public:
IRToGraphVisitor(const int nQubits);
std::shared_ptr<Graph> getGraph();
void visit(Hadamard &h) { addSingleQubitGate(h); }
void visit(Hadamard &h) override { addSingleQubitGate(h); }
void visit(Identity &i) { addSingleQubitGate(i);}
void visit(Identity &i) override { addSingleQubitGate(i);}
void visit(CZ &cz) { addTwoQubitGate(cz); }
void visit(CZ &cz) override { addTwoQubitGate(cz); }
void visit(CNOT &cn) { addTwoQubitGate(cn); }
void visit(CNOT &cn) override { addTwoQubitGate(cn); }
void visit(X &x) { addSingleQubitGate(x); }
void visit(X &x) override { addSingleQubitGate(x); }
void visit(Y &y) { addSingleQubitGate(y); }
void visit(Y &y) override { addSingleQubitGate(y); }
void visit(Z &z) { addSingleQubitGate(z); }
void visit(Z &z) override { addSingleQubitGate(z); }
void visit(Measure &m) { addSingleQubitGate(m); }
void visit(Measure &m) override { addSingleQubitGate(m); }
// void visit(ConditionalFunction &c) {
// nothing
// }
void visit(Rx &rx) override { addSingleQubitGate(rx); }
void visit(Rx &rx) { addSingleQubitGate(rx); }
void visit(Ry &ry) override { addSingleQubitGate(ry); }
void visit(Ry &ry) { addSingleQubitGate(ry); }
void visit(Rz &rz) override { addSingleQubitGate(rz); }
void visit(Rz &rz) { addSingleQubitGate(rz); }
void visit(CPhase &cp) override { addTwoQubitGate(cp); }
void visit(CPhase &cp) { addTwoQubitGate(cp); }
void visit(Swap &s) override { addTwoQubitGate(s); }
void visit(Swap &s) { addTwoQubitGate(s); }
void visit(U &u) override { addSingleQubitGate(u); }
void visit(U &u) { addSingleQubitGate(u); }
void visit(S &s) override { addSingleQubitGate(s);}
void visit(Sdg &sdg) override {addSingleQubitGate(sdg);}
void visit(T &t) override {addSingleQubitGate(t);}
void visit(Tdg &tdg) override {addSingleQubitGate(tdg);}
void visit(CRZ &crz) override {addTwoQubitGate(crz);}
void visit(CH &ch) override {addTwoQubitGate(ch);}
// Base gate visitor, i.e. none of the concrete gates can match.
// We need to assert here because we cannot generate a graph when there are unknown gates.
// e.g. there is an 1-1 mapping between node Id (in the graph) and instruction counter (in the circuit),
......
......@@ -23,34 +23,41 @@ using namespace xacc;
namespace xacc {
namespace algorithm {
bool VQE::initialize(const HeterogeneousMap &parameters) {
if (!parameters.keyExists<std::shared_ptr<Observable>>("observable")) {
if (!parameters.pointerLikeExists<Observable>("observable")) {
std::cout << "Obs was false\n";
return false;
} else if (!parameters.keyExists<std::shared_ptr<CompositeInstruction>>(
} else if (!parameters.pointerLikeExists<CompositeInstruction>(
"ansatz")) {
std::cout << "Ansatz was false\n";
return false;
} else if (!parameters.keyExists<std::shared_ptr<Accelerator>>(
} else if (!parameters.pointerLikeExists<Accelerator>(
"accelerator")) {
std::cout << "Acc was false\n";
return false;
}
try {
observable =
parameters.get_with_throw<std::shared_ptr<Observable>>("observable");
} catch (std::exception &e) {
observable = std::shared_ptr<Observable>(
parameters.get<Observable *>("observable"), [](Observable *) {});
}
if (parameters.keyExists<std::shared_ptr<Optimizer>>("optimizer")) {
optimizer = parameters.get<std::shared_ptr<Optimizer>>("optimizer");
} else {
optimizer = xacc::getOptimizer("nlopt");
}
kernel = parameters.get<std::shared_ptr<CompositeInstruction>>("ansatz");
accelerator = parameters.get<std::shared_ptr<Accelerator>>("accelerator");
observable = parameters.getPointerLike<Observable>("observable");
optimizer = parameters.getPointerLike<Optimizer>("optimizer");
accelerator = parameters.getPointerLike<Accelerator>("accelerator");
kernel = parameters.getPointerLike<CompositeInstruction>("ansatz");
// try {
// observable =
// parameters.get_with_throw<std::shared_ptr<Observable>>("observable");
// } catch (std::exception &e) {
// observable = std::shared_ptr<Observable>(
// parameters.get<Observable *>("observable"), [](Observable *) {});
// }
// if (parameters.keyExists<std::shared_ptr<Optimizer>>("optimizer")) {
// optimizer = parameters.get<std::shared_ptr<Optimizer>>("optimizer");
// } else {
// optimizer = xacc::getOptimizer("nlopt");
// }
// kernel = parameters.get<std::shared_ptr<CompositeInstruction>>("ansatz");
// accelerator = parameters.get<std::shared_ptr<Accelerator>>("accelerator");
return true;
}
......@@ -61,8 +68,7 @@ const std::vector<std::string> VQE::requiredParameters() const {
void VQE::execute(const std::shared_ptr<AcceleratorBuffer> buffer) const {
// void VQE::execute(xacc::Observable &observable, Optimizer &optimizer) {
auto kernels = observable->observe(kernel);
auto kernels = observable->observe(xacc::as_shared_ptr(kernel));
// Here we just need to make a lambda kernel
// to optimize that makes calls to the targeted QPU.
......@@ -147,7 +153,7 @@ void VQE::execute(const std::shared_ptr<AcceleratorBuffer> buffer) const {
std::vector<double>
VQE::execute(const std::shared_ptr<AcceleratorBuffer> buffer,
const std::vector<double> &x) {
auto kernels = observable->observe(kernel);
auto kernels = observable->observe(xacc::as_shared_ptr(kernel));
std::vector<double> coefficients;
std::vector<std::string> kernelNames;
std::vector<std::shared_ptr<CompositeInstruction>> fsToExec;
......
......@@ -19,10 +19,10 @@ namespace xacc {
namespace algorithm {
class VQE : public Algorithm {
protected:
std::shared_ptr<Observable> observable;
std::shared_ptr<Optimizer> optimizer;
std::shared_ptr<CompositeInstruction> kernel;
std::shared_ptr<Accelerator> accelerator;
Observable * observable;
Optimizer * optimizer;
CompositeInstruction * kernel;
Accelerator * accelerator;
std::vector<double> initial_params;
HeterogeneousMap parameters;
......
......@@ -17,7 +17,7 @@
TEST(StaqCompilerTester, checkSimple) {
auto compiler = xacc::getCompiler("staq");
auto IR = compiler->compile(R"(OPENQASM 2.0;
auto IR = compiler->compile(R"(
qreg q[2];
creg c[2];
U(0,0,0) q[0];
......
......@@ -6,12 +6,19 @@
namespace xacc {
namespace internal_compiler {
Accelerator *qpu = nullptr;
CompositeInstruction* lastCompiled = nullptr;
bool __execute = true;
void __set_verbose(bool v) {
xacc::set_verbose(v);
}
void compiler_InitializeXACC(const char *qpu_backend) {
if (!xacc::isInitialized())
xacc::Initialize();
xacc::external::load_external_language_plugins();
setAccelerator(qpu_backend);
}
void setAccelerator(const char *qpu_backend) {
......@@ -29,15 +36,24 @@ void setAccelerator(const char * qpu_backend, const int shots) {
qpu->updateConfiguration({std::make_pair("shots", shots)});
}
Accelerator* get_qpu() {
return qpu;
}
CompositeInstruction* getLastCompiled() {
return lastCompiled;
}
// Map kernel source string representing a single
// kernel function to a single CompositeInstruction (src to IR)
CompositeInstruction *compile(const char *compiler_name,
const char *kernel_src) {
auto qpu_as_shared =
std::shared_ptr<Accelerator>(qpu, empty_delete<Accelerator>());
std::shared_ptr<Accelerator>(qpu, xacc::empty_delete<Accelerator>());
auto compiler = xacc::getCompiler(compiler_name);
auto IR = compiler->compile(kernel_src, qpu_as_shared);
auto program = IR->getComposites()[0];
lastCompiled = program.get();
return program.get();
}
......@@ -49,18 +65,23 @@ CompositeInstruction *getCompiled(const char *kernel_name) {
// Run quantum compilation routines on IR
void optimize(CompositeInstruction *program, const OptLevel opt) {
xacc::info("[InternalCompiler] Pre-optimization, circuit has " + std::to_string(program->nInstructions()) + " instructions.");
// We don't own this ptr, so create shared_ptr with empty deleter
auto as_shared = std::shared_ptr<CompositeInstruction>(
program, empty_delete<CompositeInstruction>());
program, xacc::empty_delete<CompositeInstruction>());
auto qpu_as_shared =
std::shared_ptr<Accelerator>(qpu, empty_delete<Accelerator>());
std::shared_ptr<Accelerator>(qpu, xacc::empty_delete<Accelerator>());
if (opt == DEFAULT) {
auto optimizer = xacc::getIRTransformation("circuit-optimizer");
optimizer->apply(as_shared, qpu_as_shared);
} else {
xacc::error("Other Optimization Levels not yet supported.");
}
xacc::info("[InternalCompiler] Post-optimization, circuit has " + std::to_string(program->nInstructions()) + " instructions.");
}
// Execute on the specified QPU, persisting results to
......@@ -75,10 +96,13 @@ void execute(AcceleratorBuffer *buffer, CompositeInstruction *program,
} else {
// We don't own this ptr, so create shared_ptr with empty deleter
program_as_shared = std::shared_ptr<CompositeInstruction>(
program, empty_delete<CompositeInstruction>());
program, xacc::empty_delete<CompositeInstruction>());
}
auto buffer_as_shared = std::shared_ptr<AcceleratorBuffer>(
buffer, empty_delete<AcceleratorBuffer>());
buffer, xacc::empty_delete<AcceleratorBuffer>());
optimize(program);
qpu->execute(buffer_as_shared, program_as_shared);
}
......@@ -96,7 +120,7 @@ void execute(AcceleratorBuffer **buffers, const int nBuffers,
// We don't own this ptr, so create shared_ptr with empty deleter
auto program_as_shared = std::shared_ptr<CompositeInstruction>(
program, empty_delete<CompositeInstruction>());
program, xacc::empty_delete<CompositeInstruction>());
// Do we have any unknown ancilla bits?
std::vector<std::string> possible_extra_buffers;
......@@ -185,6 +209,8 @@ void execute(AcceleratorBuffer **buffers, const int nBuffers,
}
}
optimize(program);
// Now execute using the global merged register
execute(tmp.get(), program, parameters);
......
......@@ -20,23 +20,24 @@ class Accelerator;
namespace internal_compiler {
extern Accelerator *qpu;
template <typename T> struct empty_delete {
empty_delete() {}
void operator()(T *const) const {}
};
extern CompositeInstruction * lastCompiled;
extern bool __execute;
enum OptLevel { DEFAULT, LEVEL1, LEVEL2, LEVEL3 };
void compiler_InitializeXACC(const char *qpu_backend = "local-ibm");
void setAccelerator(const char * qpu_backend);
void setAccelerator(const char * qpu_backend, const int shots);
Accelerator* get_qpu();
void __set_verbose(bool verbose);
// Map kernel source string representing a single
// kernel function to a single CompositeInstruction (src to IR)
CompositeInstruction *compile(const char *compiler_name,
const char *kernel_src);
CompositeInstruction* getLastCompiled();
CompositeInstruction *getCompiled(const char *kernel_name);
// Run quantum compilation routines on IR
......
......@@ -63,7 +63,7 @@ TEST(InternalCompilerTester, checkStaqAdd) {
return;
}
xacc::external::load_external_language_plugins();
// xacc::external::load_external_language_plugins();
if (!xacc::hasAccelerator("aer")) {
return;
}
......@@ -98,6 +98,9 @@ TEST(InternalCompilerTester, checkStaqAdd) {
measure c -> result;
})";
auto circuit = compile("staq", src);
// optimize(circuit);
xacc::AcceleratorBuffer *bufs[3] = {a.results(), b.results(), c.results()};
// std::vector<xacc::AcceleratorBuffer*> bufs{q.results(),r.results()};
......
......@@ -37,6 +37,16 @@ bool directoryExists(const std::string path);
void print_backtrace();
template <typename T> struct empty_delete {
empty_delete() {}
void operator()(T *const) const {}
};
// This function assumes ownership of pointer is taken care of elsewhere.
template<typename T> std::shared_ptr<T> as_shared_ptr(T* ptr) {
return std::shared_ptr<T>(ptr, empty_delete<T>());
}
template <class Op> void split(const std::string &s, char delim, Op op) {
std::stringstream ss(s);
for (std::string item; std::getline(ss, item, delim);) {
......
......@@ -99,9 +99,7 @@ public:
template <class T> T &get_mutable(const std::string key) const {
if (!items<T>.count(this) && !items<T>[this].count(key)) {
XACCLogger::instance()->error("Invalid type (" +
std::string(typeid(T).name()) +
") or key (" + key + ").");
XACCLogger::instance()->error("Invalid type or key (" + key + ").");
print_backtrace();
}
return items<T>[this][key];
......@@ -109,9 +107,7 @@ public:
template <class T> const T &get(const std::string key) const {
if (!keyExists<T>(key)) {
XACCLogger::instance()->error("Invalid type (" +
std::string(typeid(T).name()) +
") or key (" + key + ").");
XACCLogger::instance()->error("Invalid type or key (" + key + ").");
print_backtrace();
}
return items<T>[this][key];
......@@ -119,8 +115,7 @@ public:
template <class T> const T &get_with_throw(const std::string key) const {
if (!items<T>.count(this) && !items<T>[this].count(key)) {
throw new std::runtime_error("Invalid type (" +
std::string(typeid(T).name()) + ").");
throw new std::runtime_error("Invalid type.");
}
return items<T>[this][key];
}
......@@ -148,6 +143,29 @@ public:
return "";
}
template<typename T>
bool pointerLikeExists(const std::string key) const {
if (keyExists<T*>(key)) {
return true;
} else if (keyExists<std::shared_ptr<T>>(key)) {
return true;
} else {
return false;
}
}
template<typename T>
T* getPointerLike(const std::string key) const {
if (keyExists<T*>(key)) {
return get<T*>(key);
} else if (keyExists<std::shared_ptr<T>>(key)) {
return get<std::shared_ptr<T>>(key).get();
} else {
XACCLogger::instance()->error("No pointer-like value at provided key (" +
key + ").");
print_backtrace();
}
return nullptr;
}
void clear() {
for (auto &&clear_func : clear_functions) {
clear_func(*this);
......@@ -272,8 +290,7 @@ public:
std::stringstream s;
s << "InstructionParameter::this->toString() = " << toString() << "\n";
s << "This InstructionParameter type id is " << this->which() << "\n";
XACCLogger::instance()->error("Cannot cast Variant to (" +
std::string(typeid(T).name()) + "):\n" +
XACCLogger::instance()->error("Cannot cast Variant: " +
s.str());
print_backtrace();
exit(0);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment