Instruction.hpp 7.62 KB
Newer Older
1
/*******************************************************************************
2
 * Copyright (c) 2019 UT-Battelle, LLC.
3
4
5
6
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompanies this
 * distribution. The Eclipse Public License is available at
7
8
 * http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
 *License is available at https://eclipse.org/org/documents/edl-v10.php
9
10
 *
 * Contributors:
11
12
 *   Alexander J. McCaskey - initial API and implementation
 *******************************************************************************/
13
14
#ifndef XACC_IR_INSTRUCTION_HPP_
#define XACC_IR_INSTRUCTION_HPP_
15
#include <memory>
16

Mccaskey, Alex's avatar
Mccaskey, Alex committed
17
#include "Cloneable.hpp"
18
#include "InstructionVisitor.hpp"
19
#include "heterogeneous.hpp"
20
#include <limits>
21
22

namespace xacc {
23
using InstructionParameter = Variant<int, double, std::string>;
Nguyen, Thien Minh's avatar
Nguyen, Thien Minh committed
24
25

// Util func to get a double parameter from an InstructionParameter variant.
26
27
28
29
30
// Note: most of the cases, we have double-type parameters (e.g. rotation
// angles). This also handles int->double and string->double conversion if
// necessary.
static double
InstructionParameterToDouble(const xacc::InstructionParameter &in_parameter) {
Nguyen, Thien Minh's avatar
Nguyen, Thien Minh committed
31
32
33
34
35
36
37
  if (in_parameter.which() == 0) {
    // Convert int to double
    return static_cast<double>(in_parameter.as<int>());
  } else if (in_parameter.which() == 1) {
    return in_parameter.as<double>();
  } else {
    // Check if this string parameter can be converted to a double
38
39
40
    const auto isNumber = [](const std::string &in_string,
                             double &out_double) -> bool {
      char *end = 0;
Nguyen, Thien Minh's avatar
Nguyen, Thien Minh committed
41
42
      double val = strtod(in_string.c_str(), &end);
      // This whole string must be a valid double number
43
44
45
      const bool isConversionOkay =
          (end != in_string.c_str()) && (*end == '\0') &&
          (val != std::numeric_limits<double>::infinity());
Nguyen, Thien Minh's avatar
Nguyen, Thien Minh committed
46
47
48
      if (isConversionOkay) {
        out_double = val;
      }
49

Nguyen, Thien Minh's avatar
Nguyen, Thien Minh committed
50
51
      return isConversionOkay;
    };
52

Nguyen, Thien Minh's avatar
Nguyen, Thien Minh committed
53
54
    const std::string paramString = in_parameter.toString();
    double paramDouble = 0.0;
55
    if (isNumber(paramString, paramDouble)) {
Nguyen, Thien Minh's avatar
Nguyen, Thien Minh committed
56
57
58
      return paramDouble;
    }
  }
59

Nguyen, Thien Minh's avatar
Nguyen, Thien Minh committed
60
61
62
63
  // Cannot find a way to convert, returns 0.0
  return 0.0;
}

64
class CompositeInstruction;
65

66
67
class CompositeArgument {
public:
68
69
70
  std::string name;
  std::string type;
  HeterogeneousMap runtimeValue;
71
72
73
74
75
76
77
  CompositeArgument(const std::string n, const std::string t)
      : name(n), type(t) {}
  CompositeArgument(const std::string n, const std::string t,
                    HeterogeneousMap &map)
      : name(n), type(t), runtimeValue(map) {}
  CompositeArgument(const CompositeArgument &other)
      : name(other.name), type(other.type), runtimeValue(other.runtimeValue) {}
78
79
80
81
};

const std::string INTERNAL_ARGUMENT_VALUE_KEY = "__xacc_internal_value_key";

82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// The Instruction interface exposes an API for describing a general
// post-Moore's law low-level assembly instruction. Each Instruction
// exposes a unique string name, the vector of bit indices that it operates on,
// and a vector of InstructionParameters describing any runtime
// parameters (like rotation angle for a gate-model quantum computing
// instruction) that it requires. Clients can get the name of the
// Instruction, get and set the bits it operates on, and get and set
// any of the InstructionParameters it exposes.
//
// Instructions can be enabled or disabled, and expose whether
// it is composite or not (see CompositeInstruction).
//
// Instructions are Cloneable, which is required for use with the
// xacc service registry. Therefore, all Instructions are meant to
// be provided services within the XACC framework, making it easy
// to inject new instructions to an existing framework install.
//
// Instruction can be visited, enabling type-specific information
// at runtime to custom InstructionVisitors.
Mccaskey, Alex's avatar
Mccaskey, Alex committed
101
102
103
class Instruction : public BaseInstructionVisitable,
                    public Identifiable,
                    public Cloneable<Instruction> {
104
105
protected:
  HeterogeneousMap metadata;
106

107
public:
108
109
110
111
112
113
114
115
116
  // Instructions can carry domain-specific metadata as a 
  // key-value dictionary of information. Here we provide 
  // a method for attaching metadata
  virtual void attachMetadata(HeterogeneousMap&& m) {
    metadata = m;
  }
  // Retrieve this intruction's metadata. 
  virtual HeterogeneousMap getMetadata() {return metadata;}

117
118
119
120
  virtual void applyRuntimeArguments() = 0;
  virtual void addArgument(std::shared_ptr<CompositeArgument> arg,
                           const int idx_of_inst_param) = 0;

121
122
123
124
125
126
  // This method is a helper for associating InstructionParameter indices 
  // to other indices like std::vector<double> indices. Does nothing here
  // to be implemented by subclasses.
  virtual void addIndexMapping(const int idx_1, const int idx_2) {
      return;
  }
127
128
  virtual const std::string toString() = 0;

129
130
131
  virtual const std::vector<std::size_t> bits() = 0;
  virtual void setBits(const std::vector<std::size_t> bits) = 0;
  virtual void mapBits(std::vector<std::size_t> bitMap) = 0;
132

133
134
135
  // For the case where the bit indices for this Instruction are
  // some general expression, Clients should set the bit to -1 and provide
  // the bit expression as a string. The example here would be
136
137
138
139
  // H(q[i]) (bit_idx=0, expr=i), or C(q[i],q[i+1]) (bit_idx=0, expr=i and
  // bit_idx=1,expr=i+1)
  virtual void setBitExpression(const std::size_t bit_idx,
                                const std::string expr) = 0;
140
141
  virtual std::string getBitExpression(const std::size_t bit_idx) = 0;

142
143
144
145
146
147
148
  // Return the name of the AcceleratorBuffer that this
  // Instruction operates on at the given bitIdx. E.g.
  // CX(q[0], r[1]), this would return 'q' for bit 0 and 'r'
  // for bit 1
  // Additionally, set enables one to provide these buffer names
  // input vector should be same size as bits()
  virtual std::string getBufferName(const std::size_t bitIdx) = 0;
149
  virtual std::vector<std::string> getBufferNames() = 0;
150
151
  virtual void
  setBufferNames(const std::vector<std::string> bufferNamesPerIdx) = 0;
152

153
154
  virtual const InstructionParameter
  getParameter(const std::size_t idx) const = 0;
155
156
  virtual std::vector<InstructionParameter> getParameters() = 0;

157
158
159
160
  virtual void setParameter(const std::size_t idx,
                            InstructionParameter &inst) = 0;
  virtual void setParameter(const std::size_t idx,
                            InstructionParameter &&inst) {
161
162
    setParameter(idx, inst);
  }
163
164
165
166
167
168

  virtual const int nParameters() = 0;
  virtual bool isParameterized() { return false; }

  virtual bool isComposite() { return false; }

169
  // The following accomadate pulse-level instructions
170
171
172
  virtual std::string channel() { return "default"; }
  virtual void setChannel(const std::string ch) { return; }
  virtual std::size_t start() { return 0; }
173
174
175
  virtual void setStart(const std::size_t s) { return; }
  virtual std::size_t duration() { return 0; }
  virtual void setDuration(const std::size_t d) { return; }
176
177
178
179
  virtual void setSamples(const std::vector<std::vector<double>> samples) {
    return;
  }
  virtual std::vector<std::vector<double>> getSamples() { return {}; }
180
181
  virtual void setPulseParams(const HeterogeneousMap &in_pulseParams) {}
  virtual HeterogeneousMap getPulseParams() { return {}; }
182
183

  // The following accomodate conditional instructions
184
185
186
187
  virtual bool isEnabled() { return true; }
  virtual void disable() {}
  virtual void enable() {}

188
  virtual void customVisitAction(BaseInstructionVisitor &visitor) {
189
    /* do nothing at this level */
190
  }
191
192

  virtual const bool isAnalog() const { return false; }
193
  virtual const int nRequiredBits() const = 0;
194

195
  virtual ~Instruction() {}
196
197
};

198
} // namespace xacc
199
#endif