DWQMICompiler.cpp 6.44 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/***********************************************************************************
 * 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
 *
 **********************************************************************************/
#include <regex>
#include <boost/algorithm/string.hpp>
33
34
#include "DWQMICompiler.hpp"
#include "DWKernel.hpp"
35
#include "RuntimeOptions.hpp"
36
#include "AQCAcceleratorBuffer.hpp"
37
#include "ParameterSetter.hpp"
38
39
40
41
42

namespace xacc {

namespace quantum {

43
std::shared_ptr<IR> DWQMICompiler::compile(const std::string& src,
44
45
		std::shared_ptr<Accelerator> acc) {

46
47
48
49
50
51
	auto runtimeOptions = RuntimeOptions::instance();
	auto hardwareGraph = acc->getAcceleratorConnectivity();
	std::set<int> qubits;
	std::vector<std::shared_ptr<DWQMI>> instructions;
	int nHardwareVerts = hardwareGraph->order();

52
53
54
	// Set the Kernel Source code
	kernelSource = src;

55
56
	// Here we assume, there is just one allocation
	// of qubits for the D-Wave -- all of them.
Mccaskey, Alex's avatar
Mccaskey, Alex committed
57
58
59
60
61
62
	auto bufName = acc->getAllocatedBufferNames()[0];
	auto buffer = acc->getBuffer(bufName);
	auto aqcBuffer = std::dynamic_pointer_cast<AQCAcceleratorBuffer>(buffer);
	if (!aqcBuffer) {
		XACCError("Invalid AcceleratorBuffer passed to DW QMI Compiler. Must be an AQCAcceleratorBuffer.");
	}
63

64
65
66
67
68
69
	// Here we expect we have a kernel, only one kernel,
	// and that it is just machine level instructions
	// So just pick out where the opening and closing
	// brackets are, and then get the text between them.

	// First off, split the string into lines
70
	std::vector<std::string> lines, fLineSpaces;
71
	boost::split(lines, src, boost::is_any_of("\n"));
72
73
74
75
76
77
	auto functionLine = lines[0];
	boost::split(fLineSpaces, functionLine, boost::is_any_of(" "));
	auto fName = fLineSpaces[1];
	boost::trim(fName);
	fName = fName.substr(0, fName.find_first_of("("));
	auto dwKernel = std::make_shared<DWKernel>(fName);
78
79
80
81
	auto firstCodeLine = lines.begin() + 1;
	auto lastCodeLine = lines.end() - 1;
	std::vector<std::string> qmiStrVec(firstCodeLine, lastCodeLine);

82
	// Loop over the lines to create DWQMI
83
84
	for (auto qmi : qmiStrVec) {
		boost::trim(qmi);
85
		if (!qmi.empty() && (std::string::npos != qmi.find_first_of("0123456789"))) {
86
87
88
89
90
			std::vector<std::string> splitOnSpaces;
			boost::split(splitOnSpaces, qmi, boost::is_any_of(" "));
			auto qbit1 = std::stoi(splitOnSpaces[0]);
			auto qbit2 = std::stoi(splitOnSpaces[1]);
			auto weight = std::stod(splitOnSpaces[2]);
91
92
93
94
95
			qubits.insert(qbit1);
			qubits.insert(qbit2);
			instructions.emplace_back(std::make_shared<DWQMI>(qbit1, qbit2, weight));
		}
	}
96

97
98
99
100
101
102
103
	// Now we have a qubits set. If we used 0-N qubits,
	// then this set size will be N, but if we skipped some
	// bits, then it will be < N. Get the maximum int in this set
	// so we can see if any were skipped.
	int maxBitIdx = *qubits.rbegin();
	maxBitIdx++;

104
	// Create a graph representation of the problem
105
	auto problemGraph = std::make_shared<DWGraph>(maxBitIdx);
106
107
108
109
110
111
112
113
114
	for (auto inst : instructions) {
		auto qbit1 = inst->bits()[0];
		auto qbit2 = inst->bits()[1];
		double weightOrBias = boost::get<double>(inst->getParameter(0));
		if (qbit1 == qbit2) {
			problemGraph->setVertexProperties(qbit1, weightOrBias);
		} else {
			problemGraph->addEdge(qbit1, qbit2,
					weightOrBias);
115
		}
116
	}
117

118
	Embedding embedding;
119
	// Get an embedding algorithm to execute
120
121
	if (!runtimeOptions->exists("dwave-embedding")
			&& !runtimeOptions->exists("dwave-load-embedding")) {
122
		// For now, this is an error
123
		XACCError("You must specify an embedding algorithm or embedding file.");
124
125
	}

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
	if (runtimeOptions->exists("dwave-load-embedding")) {
		std::ifstream ifs((*runtimeOptions)["dwave-load-embedding"]);
		embedding.load(ifs);
	} else {
		auto algoStr = (*runtimeOptions)["dwave-embedding"];
		auto embeddingAlgorithm =
				EmbeddingAlgorithmRegistry::instance()->create(algoStr);

		// Compute the minor graph embedding
		embedding = embeddingAlgorithm->embed(problemGraph, hardwareGraph);

		if (runtimeOptions->exists("dwave-persist-embedding")) {
			auto fileName = (*runtimeOptions)["dwave-persist-embedding"];
			std::ofstream ofs(fileName);
			embedding.persist(ofs);
		}
	}
143

144
	// Add the embedding to the AcceleratorBuffer
Mccaskey, Alex's avatar
Mccaskey, Alex committed
145
	aqcBuffer->setEmbedding(embedding);
146

147
148
149
150
151
152
153
154
	// Get the ParameterSetter
	std::shared_ptr<ParameterSetter> parameterSetter;
	if (runtimeOptions->exists("dwave-parameter-setter")) {
		parameterSetter = ParameterSetterRegistry::instance()->create(
				(*runtimeOptions)["dwave-parameter-setter"]);
	} else {
		parameterSetter = ParameterSetterRegistry::instance()->create(
				"default");
155
156
	}

157
158
159
160
161
162
	// Set the parameters
	auto insts = parameterSetter->setParameters(problemGraph, hardwareGraph, embedding);

	// Add the instructions to the Kernel
	for (auto i : insts) {
		dwKernel->addInstruction(i);
163
	}
164

165
	// Create and return the IR
166
167
	auto ir = std::make_shared<DWIR>();
	ir->addKernel(dwKernel);
168
	return ir;
169
}
170

171
172
173
std::shared_ptr<IR> DWQMICompiler::compile(const std::string& src) {
	XACCError("Cannot compile D-Wave program without "
			"information about Accelerator connectivity.");
174
175
176
177
178
}

}

}