Maestro 0.2.11
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
HermiteInterpolation.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#ifndef __UTILS_HERMITE_INTERPOLATION_H__
13#define __UTILS_HERMITE_INTERPOLATION_H__
14
15#include <vector>
16#include <boost/math/interpolators/pchip.hpp>
17
19
20namespace Utils {
21
23 public:
24 template <typename T = size_t>
25 void SetSamples(const std::vector<T>& x, const std::vector<double>& y) {
26 assert(x.size() == y.size());
27 assert(!x.empty());
28 if (x.empty() || y.empty()) return;
29
30 spline.reset();
31
32 std::vector<double> xvals(x.begin(), x.end());
33 std::vector<double> yvals = y;
34 x1 = xvals.front();
35 x2 = xvals.back();
36 y1 = yvals.front();
37 y2 = yvals.back();
38
39 if (xvals.size() == 1)
40 slopel = sloper = 0;
41 else {
42 slopel = (yvals[1] - y1) / (xvals[1] - x1);
43 sloper = (y2 - yvals[yvals.size() - 2]) / (x2 - xvals[xvals.size() - 2]);
44 }
45
46
47 bool fallbackToLinear = false;
48
49 // needs 4 values to work, if we don't have them,
50 // fallback to linear
51 if (xvals.size() < 4) fallbackToLinear = true;
52 else {
53 // check the xvals to ensure they are strictly increasing, otherwise the
54 // pchip interpolator will throw an exception
55 // if that's the case, fallback to linear
56
57 for (size_t i = 1; i < xvals.size(); ++i)
58 if (xvals[i] <= xvals[i - 1]) {
59 fallbackToLinear = true;
60 break;
61 }
62 }
63
64 if (fallbackToLinear) {
65 linearExtrapolation = std::make_unique<SimpleLinearRegression<double, double>>();
66 linearExtrapolation->SetTrueLinearRegression(trueInterpolation);
67
68 size_t offset = 0;
69 for (size_t i = 0; i < xvals.size(); ++i) {
70 if (xvals[i] > 1E-12) {
71 offset = i;
72 break;
73 }
74 }
75
76 if (offset > 0) {
77 xvals.erase(xvals.begin(), xvals.begin() + offset);
78 yvals.erase(yvals.begin(), yvals.begin() + offset);
79 }
80
81 linearExtrapolation->SetSamples(xvals, yvals);
82 return;
83 }
84
85 spline = std::make_unique<
86 boost::math::interpolators::pchip<std::vector<double>>>(
87 std::move(xvals), std::move(yvals));
88 }
89
90 double Predict(double x) const {
91 double result = 0;
92
93 const bool smallx = x <= x1;
94 const bool largex = x >= x2;
95 if (smallx || largex) {
96 if (smallx) {
97 if (slopel == 0)
98 result = y1;
99 else
100 result = y1 + slopel * (x - x1);
101 } else {
102 if (sloper == 0)
103 result = y2;
104 else
105 result = y2 + sloper * (x - x2);
106 }
107 } else if (spline) {
108 result = (*spline)(x);
109 } else if (linearExtrapolation) {
110 result = linearExtrapolation->Predict(x);
111 } else {
112 const double slope = (y2 - y1) / (x2 - x1);
113 result = y1 + slope * (x - x1);
114 }
115
116 if (trueInterpolation) return result;
117
118 const auto m = 1E-12;
119 if (result < m) return m;
120
121 return result;
122 }
123
124 void SetTrueInterpolation(bool reg) {
125 trueInterpolation = reg;
126 if (linearExtrapolation)
127 linearExtrapolation->SetTrueLinearRegression(trueInterpolation);
128 }
129
130 private:
131 std::unique_ptr<boost::math::interpolators::pchip<std::vector<double>>>
132 spline;
133 std::unique_ptr<SimpleLinearRegression<double, double>> linearExtrapolation;
134
135 double x1 = 0;
136 double x2 = 0;
137 double y1 = 0;
138 double y2 = 0;
139 double slopel = 0;
140 double sloper = 0;
141
142 //static constexpr double divisor = 8;
143 double minValue = 0;
144 bool trueInterpolation = false;
145};
146
147} // namespace Utils
148
149#endif // __UTILS_HERMITE_INTERPOLATION_H__
double Predict(double x) const
void SetSamples(const std::vector< T > &x, const std::vector< double > &y)
Definition Alias.h:22