From 2cdbb127c883a1815ef29d7e032b0ce9e1229599 Mon Sep 17 00:00:00 2001
From: Alex McCaskey <mccaskeyaj@ornl.gov>
Date: Fri, 10 Feb 2017 16:16:43 +0000
Subject: [PATCH] Implemented QuantumCircuit graph with graphviz read method,
 updated tests for FireTensorAccelerator and SimulatedQubits

---
 quantum/gate/accelerators/CMakeLists.txt      |   2 +-
 quantum/gate/accelerators/SimulatedQubits.hpp |  31 ++-
 .../FireTensorAccelerator.hpp                 |   5 +-
 ...er.hpp => FireTensorAcceleratorTester.cpp} |  58 +++---
 .../tests/SimulatedQubitsTester.cpp           |  18 ++
 .../compilers/scaffold/ScaffoldCompiler.cpp   |   6 +-
 .../scaffold/tests/ScaffoldCompilerTester.cpp |   4 +-
 quantum/gate/utils/QasmToGraph.hpp            | 118 +-----------
 quantum/gate/utils/QuantumCircuit.hpp         | 148 +++++++++++++++
 .../gate/utils/tests/QuantumCircuitTester.cpp | 177 ++++++++++++++++++
 xacc/accelerator/Accelerator.hpp              |   4 +-
 11 files changed, 425 insertions(+), 146 deletions(-)
 rename quantum/gate/accelerators/tests/{FireTensorAcceleratorTester.hpp => FireTensorAcceleratorTester.cpp} (62%)
 create mode 100644 quantum/gate/utils/QuantumCircuit.hpp
 create mode 100644 quantum/gate/utils/tests/QuantumCircuitTester.cpp

diff --git a/quantum/gate/accelerators/CMakeLists.txt b/quantum/gate/accelerators/CMakeLists.txt
index cedd6e342..dc8c602b1 100644
--- a/quantum/gate/accelerators/CMakeLists.txt
+++ b/quantum/gate/accelerators/CMakeLists.txt
@@ -34,5 +34,5 @@ include_directories(${CMAKE_SOURCE_DIR}/tpls/common/tpls/fire/tpls/eigen)
 
 # Gather tests
 file (GLOB test_files tests/*.cpp)
-add_tests("${test_files}" "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/eigenaccelerator;${CMAKE_SOURCE_DIR}/tpls/common/tpls/fire/tensors;${CMAKE_SOURCE_DIR}/tpls/common/tpls/fire/tensors/impl;${CMAKE_SOURCE_DIR}/tpls/common/tpls/fire/tpls/eigen" "${Boost_LIBRARIES}")
+add_tests("${test_files}" "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/firetensoraccelerator;${CMAKE_SOURCE_DIR}/tpls/common/tpls/fire/tensors;${CMAKE_SOURCE_DIR}/tpls/common/tpls/fire/tensors/impl;${CMAKE_SOURCE_DIR}/tpls/common/tpls/fire/tpls/eigen" "${Boost_LIBRARIES}")
 
diff --git a/quantum/gate/accelerators/SimulatedQubits.hpp b/quantum/gate/accelerators/SimulatedQubits.hpp
index d5e8b7375..6181f94f8 100644
--- a/quantum/gate/accelerators/SimulatedQubits.hpp
+++ b/quantum/gate/accelerators/SimulatedQubits.hpp
@@ -42,6 +42,7 @@ public:
 					(int) std::pow(2, TotalNumberOfQubits)) {
 		// Initialize to |000...000> state
 		bufferState(0) = 1.0;
+		this->bufferSize = TotalNumberOfQubits;
 	}
 
 	/**
@@ -104,19 +105,39 @@ public:
 		bufferState = st;
 	}
 
+	/**
+	 * Allocating this buffer type is only valid
+	 * if N <= TotalNumberOfQubits.
+	 * @param N
+	 * @return
+	 */
+	virtual bool isValidBufferSize(const int N) {
+		return N <= TotalNumberOfQubits;
+	}
+
 	/**
 	 * Print the state to the provided output stream.
 	 *
 	 * @param stream
 	 */
 	void printBufferState(std::ostream& stream) {
-		for (int i = 0; i < bufferState.dimension(0); i++) {
-			stream
-					<< std::bitset<TotalNumberOfQubits>(i).to_string().substr(
-							size(), TotalNumberOfQubits) << " -> "
-					<< bufferState(i) << "\n";
+		if (size() < TotalNumberOfQubits) {
+			for (int i = 0; i < bufferState.dimension(0); i++) {
+				stream
+						<< std::bitset<TotalNumberOfQubits>(i).to_string().substr(
+								size(), TotalNumberOfQubits) << " -> "
+						<< bufferState(i) << "\n";
+			}
+		} else {
+			for (int i = 0; i < bufferState.dimension(0); i++) {
+
+				stream << std::bitset<TotalNumberOfQubits>(i).to_string()
+						<< " -> " << bufferState(i) << "\n";
+			}
 		}
 	}
+
+	virtual ~SimulatedQubits() {}
 };
 }
 }
diff --git a/quantum/gate/accelerators/firetensoraccelerator/FireTensorAccelerator.hpp b/quantum/gate/accelerators/firetensoraccelerator/FireTensorAccelerator.hpp
index 2f03bd9d0..89ca46de9 100644
--- a/quantum/gate/accelerators/firetensoraccelerator/FireTensorAccelerator.hpp
+++ b/quantum/gate/accelerators/firetensoraccelerator/FireTensorAccelerator.hpp
@@ -32,8 +32,8 @@
 #define QUANTUM_GATE_ACCELERATORS_EIGENACCELERATOR_HPP_
 
 #include "QPUGate.hpp"
-#include "QasmToGraph.hpp"
 #include "GraphIR.hpp"
+#include "QuantumCircuit.hpp"
 #include "SimulatedQubits.hpp"
 #include <random>
 
@@ -41,8 +41,7 @@ namespace xacc {
 namespace quantum {
 
 double sqrt2 = std::sqrt(2.0);
-using GraphType = qci::common::Graph<CircuitNode>;
-using QuantumGraphIR = xacc::GraphIR<GraphType>;
+using QuantumGraphIR = xacc::GraphIR<QuantumCircuit>;
 
 /**
  * The FireTensorAccelerator is an XACC Accelerator that simulates
diff --git a/quantum/gate/accelerators/tests/FireTensorAcceleratorTester.hpp b/quantum/gate/accelerators/tests/FireTensorAcceleratorTester.cpp
similarity index 62%
rename from quantum/gate/accelerators/tests/FireTensorAcceleratorTester.hpp
rename to quantum/gate/accelerators/tests/FireTensorAcceleratorTester.cpp
index 37211f990..0ec2255e5 100644
--- a/quantum/gate/accelerators/tests/FireTensorAcceleratorTester.hpp
+++ b/quantum/gate/accelerators/tests/FireTensorAcceleratorTester.cpp
@@ -41,26 +41,30 @@ using namespace xacc::quantum;
 BOOST_AUTO_TEST_CASE(checkConstruction) {
 
 	FireTensorAccelerator<3> acc;
-//	auto qreg = acc.allocate("qreg");
-
+	auto qreg = acc.createBuffer("qreg", 3);
 
 	// Create a graph IR modeling a
 	// quantum teleportation kernel
 	std::string irstr = "graph G {\n"
-			"{\nnode [shape=box style=filled]\n"
-			"0 [label=\"Gate=InitialState,Circuit Layer=0,Gate Vertex Id=0,Gate Acting Qubits=[0 1 2 3 4]\"];\n"
-			"1 [label=\"Gate=x,Circuit Layer=1,Gate Vertex Id=1,Gate Acting Qubits=[0]\"];\n"
-			"2 [label=\"Gate=h,Circuit Layer=1,Gate Vertex Id=2,Gate Acting Qubits=[1]\"];\n"
-			"3 [label=\"Gate=cnot,Circuit Layer=2,Gate Vertex Id=3,Gate Acting Qubits=[1 2]\"];\n"
-			"4 [label=\"Gate=cnot,Circuit Layer=3,Gate Vertex Id=4,Gate Acting Qubits=[0 1]\"];\n"
-			"5 [label=\"Gate=h,Circuit Layer=4,Gate Vertex Id=5,Gate Acting Qubits=[0]\"];\n"
-			"6 [label=\"Gate=measure,Circuit Layer=5,Gate Vertex Id=6,Gate Acting Qubits=[0]\"];\n"
-			"7 [label=\"Gate=measure,Circuit Layer=5,Gate Vertex Id=7,Gate Acting Qubits=[1]\"];\n"
-			"8 [label=\"Gate=h,Circuit Layer=6,Gate Vertex Id=8,Gate Acting Qubits=[2]\"];\n"
-			"9 [label=\"Gate=cnot,Circuit Layer=7,Gate Vertex Id=9,Gate Acting Qubits=[2 1]\"];\n"
-			"10 [label=\"Gate=h,Circuit Layer=8,Gate Vertex Id=10,Gate Acting Qubits=[2]\"];\n"
-			"11 [label=\"Gate=cnot,Circuit Layer=9,Gate Vertex Id=11,Gate Acting Qubits=[2 0]\"];\n"
-			"12 [label=\"Gate=FinalState,Circuit Layer=10,Gate Vertex Id=12,Gate Acting Qubits=[0 1 2 3 4]\"];\n"
+			"{\n"
+			"node [shape=box style=filled]\n"
+			"0 [label=\"Gate=InitialState,Circuit Layer=0,Gate Vertex Id=0,Gate Acting Qubits=[0 1 2],Enabled=1\"];\n"
+			"1 [label=\"Gate=x,Circuit Layer=1,Gate Vertex Id=1,Gate Acting Qubits=[0],Enabled=1\"];\n"
+			"2 [label=\"Gate=h,Circuit Layer=1,Gate Vertex Id=2,Gate Acting Qubits=[1],Enabled=1\"];\n"
+			"3 [label=\"Gate=cnot,Circuit Layer=2,Gate Vertex Id=3,Gate Acting Qubits=[1 2],Enabled=1\"];\n"
+			"4 [label=\"Gate=cnot,Circuit Layer=3,Gate Vertex Id=4,Gate Acting Qubits=[0 1],Enabled=1\"];\n"
+			"5 [label=\"Gate=h,Circuit Layer=4,Gate Vertex Id=5,Gate Acting Qubits=[0],Enabled=1\"];\n"
+			"6 [label=\"Gate=measure,Circuit Layer=5,Gate Vertex Id=6,Gate Acting Qubits=[0],Enabled=1\"];\n"
+			"7 [label=\"Gate=measure,Circuit Layer=5,Gate Vertex Id=7,Gate Acting Qubits=[1],Enabled=1\"];\n"
+			"8 [label=\"Gate=FinalState,Circuit Layer=6,Gate Vertex Id=8,Gate Acting Qubits=[0 1 2],Enabled=1\"];\n"
+			"9 [label=\"Gate=conditional,Circuit Layer=0,Gate Vertex Id=9,Gate Acting Qubits=[0],Enabled=1\"];\n"
+			"10 [label=\"Gate=InitialState,Circuit Layer=7,Gate Vertex Id=10,Gate Acting Qubits=[0 1 2],Enabled=0\"];\n"
+			"11 [label=\"Gate=z,Circuit Layer=8,Gate Vertex Id=11,Gate Acting Qubits=[2],Enabled=0\"];\n"
+			"12 [label=\"Gate=FinalState,Circuit Layer=9,Gate Vertex Id=12,Gate Acting Qubits=[0 1 2],Enabled=0\"];\n"
+			"13 [label=\"Gate=conditional,Circuit Layer=0,Gate Vertex Id=13,Gate Acting Qubits=[1],Enabled=1\"];\n"
+			"14 [label=\"Gate=InitialState,Circuit Layer=10,Gate Vertex Id=14,Gate Acting Qubits=[0 1 2],Enabled=0\"];\n"
+			"15 [label=\"Gate=x,Circuit Layer=11,Gate Vertex Id=15,Gate Acting Qubits=[2],Enabled=0\"];\n"
+			"16 [label=\"Gate=FinalState,Circuit Layer=12,Gate Vertex Id=16,Gate Acting Qubits=[0 1 2],Enabled=0\"];\n"
 			"}\n"
 			"0--1 ;\n"
 			"0--2 ;\n"
@@ -71,19 +75,31 @@ BOOST_AUTO_TEST_CASE(checkConstruction) {
 			"4--5 ;\n"
 			"5--6 ;\n"
 			"4--7 ;\n"
+			"6--8 ;\n"
+			"7--8 ;\n"
 			"3--8 ;\n"
 			"8--9 ;\n"
-			"7--9 ;\n"
 			"9--10 ;\n"
 			"10--11 ;\n"
-			"6--11 ;\n"
-			"11--12 ;\n"
+			"10--12 ;\n"
+			"10--12 ;\n"
 			"11--12 ;\n"
-			"9--12 ;\n"
+			"8--13 ;\n"
+			"13--14 ;\n"
+			"14--15 ;\n"
+			"14--16 ;\n"
+			"14--16 ;\n"
+			"15--16 ;\n"
 			"}";
 	std::istringstream iss(irstr);
 
-	auto graphir = std::make_shared<xacc::GraphIR<qci::common::Graph<CircuitNode>>>();
+	auto graphir = std::make_shared<xacc::GraphIR<QuantumCircuit>>();
 	graphir->read(iss);
+	acc.execute("qreg", graphir);
+
+	BOOST_VERIFY(qreg->getState()(1) * qreg->getState()(1) == 1 ||
+			qreg->getState()(5) * qreg->getState()(5) == 1 ||
+			qreg->getState()(3) * qreg->getState()(3) == 1 ||
+			qreg->getState()(7) * qreg->getState()(7) == 1);
 }
 
diff --git a/quantum/gate/accelerators/tests/SimulatedQubitsTester.cpp b/quantum/gate/accelerators/tests/SimulatedQubitsTester.cpp
index df3a7c635..5e8abdd7a 100644
--- a/quantum/gate/accelerators/tests/SimulatedQubitsTester.cpp
+++ b/quantum/gate/accelerators/tests/SimulatedQubitsTester.cpp
@@ -38,5 +38,23 @@ using namespace qci::common;
 using namespace xacc::quantum;
 
 BOOST_AUTO_TEST_CASE(checkConstruction) {
+
+	fire::Tensor<1> initialState1(8);
+	initialState1(0) = 1;
+	SimulatedQubits<3> qubits1("name1");
+	BOOST_VERIFY(qubits1.size() == 3);
+	BOOST_VERIFY(qubits1.name() == "name1");
+	BOOST_VERIFY(qubits1.getState().dimension(0) == 8);
+	BOOST_VERIFY(qubits1.getState() == initialState1);
+
+	fire::Tensor<1> initialState2(4);
+	initialState2(0) = 1;
+	SimulatedQubits<3> qubits2("name2", 2);
+	BOOST_VERIFY(qubits2.size() == 2);
+	BOOST_VERIFY(qubits2.name() == "name2");
+	BOOST_VERIFY(qubits2.getState().dimension(0) == 4);
+	BOOST_VERIFY(qubits2.getState() == initialState2);
+
 }
 
+
diff --git a/quantum/gate/compilers/scaffold/ScaffoldCompiler.cpp b/quantum/gate/compilers/scaffold/ScaffoldCompiler.cpp
index 9ac31c84a..3fed7012e 100644
--- a/quantum/gate/compilers/scaffold/ScaffoldCompiler.cpp
+++ b/quantum/gate/compilers/scaffold/ScaffoldCompiler.cpp
@@ -33,7 +33,7 @@
 #include <regex>
 #include "ScaffCCAPI.hpp"
 #include "QasmToGraph.hpp"
-#include <boost/algorithm/string.hpp>
+#include "QuantumCircuit.hpp"
 
 namespace xacc {
 
@@ -187,7 +187,7 @@ std::shared_ptr<IR> ScaffoldCompiler::compile() {
 	// so that we can interact with a locally installed
 	// scaffcc executable
 	scaffold::ScaffCCAPI scaffcc;
-	using ScaffoldGraphIR = GraphIR<Graph<CircuitNode>>;
+	using ScaffoldGraphIR = GraphIR<QuantumCircuit>;
 
 	// Compile the source code and return the QASM form
 	// This will throw if it fails.
@@ -207,7 +207,7 @@ std::shared_ptr<IR> ScaffoldCompiler::compile() {
 	// So a COND node needs to know the gate id of the measurement gate
 	// and the nodes to mark enabled if the measurement is a 1,
 	if (!conditionalCodeSegments.empty()) {
-		std::vector<qci::common::Graph<CircuitNode>> condGraphs;
+		std::vector<QuantumCircuit> condGraphs;
 		for (auto cond : conditionalCodeSegments) {
 			auto condQasm = scaffcc.getFlatQASMFromSource(cond);
 			auto g = QasmToGraph::getCircuitGraph(condQasm);
diff --git a/quantum/gate/compilers/scaffold/tests/ScaffoldCompilerTester.cpp b/quantum/gate/compilers/scaffold/tests/ScaffoldCompilerTester.cpp
index 74f630fc4..d9d2193f9 100644
--- a/quantum/gate/compilers/scaffold/tests/ScaffoldCompilerTester.cpp
+++ b/quantum/gate/compilers/scaffold/tests/ScaffoldCompilerTester.cpp
@@ -42,7 +42,7 @@ using namespace qci::common;
 using namespace xacc::quantum;
 
 BOOST_AUTO_TEST_CASE(checkSimpleCompile) {
-	using GraphType = Graph<CircuitNode>;
+	using GraphType = QuantumCircuit;
 
 	auto compiler = qci::common::AbstractFactory::createAndCast<xacc::ICompiler>("compiler", "scaffold");
 	BOOST_VERIFY(compiler);
@@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(checkSimpleCompile) {
 }
 
 BOOST_AUTO_TEST_CASE(checkCodeWithMeasurementIf) {
-	using GraphType = Graph<CircuitNode>;
+	using GraphType = QuantumCircuit;
 
 	auto compiler =
 			qci::common::AbstractFactory::createAndCast<xacc::ICompiler>(
diff --git a/quantum/gate/utils/QasmToGraph.hpp b/quantum/gate/utils/QasmToGraph.hpp
index 8b8bc1d9f..c4cbd8667 100644
--- a/quantum/gate/utils/QasmToGraph.hpp
+++ b/quantum/gate/utils/QasmToGraph.hpp
@@ -31,114 +31,12 @@
 #ifndef QUANTUM_GATE_QASMTOGRAPH_HPP_
 #define QUANTUM_GATE_QASMTOGRAPH_HPP_
 
-#include "Graph.hpp"
+#include "QuantumCircuit.hpp"
 #include <regex>
-#include <boost/algorithm/string.hpp>
 
 namespace xacc {
 namespace quantum {
 
-/**
- * CircuitNode subclasses QCIVertex to provide the following
- * parameters in the given order:
- *
- * Parameters: Gate, Layer (ie time sequence), Gate Vertex Id,
- * Qubit Ids that the gate acts on
- */
-class CircuitNode: public qci::common::QCIVertex<std::string, int, int,
-		std::vector<int>, bool> {
-public:
-	CircuitNode() :
-			QCIVertex() {
-		propertyNames[0] = "Gate";
-		propertyNames[1] = "Circuit Layer";
-		propertyNames[2] = "Gate Vertex Id";
-		propertyNames[3] = "Gate Acting Qubits";
-		propertyNames[4] = "Enabled";
-
-		// by default all circuit nodes
-		// are enabled and
-		std::get<4>(properties) = true;
-	}
-};
-
-class QuantumCircuit : virtual public qci::common::Graph<CircuitNode> {
-public:
-
-	virtual void read(std::istream& stream) {
-		std::string content { std::istreambuf_iterator<char>(stream),
-				std::istreambuf_iterator<char>() };
-
-		std::vector<std::string> lines, sections;
-		boost::split(sections, content, boost::is_any_of("}"));
-
-		// Sections should be size 2 for a valid dot file
-		boost::split(lines, sections[0], boost::is_any_of("\n"));
-		for (auto line : lines) {
-			if (boost::contains(line, "label")) {
-				CircuitNode v;
-				std::vector<std::string> labelLineSplit, attrSplit;
-				boost::split(labelLineSplit, line, boost::is_any_of("="));
-				auto attributes = labelLineSplit[1].substr(1, labelLineSplit.size()-3);
-				boost::split(attrSplit, attributes, boost::is_any_of(","));
-
-				std::tuple<std::string, int, int, std::vector<int>, bool> props;
-
-				std::map<std::string, std::string> attrMap;
-				for (auto a : attrSplit) {
-					std::vector<std::string> eqsplit;
-					boost::split(eqsplit, a, boost::is_any_of("="));
-
-					if (eqsplit[0] == "Gate") {
-						std::get<0>(v.properties) = eqsplit[1];
-					} else if (eqsplit[0] == "Circuit Layer") {
-						std::get<1>(v.properties) = std::stoi(eqsplit[1]);
-					} else if (eqsplit[0] == "Vertex Id") {
-						std::get<2>(v.properties) = std::stoi(eqsplit[1]);
-					} else if (eqsplit[0] == "Gate Acting Qubits") {
-						auto qubitsStr = eqsplit[1];
-						boost::replace_all(qubitsStr, "[", "");
-						boost::replace_all(qubitsStr, "[", "");
-						std::vector<std::string> elementsStr;
-						std::vector<int> qubits;
-						boost::split(elementsStr, qubitsStr,
-								boost::is_any_of(" "));
-						for (auto element : elementsStr) {
-							qubits.push_back(std::stoi(element));
-						}
-						std::get<3>(v.properties) = qubits;
-					} else if (eqsplit[0] == "Enabled") {
-						std::get<4>(v.properties) = (bool) std::stoi(
-								eqsplit[1]);
-					}
-
-					std::cout << "adding vertex " << std::get<0>(v.properties)
-							<< ", " << std::get<1>(v.properties) << ", "
-							<< std::get<2>(v.properties) << ", "
-							<< std::get<4>(v.properties) << "\n";
-					this->addVertex(v);
-				}
-
-			}
-		}
-
-		// Now add the edges
-		lines.clear();
-		boost::split(lines, sections[1], boost::is_any_of(";\n"));
-		for (auto line : lines) {
-			boost::trim(line);
-			if (line == "}") continue;
-			std::vector<std::string> vertexPairs;
-			boost::split(vertexPairs, line, boost::is_any_of("--"));
-			this->addEdge(std::stoi(vertexPairs[0]), std::stoi(vertexPairs[1]));
-			std::cout << "Adding Edge between " << vertexPairs[0] << " and " << vertexPairs[1] << "\n";
-		}
-	}
-
-
-	virtual ~QuantumCircuit() {}
-};
-
 /**
  * The QasmToGraph class provides a static
  * utility method that maps a flat qasm string
@@ -155,12 +53,12 @@ public:
 	 * @param flatQasmStr The qasm to be converted to a Graph.
 	 * @return graph Graph modeling a quantum circuit.
 	 */
-	static qci::common::Graph<CircuitNode> getCircuitGraph(
+	static QuantumCircuit getCircuitGraph(
 			const std::string& flatQasmStr) {
 
 		// Local Declarations
 		using namespace qci::common;
-		Graph<CircuitNode> graph;
+		QuantumCircuit graph;
 		std::map<std::string, int> qubitVarNameToId;
 		std::vector<std::string> qasmLines;
 		std::vector<int> allQbitIds;
@@ -276,8 +174,8 @@ public:
 	 * @param mainGraph
 	 * @param conditionalGraphs
 	 */
-	static void linkConditionalQasm(qci::common::Graph<CircuitNode>& mainGraph,
-			std::vector<qci::common::Graph<CircuitNode>>& conditionalGraphs,
+	static void linkConditionalQasm(QuantumCircuit& mainGraph,
+			std::vector<QuantumCircuit>& conditionalGraphs,
 			std::vector<int>& conditionalQubits) {
 
 		// At this point we have a main circuit graph,
@@ -356,12 +254,12 @@ private:
 	 * @param gateOperations
 	 * @param initialStateId
 	 */
-	static void generateEdgesFromLayer(const int layer,
-			qci::common::Graph<CircuitNode>& graph,
+	static void generateEdgesFromLayer(const int layer, QuantumCircuit& graph,
 			std::vector<CircuitNode>& gateOperations, int initialStateId) {
 
 		int nQubits = std::get<3>(graph.getVertexProperties(0)).size();
-		int maxLayer = std::get<1>(gateOperations[gateOperations.size() - 1].properties);
+		int maxLayer = std::get<1>(
+				gateOperations[gateOperations.size() - 1].properties);
 
 		std::map<int,int> qubitToCurrentGateId;
 		for (int i = 0 ; i < nQubits; i++) {
diff --git a/quantum/gate/utils/QuantumCircuit.hpp b/quantum/gate/utils/QuantumCircuit.hpp
new file mode 100644
index 000000000..1d61f892b
--- /dev/null
+++ b/quantum/gate/utils/QuantumCircuit.hpp
@@ -0,0 +1,148 @@
+/***********************************************************************************
+ * Copyright (c) 2016, UT-Battelle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of the xacc nor the
+ *     names of its contributors may be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Contributors:
+ *   Initial API and implementation - Alex McCaskey
+ *
+ **********************************************************************************/
+#ifndef QUANTUM_GATE_UTILS_QUANTUMCIRCUIT_HPP_
+#define QUANTUM_GATE_UTILS_QUANTUMCIRCUIT_HPP_
+
+#include "Graph.hpp"
+#include <boost/algorithm/string.hpp>
+
+namespace xacc {
+namespace quantum {
+/**
+ * CircuitNode subclasses QCIVertex to provide the following
+ * parameters in the given order:
+ *
+ * Parameters: Gate, Layer (ie time sequence), Gate Vertex Id,
+ * Qubit Ids that the gate acts on
+ */
+class CircuitNode: public qci::common::QCIVertex<std::string, int, int,
+		std::vector<int>, bool> {
+public:
+	CircuitNode() :
+			QCIVertex() {
+		propertyNames[0] = "Gate";
+		propertyNames[1] = "Circuit Layer";
+		propertyNames[2] = "Gate Vertex Id";
+		propertyNames[3] = "Gate Acting Qubits";
+		propertyNames[4] = "Enabled";
+
+		// by default all circuit nodes
+		// are enabled and
+		std::get<4>(properties) = true;
+	}
+};
+
+/**
+ * The QuantumCircuit is a subclass of Graph that provides
+ * its Vertex template parameter as a CircuitNode. It adds the
+ * ability to read QuantumCircuits from a graphviz dot file.
+ */
+class QuantumCircuit : virtual public qci::common::Graph<CircuitNode> {
+public:
+
+	virtual void read(std::istream& stream) {
+		std::string content { std::istreambuf_iterator<char>(stream),
+				std::istreambuf_iterator<char>() };
+
+		std::vector<std::string> lines, sections;
+		boost::split(sections, content, boost::is_any_of("}"));
+
+		// Sections should be size 2 for a valid dot file
+		boost::split(lines, sections[0], boost::is_any_of("\n"));
+		for (auto line : lines) {
+			if (boost::contains(line, "label")) {
+				CircuitNode v;
+
+				auto firstBracket = line.find_first_of('[');
+				line = line.substr(firstBracket+1, line.size()-2);
+
+				boost::replace_all(line, ";", "");
+				boost::replace_all(line, "[", "");
+				boost::replace_all(line, "]", "");
+				boost::replace_all(line, "\"", "");
+				boost::replace_all(line, "label=", "");
+				boost::trim(line);
+				std::vector<std::string> labelLineSplit, removeId;
+				boost::split(labelLineSplit, line, boost::is_any_of(","));
+
+				for (auto a : labelLineSplit) {
+					std::vector<std::string> eqsplit;
+					boost::split(eqsplit, a, boost::is_any_of("="));
+					if (eqsplit[0] == "Gate") {
+						std::get<0>(v.properties) = eqsplit[1];
+					} else if (eqsplit[0] == "Circuit Layer") {
+						std::get<1>(v.properties) = std::stoi(eqsplit[1]);
+					} else if (eqsplit[0] == "Gate Vertex Id") {
+						std::get<2>(v.properties) = std::stoi(eqsplit[1]);
+					} else if (eqsplit[0] == "Gate Acting Qubits") {
+						auto qubitsStr = eqsplit[1];
+						boost::replace_all(qubitsStr, "[", "");
+						boost::replace_all(qubitsStr, "[", "");
+						std::vector<std::string> elementsStr;
+						std::vector<int> qubits;
+						boost::split(elementsStr, qubitsStr,
+								boost::is_any_of(" "));
+						for (auto element : elementsStr) {
+							qubits.push_back(std::stoi(element));
+						}
+						std::get<3>(v.properties) = qubits;
+					} else if (eqsplit[0] == "Enabled") {
+						std::get<4>(v.properties) = (bool) std::stoi(
+								eqsplit[1]);
+					}
+
+				}
+				addVertex(v);
+			}
+		}
+
+		// Now add the edges
+		lines.clear();
+		boost::split(lines, sections[1], boost::is_any_of(";\n"));
+		for (auto line : lines) {
+			boost::trim(line);
+			if (line == "}" || line.empty()) continue;
+			boost::trim(line);
+			boost::replace_all(line, "--", " ");
+			std::vector<std::string> vertexPairs;
+			boost::split(vertexPairs, line, boost::is_any_of(" "));
+			addEdge(std::stoi(vertexPairs[0]), std::stoi(vertexPairs[1]));
+		}
+	}
+
+
+	virtual ~QuantumCircuit() {}
+};
+
+}
+}
+
+#endif /* QUANTUM_GATE_UTILS_QUANTUMCIRCUIT_HPP_ */
diff --git a/quantum/gate/utils/tests/QuantumCircuitTester.cpp b/quantum/gate/utils/tests/QuantumCircuitTester.cpp
new file mode 100644
index 000000000..a5bbb1da9
--- /dev/null
+++ b/quantum/gate/utils/tests/QuantumCircuitTester.cpp
@@ -0,0 +1,177 @@
+/***********************************************************************************
+ * Copyright (c) 2016, UT-Battelle
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of the xacc nor the
+ *     names of its contributors may be used to endorse or promote products
+ *     derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Contributors:
+ *   Initial API and implementation - Alex McCaskey
+ *
+ **********************************************************************************/
+#define BOOST_TEST_DYN_LINK
+#define BOOST_TEST_MODULE ScaffoldCompilerTester
+
+#include <boost/test/included/unit_test.hpp>
+#include "QuantumCircuit.hpp"
+
+using namespace xacc::quantum;
+
+BOOST_AUTO_TEST_CASE(checkReadGraph) {
+
+	// Create a graph IR modeling a
+	// quantum teleportation kernel
+	std::string irstr = "graph G {\n"
+			"{\n"
+			"node [shape=box style=filled]\n"
+			"0 [label=\"Gate=InitialState,Circuit Layer=0,Gate Vertex Id=0,Gate Acting Qubits=[0 1 2],Enabled=1\"];\n"
+			"1 [label=\"Gate=x,Circuit Layer=1,Gate Vertex Id=1,Gate Acting Qubits=[0],Enabled=1\"];\n"
+			"2 [label=\"Gate=h,Circuit Layer=1,Gate Vertex Id=2,Gate Acting Qubits=[1],Enabled=1\"];\n"
+			"3 [label=\"Gate=cnot,Circuit Layer=2,Gate Vertex Id=3,Gate Acting Qubits=[1 2],Enabled=1\"];\n"
+			"4 [label=\"Gate=cnot,Circuit Layer=3,Gate Vertex Id=4,Gate Acting Qubits=[0 1],Enabled=1\"];\n"
+			"5 [label=\"Gate=h,Circuit Layer=4,Gate Vertex Id=5,Gate Acting Qubits=[0],Enabled=1\"];\n"
+			"6 [label=\"Gate=measure,Circuit Layer=5,Gate Vertex Id=6,Gate Acting Qubits=[0],Enabled=1\"];\n"
+			"7 [label=\"Gate=measure,Circuit Layer=5,Gate Vertex Id=7,Gate Acting Qubits=[1],Enabled=1\"];\n"
+			"8 [label=\"Gate=FinalState,Circuit Layer=6,Gate Vertex Id=8,Gate Acting Qubits=[0 1 2],Enabled=1\"];\n"
+			"9 [label=\"Gate=conditional,Circuit Layer=0,Gate Vertex Id=9,Gate Acting Qubits=[0],Enabled=1\"];\n"
+			"10 [label=\"Gate=InitialState,Circuit Layer=7,Gate Vertex Id=10,Gate Acting Qubits=[0 1 2],Enabled=0\"];\n"
+			"11 [label=\"Gate=z,Circuit Layer=8,Gate Vertex Id=11,Gate Acting Qubits=[2],Enabled=0\"];\n"
+			"12 [label=\"Gate=FinalState,Circuit Layer=9,Gate Vertex Id=12,Gate Acting Qubits=[0 1 2],Enabled=0\"];\n"
+			"13 [label=\"Gate=conditional,Circuit Layer=0,Gate Vertex Id=13,Gate Acting Qubits=[1],Enabled=1\"];\n"
+			"14 [label=\"Gate=InitialState,Circuit Layer=10,Gate Vertex Id=14,Gate Acting Qubits=[0 1 2],Enabled=0\"];\n"
+			"15 [label=\"Gate=x,Circuit Layer=11,Gate Vertex Id=15,Gate Acting Qubits=[2],Enabled=0\"];\n"
+			"16 [label=\"Gate=FinalState,Circuit Layer=12,Gate Vertex Id=16,Gate Acting Qubits=[0 1 2],Enabled=0\"];\n"
+			"}\n"
+			"0--1 ;\n"
+			"0--2 ;\n"
+			"2--3 ;\n"
+			"0--3 ;\n"
+			"1--4 ;\n"
+			"3--4 ;\n"
+			"4--5 ;\n"
+			"5--6 ;\n"
+			"4--7 ;\n"
+			"6--8 ;\n"
+			"7--8 ;\n"
+			"3--8 ;\n"
+			"8--9 ;\n"
+			"9--10 ;\n"
+			"10--11 ;\n"
+			"10--12 ;\n"
+			"10--12 ;\n"
+			"11--12 ;\n"
+			"8--13 ;\n"
+			"13--14 ;\n"
+			"14--15 ;\n"
+			"14--16 ;\n"
+			"14--16 ;\n"
+			"15--16 ;\n"
+			"}";
+	std::istringstream iss(irstr);
+
+	QuantumCircuit circuit;
+	circuit.read(iss);
+
+	std::map<int, std::vector<int>> expectedQubits;
+	expectedQubits.insert(std::make_pair(0, std::vector<int>{0, 1, 2}));
+	expectedQubits.insert(std::make_pair(1, std::vector<int>{0}));
+	expectedQubits.insert(std::make_pair(2, std::vector<int>{1}));
+	expectedQubits.insert(std::make_pair(3, std::vector<int>{1, 2}));
+	expectedQubits.insert(std::make_pair(4, std::vector<int>{0, 1}));
+	expectedQubits.insert(std::make_pair(5, std::vector<int>{0}));
+	expectedQubits.insert(std::make_pair(6, std::vector<int>{0}));
+	expectedQubits.insert(std::make_pair(7, std::vector<int>{1}));
+	expectedQubits.insert(std::make_pair(8, std::vector<int>{0, 1, 2}));
+	expectedQubits.insert(std::make_pair(9, std::vector<int>{0}));
+	expectedQubits.insert(std::make_pair(10, std::vector<int>{0, 1, 2}));
+	expectedQubits.insert(std::make_pair(11, std::vector<int>{2}));
+	expectedQubits.insert(std::make_pair(12, std::vector<int>{0, 1, 2}));
+	expectedQubits.insert(std::make_pair(13, std::vector<int>{1}));
+	expectedQubits.insert(std::make_pair(14, std::vector<int>{0, 1, 2}));
+	expectedQubits.insert(std::make_pair(15, std::vector<int>{2}));
+	expectedQubits.insert(std::make_pair(16, std::vector<int>{0, 1, 2}));
+
+	BOOST_VERIFY(circuit.order() == 17);
+	BOOST_VERIFY(circuit.size() == 24);
+
+	BOOST_VERIFY(circuit.getVertexProperty<0>(0) == "InitialState");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(1) == "x");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(2) == "h");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(3) == "cnot");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(4) == "cnot");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(5) == "h");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(6) == "measure");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(7) == "measure");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(8) == "FinalState");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(9) == "conditional");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(10) == "InitialState");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(11) == "z");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(12) == "FinalState");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(13) == "conditional");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(14) == "InitialState");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(15) == "x");
+	BOOST_VERIFY(circuit.getVertexProperty<0>(16) == "FinalState");
+
+	for (int i = 0; i < 17; i++) {
+		BOOST_VERIFY(circuit.getVertexProperty<2>(i) == i);
+		BOOST_VERIFY(circuit.getVertexProperty<3>(i) == expectedQubits[i]);
+	}
+
+	BOOST_VERIFY(circuit.getVertexProperty<1>(0) == 0);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(1) == 1);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(2) == 1);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(3) == 2);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(4) == 3);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(5) == 4);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(6) == 5);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(7) == 5);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(8) == 6);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(9) == 0);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(10) == 7);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(11) == 8);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(12) == 9);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(13) == 0);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(14) == 10);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(15) == 11);
+	BOOST_VERIFY(circuit.getVertexProperty<1>(16) == 12);
+
+	BOOST_VERIFY(circuit.getVertexProperty<4>(0));
+	BOOST_VERIFY(circuit.getVertexProperty<4>(1));
+	BOOST_VERIFY(circuit.getVertexProperty<4>(2));
+	BOOST_VERIFY(circuit.getVertexProperty<4>(3));
+	BOOST_VERIFY(circuit.getVertexProperty<4>(4));
+	BOOST_VERIFY(circuit.getVertexProperty<4>(5));
+	BOOST_VERIFY(circuit.getVertexProperty<4>(6));
+	BOOST_VERIFY(circuit.getVertexProperty<4>(7));
+	BOOST_VERIFY(circuit.getVertexProperty<4>(8));
+	BOOST_VERIFY(circuit.getVertexProperty<4>(9));
+	BOOST_VERIFY(!circuit.getVertexProperty<4>(10));
+	BOOST_VERIFY(!circuit.getVertexProperty<4>(11));
+	BOOST_VERIFY(!circuit.getVertexProperty<4>(12));
+	BOOST_VERIFY(circuit.getVertexProperty<4>(13));
+	BOOST_VERIFY(!circuit.getVertexProperty<4>(14));
+	BOOST_VERIFY(!circuit.getVertexProperty<4>(15));
+	BOOST_VERIFY(!circuit.getVertexProperty<4>(16));
+
+
+
+}
diff --git a/xacc/accelerator/Accelerator.hpp b/xacc/accelerator/Accelerator.hpp
index 562100c52..0fbef44ea 100644
--- a/xacc/accelerator/Accelerator.hpp
+++ b/xacc/accelerator/Accelerator.hpp
@@ -139,7 +139,9 @@ protected:
 template<typename BitsType>
 class Accelerator : public IAccelerator {
 
-	static_assert(std::is_base_of<AcceleratorBuffer, BitsType>::value, "");
+	static_assert(std::is_base_of<AcceleratorBuffer, BitsType>::value, "Accelerators "
+			"can only be instantiated with a valid AcceleratorBuffer type as "
+			"the template parameter.");
 
 	using BitsTypePtr = std::shared_ptr<BitsType>;
 
-- 
GitLab