QCOR
qcor_observable.hpp
1 #pragma once
2 
3 #include <complex>
4 #include <functional>
5 #include <memory>
6 #include <vector>
7 
8 #include "Identifiable.hpp"
9 #include "heterogeneous.hpp"
10 #include "operators.hpp"
11 #include "qcor_pimpl.hpp"
12 #include "qcor_utils.hpp"
13 
14 namespace qcor {
15 
16 using namespace tao::operators;
17 
18 // This class implements the QCOR specification Operator concept.
19 // It can be created from a string representation, or via the provided
20 // algebraic API. It is intended to be polymorphic in Operator type, i.e.
21 // it can be a Spin (Pauli) operator, Fermion operator, etc.
22 // Clients can use this by value, and operate on it algebraically with othe r
23 // instances of the same underlying type.
24 class Operator
25  : public commutative_ring<Operator>,
26  public equality_comparable<Operator>,
27  public commutative_multipliable<Operator, double>,
28  public commutative_multipliable<Operator, std::complex<double>> {
29  private:
30  class OperatorImpl;
31  qcor_pimpl<OperatorImpl> m_internal;
32 
33  public:
34 
35  // Construct from underlying type name + config options, from string-like
36  // representation (e.g. 'X0 Y1 + Y0 Y1')
37  Operator(const std::string &name, xacc::HeterogeneousMap &options);
38  Operator(const std::string &type, const std::string &expr);
39  Operator(const OperatorImpl &&impl);
40  Operator(const Operator &i);
41  Operator &operator=(const Operator &);
42  Operator();
43  ~Operator();
44 
45  // Transform this operator using the OperatorTransform corresponding to the
46  // key type
47  Operator transform(const std::string &type, xacc::HeterogeneousMap m = {});
48 
49  // Return as an opaque Identifiable type. Clients should be able
50  // to cast this to an xacc Observable
51  std::shared_ptr<xacc::Identifiable> get_as_opaque();
52 
53  // Algebraic API
54  Operator &operator+=(const Operator &v) noexcept;
55  Operator &operator-=(const Operator &v) noexcept;
56  Operator &operator*=(const Operator &v) noexcept;
57  bool operator==(const Operator &v) noexcept;
58  Operator &operator*=(const double v) noexcept;
59  Operator &operator*=(const std::complex<double> v) noexcept;
60 
61  // Query the number of bits
62  int nQubits();
63  int nBits() { return nQubits(); }
64 
65  // Observe the given CompositeInstruction to produce a vector
66  // of CompositeInstructions measured according to this Operator
67  std::vector<std::shared_ptr<CompositeInstruction>> observe(
68  std::shared_ptr<CompositeInstruction> function);
69 
70  // Retrieve all Operator sub-terms as individual Operators
71  std::vector<Operator> getSubTerms();
72 
73  // Get all sub-terms, excluding the Identity sub-term
74  std::vector<Operator> getNonIdentitySubTerms();
75 
76  // Get the Identity sub-term
77  Operator getIdentitySubTerm();
78 
79  // True if this Operator has an identity sub-term
80  bool hasIdentitySubTerm();
81 
82  // Return a string representation of this Operator
83  std::string toString() const;
84 
85  // Return the coefficient on this Operator (throws an error
86  // if there are more than 1 terms in this Operator)
87  std::complex<double> coefficient();
88 
89  // Produce (zv,xv) binary representation whereby for all i in (0,nqubits-1)
90  // zv[i] == xv[i] == 1 -> Y on qubit i, zv[i] == 1, xv[i] == 0 -> Z on qubit i
91  // and xv[i] == 1, zv[i] == 0 -> X on qubit i
92  std::pair<std::vector<int>, std::vector<int>> toBinaryVectors(
93  const int nQubits);
94 
95  // Map qubit sites to a new set of qubits
96  void mapQubitSites(std::map<int, int> &siteMap);
97 
98  // Internal class describing a sparse matrix element
100  : std::tuple<std::uint64_t, std::uint64_t, std::complex<double>> {
101  public:
102  SparseElement(std::uint64_t r, std::uint64_t c,
103  std::complex<double> coeff) {
104  std::get<0>(*this) = r;
105  std::get<1>(*this) = c;
106  std::get<2>(*this) = coeff;
107  }
108  std::uint64_t row() { return std::get<0>(*this); }
109  std::uint64_t col() { return std::get<1>(*this); }
110  const std::complex<double> coeff() { return std::get<2>(*this); }
111  };
112 
113  // Generate a sparse matrix representation of this Operator
114  std::vector<SparseElement> to_sparse_matrix();
115 
116  // Compute the commutator of this operator with the given one.
117  Operator commutator(Operator &);
118 };
119 
120 void __internal_exec_observer(
121  xacc::AcceleratorBuffer *,
122  std::vector<std::shared_ptr<CompositeInstruction>>);
123 
124 // Convenience functions for constructing Pauli operators
125 Operator X(int idx);
126 Operator Y(int idx);
127 Operator Z(int idx);
128 Operator SP(int idx);
129 Operator SM(int idx);
130 Operator allZs(const int nQubits);
131 
132 // Convenience functions for constructing Fermioon operators
133 Operator adag(int idx);
134 Operator a(int idx);
135 
136 // // Expose extra algebra needed for pauli operators
137 Operator operator+(double coeff, Operator op);
138 Operator operator+(Operator op, double coeff);
139 Operator operator-(double coeff, Operator op);
140 Operator operator-(Operator op, double coeff);
141 
142 Eigen::MatrixXcd get_dense_matrix(Operator &op);
143 
144 // Observe the given kernel, and return the expected value
145 double observe(std::shared_ptr<CompositeInstruction> program, Operator &obs,
147 
148 namespace __internal__ {
149 // Observe the kernel and return the measured kernels
150 std::vector<std::shared_ptr<CompositeInstruction>> observe(
151  Operator &obs, std::shared_ptr<CompositeInstruction> program);
152 
153 // Keep track of all created Operators in this translation unit
154 extern std::map<std::size_t, Operator> cached_observables;
155 
156 } // namespace __internal__
157 
158 Operator _internal_python_createObservable(const std::string &name,
159  const std::string &repr);
160 
161 // Public QCOR Specification API for Operator creation (we retain the name Observable
162 // for backwards compatibility)
163 Operator createObservable(const std::string &repr);
164 Operator createObservable(const std::string &name, const std::string &repr);
165 Operator createOperator(const std::string &repr);
166 Operator createOperator(const std::string &name, const std::string &repr);
167 Operator createOperator(const std::string &name, HeterogeneousMap &&options);
168 Operator createOperator(const std::string &name, HeterogeneousMap &options);
169 
170 // Transform the given Operator
171 Operator operatorTransform(const std::string &type, Operator &op);
172 
173 
174 } // namespace qcor
175 
176 // Print Operators to ostreams
177 std::ostream &operator<<(std::ostream &os, qcor::Operator const &m);
qcor::Operator
Definition: qcor_observable.hpp:24
qcor::qcor_pimpl
Definition: qcor_pimpl.hpp:7
qcor::Operator::SparseElement
Definition: qcor_observable.hpp:99
qcor
Definition: qcor_syntax_handler.cpp:15
qcor::Operator::OperatorImpl
Definition: qcor_observable.cpp:27
xacc::internal_compiler::qreg
Definition: qalloc.hpp:101