47 if (
static_cast<int>(ref_idxs.size()) !=
domainDim) {
48 throw std::runtime_error(
"The number of indices differs from the map's"
49 " domain dimension.");
54 if (ref_idxs[i] < 0) {
55 throw std::runtime_error(
"The argument indices aren't non-negative.");
57 flatIdx += ref_idxs[i] *
strides[i];
65 std::vector<int>& ref_idxs,
double eps)
const {
66 if (
static_cast<int>(ref_p.size()) !=
domainDim) {
67 throw std::runtime_error(
"The argument point's size doesn't match the"
68 " domain dimension.");
71 ref_idxs = std::vector<int>(
domainDim, -1);
73 if (
axes[i][0] - eps <= ref_p[i] && ref_p[i] <
axes[i][0]) {
75 }
else if (
axes[i][
axes[i].size() - 1] <= ref_p[i]
76 && ref_p[i] <
axes[i][
axes[i].size() - 1] + eps) {
77 ref_idxs[i] = (int)
axes[i].size() - 1;
79 for (
int j = 0; j < static_cast<int>(
axes[i].size()) - 1; j++) {
80 if (
axes[i][j] <= ref_p[i] && ref_p[i] <
axes[i][j + 1]) {
82 if (ref_p[i] -
axes[i][j] <=
axes[i][j + 1] - ref_p[i]) {
94 if (ref_idxs[i] == -1) {
105 if (
static_cast<int>(ref_idxs.size()) !=
domainDim) {
106 throw std::runtime_error(
"The number of indices differs from the map's"
107 " domain dimension.");
111 return std::vector<double>(
flattenedMap.begin() + flatIdx,
117 const std::vector<std::vector<double>>& ref_axes,
118 const std::vector<double>& ref_flattenedMap)
119 : domainDim(domainDim),
122 flattenedMap(ref_flattenedMap) {
125 throw std::runtime_error(
"The number of axes doesn't match the specified"
126 " domain dimension.");
129 for (
auto& ref_axis :
axes) {
130 expectedEntryCnt *= (int)ref_axis.size();
132 if (
static_cast<int>(
flattenedMap.size()) != expectedEntryCnt) {
133 throw std::runtime_error(
"The number of map entries isn't equal to the"
134 " product of the axes' dimensions times the image dimension.");
144 if (tokens.size() != 3) {
145 throw std::runtime_error(
"The map string isn't made up of the 3 parts"
146 " dimensions, axes, and flattened entries.");
151 if (dimensionTokens.size() != 2) {
152 throw std::runtime_error(
"The domain and image dimensions aren't specified"
155 domainDim = std::stoi(dimensionTokens[0]);
156 imageDim = std::stoi(dimensionTokens[1]);
160 if (
static_cast<int>(axisTokens.size()) !=
domainDim) {
161 throw std::runtime_error(
"The number of axes doesn't match the specified"
162 " domain dimension.");
164 for (
auto& ref_axisToken : axisTokens) {
166 std::vector<double> axisEntries;
167 for (
auto& ref_axisEntryToken : axisEntryTokens) {
168 axisEntries.push_back(std::stod(ref_axisEntryToken));
170 axes.push_back(axisEntries);
176 for (
auto& ref_axis :
axes) {
177 expectedEntryCnt *= (int)ref_axis.size();
179 if (
static_cast<int>(flattenedMapTokens.size()) != expectedEntryCnt) {
180 throw std::runtime_error(
"The number of map entries isn't equal to the"
181 " product of the axes' dimensions times the image dimension.");
184 for (
auto& ref_flattenedMapToken : flattenedMapTokens) {
185 flattenedMap.push_back(std::stod(ref_flattenedMapToken));
195 std::string mapString = std::to_string(
domainDim) +
","
199 for (
int i = 0; i < static_cast<int>(
axes.size()); i++) {
200 for (
int j = 0; j < static_cast<int>(
axes[i].size()); j++) {
201 mapString += std::to_string(
axes[i][j])
202 + (j ==
static_cast<int>(
axes[i].size()) - 1 ?
"" :
",");
204 mapString += (i ==
static_cast<int>(
axes.size()) - 1 ?
"|" :
";");
208 for (
int i = 0; i < static_cast<int>(
flattenedMap.size()); i++) {
210 + (i ==
static_cast<int>(
flattenedMap.size()) - 1 ?
"" :
",");
231 if (
static_cast<int>(ref_p.size()) !=
domainDim) {
232 throw std::runtime_error(
"The argument's size doesn't match the domain"
237 std::vector<int> nnIdxs;
239 return std::vector<double>(
imageDim, std::stod(
"nan"));
242 const std::vector<double> y_nn =
at(nnIdxs);
244 std::vector<double> y = y_nn;
250 const double s = ref_p[i] -
axes[i][nnIdxs[i]];
251 if (std::abs(s) <= eps) {
254 bool b_constellation1 = s < 0 && nnIdxs[i] > 0;
255 bool b_constellation2 = s >= 0
256 && nnIdxs[i] ==
static_cast<int>(
axes[i].size()) - 1
258 bool b_constellation3 = s < 0 && nnIdxs[i] == 0
259 && nnIdxs[i] <
static_cast<int>(
axes[i].size()) - 1;
260 bool b_constellation4 = s >= 0
261 && nnIdxs[i] <
static_cast<int>(
axes[i].size()) - 1;
265 std::vector<int> anIdxs = nnIdxs;
266 if (b_constellation1 || b_constellation2) {
268 dx =
axes[i][nnIdxs[i]] -
axes[i][anIdxs[i]];
269 }
else if (b_constellation3 || b_constellation4) {
271 dx =
axes[i][anIdxs[i]] -
axes[i][nnIdxs[i]];
276 const std::vector<double> y_an =
at(anIdxs);
278 for (
int j = 0; j <
imageDim; j++) {
280 if (b_constellation1 || b_constellation2) {
281 dy = y_nn[j] - y_an[j];
283 dy = y_an[j] - y_nn[j];
int imageDim
Image dimension of the map.
int calcFlatIdx(const std::vector< int > &ref_idxs) const
Compute the index of a map entry in the flattened map.
std::vector< int > strides
Stride for each domain dimension in the flattened map.
std::vector< double > flattenedMap
Flattened map entries.
std::vector< double > eval(const std::vector< double > &ref_p, double eps=1e-6) const
Evaluate a point in the map using linear interpolation.
int getDomainDim() const
Get the dimension of the map's domain.
std::vector< std::vector< double > > axes
Vector containing the values along each domain axis in ascending order.
int findNearestNeighborIdxs(const std::vector< double > &ref_p, std::vector< int > &ref_idxs, double eps=1e-6) const
Determine the indices of the nearest neighbor of a point in the map.
void determineStrides()
Determine the stride for each map dimension in the flattened map.
std::vector< double > at(const std::vector< int > &ref_idxs) const
Access a map entry using its indices.
int domainDim
Dimension of the map's domain.
std::string toString() const
Encode the map as a string.
CharacteristicMap(int domainDim, int imageDim, const std::vector< std::vector< double > > &ref_axes, const std::vector< double > &ref_flattenedMap)
Constructor.
int getImageDim() const
Get the image dimension of the map.
std::vector< std::string > getVector()
return vector of strings