LCOV - code coverage report
Current view: top level - src/utils/emissions - CharacteristicMap.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 1 1 100.0 %
Date: 2024-05-04 15:27:10 Functions: 0 0 -

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2002-2024 German Aerospace Center (DLR) and others.
       4             : // This program and the accompanying materials are made available under the
       5             : // terms of the Eclipse Public License 2.0 which is available at
       6             : // https://www.eclipse.org/legal/epl-2.0/
       7             : // This Source Code may also be made available under the following Secondary
       8             : // Licenses when the conditions for such availability set forth in the Eclipse
       9             : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10             : // or later which is available at
      11             : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12             : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13             : /****************************************************************************/
      14             : /// @file    CharacteristicMap.h
      15             : /// @author  Kevin Badalian (badalian_k@mmp.rwth-aachen.de)
      16             : /// @date    2021-02
      17             : ///
      18             : // Characteristic map for vehicle type parameters as needed by the MMPEVEM model
      19             : // Teaching and Research Area Mechatronics in Mobile Propulsion (MMP), RWTH Aachen
      20             : /****************************************************************************/
      21             : 
      22             : 
      23             : /******************************************************************************
      24             :  * ============================= Example Usage ============================== *
      25             :  ******************************************************************************
      26             :  *                                                                            *
      27             :  * Assume a function f which maps from R^2 to R^1 according to...             *
      28             :  *                                                                            *
      29             :  *     |  0 |  1 |  2 |  3 |  4   -> x_1                                      *
      30             :  * ----|------------------------                                              *
      31             :  *  -1 |  1 |  3 |  1 | -2 |                                                  *
      32             :  *   1 |  1 | -2 | -3 |  7 |  5                                               *
      33             :  *   3 | -2 | -1 |  0 |  1 |  3                                               *
      34             :  *   5 |    |  0 |  8 |  4 |  4                                               *
      35             :  *                                                                            *
      36             :  *   |                                                                        *
      37             :  *   v                                                                        *
      38             :  *  x_2                                                                       *
      39             :  *                                                                            *
      40             :  * ... so that, for example, f(3, 1) = 7. Note that f is not defined at       *
      41             :  * (4, -1) and (0, 5). There are two ways to create a CharacteristicMap       *
      42             :  * object for this function.                                                  *
      43             :  * 1) Using the standard constructor:                                         *
      44             :  *      // Axes                                                               *
      45             :  *      std::vector<std::vector<double>> axes;                                *
      46             :  *      axes.push_back(std::vector<double>{0, 1, 2, 3, 4});  // Axis 1        *
      47             :  *      axes.push_back(std::vector<double>{-1, 1, 3, 5});    // Axis 2        *
      48             :  *      // Flattened row-major map entries                                    *
      49             :  *      std::vector<double> flattenedMap{1, 3, 1, -2, std::nan(""),           *
      50             :  *          1, -2, -3, 7, 5, -2, -1, 0, 1, 3, std::nan(""), 0, 8, 4, 4};      *
      51             :  *                                                                            *
      52             :  *      CharacteristicMap map1(2,              // Mapping from R^2...         *
      53             :  *                             1,              // ... to R^1                  *
      54             :  *                             axes,                                          *
      55             :  *                             flattenedMap);                                 *
      56             :  *                                                                            *
      57             :  * 2) Using a string-encoding of the map:                                     *
      58             :  *      CharacteristicMap map2("2,1|0,1,2,3,4;-1,1,3,5|1,3,1,-2,nan,"         *
      59             :  *          "1,-2,-3,7,5,-2,-1,0,1,3,nan,0,8,4,4");                           *
      60             :  *                                                                            *
      61             :  *    See below for an in-depth explanation of the format.                    *
      62             :  *                                                                            *
      63             :  *                                                                            *
      64             :  * To evaluate the map at, for instance, p = (2.2, 2), one must call:         *
      65             :  *   std::vector<double> res = map1.eval(std::vector<double>{2.2, 2},  // p   *
      66             :  *                                       1e-3);  // eps                       *
      67             :  *   if(std::isnan(res[0]))                                                   *
      68             :  *     std::cout << "[WARNING] Couldn't evaluate the map." << std::endl;      *
      69             :  *   else                                                                     *
      70             :  *     std::cout << "res = " << res[0] << std::endl;                          *
      71             :  *                                                                            *
      72             :  * The epsilon value is used for numerical reasons and decides how much a     *
      73             :  * point must deviate from its nearest neighbor before linear interpolation   *
      74             :  * is applied or when a point is considered outside of the map. The default   *
      75             :  * is 1e-6.                                                                   *
      76             :  *                                                                            *
      77             :  *                                                                            *
      78             :  * The string-encoding of a CharacteristicMap that maps from R^m to R^n is    *
      79             :  * formally defined as                                                        *
      80             :  *   "m,n|A_1[1],A_1[2],...,A_1[l1];A_2[1],A_2[2],...,A_2[l2];...;\           *
      81             :  *       A_m[1],A_m[2],...,A_m[lm]|\                                          *
      82             :  *       M_flat[1],M_flat[2],...,M_flat[l1*l2*...*lm]"                        *
      83             :  * where A_i[j] denotes the j-th value of the i-th axis (which has li values  *
      84             :  * total) and M_flat[i] stands for the i-th entry in the row-major flattened  *
      85             :  * map. To be more specific, given a map M, its flattened version is          *
      86             :  * computed as follows (using pseudo code):                                   *
      87             :  *   M_flat = ""                                                              *
      88             :  *   for i_m in {1,2,...,lm}:        // Last axis                             *
      89             :  *     ...                                                                    *
      90             :  *       for i_2 in {1,2,...,l2}:    // Second axis                           *
      91             :  *         for i_1 in {1,2,...,l1}:  // First axis (i.e. row axis)            *
      92             :  *           for d in {1,2,...,n}:   // Image dimensions                      *
      93             :  *             M_flat += M[i_1,i_2,...,i_m][d] + ","                          *
      94             :  *   removeTrailingComma(M_flat)                                              *
      95             :  *                                                                            *
      96             :  ******************************************************************************/
      97             : #pragma once
      98             : 
      99             : #include <vector>
     100             : #include <string>
     101             : 
     102             : 
     103             : /**
     104             :  * \class CharacteristicMap
     105             :  * \brief The purpose of this class is to store a characteristic map (German:
     106             :  *        Kennfeld) of arbitrary dimensions and to provide functions in order to
     107             :  *        evaluate/interpolate points in it.
     108             :  */
     109      276132 : class CharacteristicMap {
     110             : private:
     111             :     /// Dimension of the map's domain
     112             :     int domainDim;
     113             : 
     114             :     /// Image dimension of the map
     115             :     int imageDim;
     116             : 
     117             :     /// Vector containing the values along each domain axis in ascending order
     118             :     std::vector<std::vector<double>> axes;
     119             : 
     120             :     /// Flattened map entries
     121             :     std::vector<double> flattenedMap;
     122             : 
     123             :     /// Stride for each domain dimension in the flattened map
     124             :     std::vector<int> strides;
     125             : 
     126             :     /**
     127             :      * \brief Determine the stride for each map dimension in the flattened map.
     128             :      */
     129             :     void determineStrides();
     130             : 
     131             :     /**
     132             :      * \brief Compute the index of a map entry in the flattened map.
     133             :      *
     134             :      * \param[in] ref_idxs Non-flattened map indices
     135             :      * \returns Flattened map index
     136             :      * \throws std::runtime_error
     137             :      */
     138             :     int calcFlatIdx(const std::vector<int>& ref_idxs) const;
     139             : 
     140             :     /**
     141             :      * \brief Determine the indices of the nearest neighbor of a point in the map.
     142             :      *
     143             :      * A point has no such neighbor if it lies outside of the range of an axis
     144             :      * with respect to some epsilon.
     145             :      * \param[in] ref_p A point
     146             :      * \param[out] ref_idxs A vector into which the indices shall be written
     147             :      * \param[in] eps An epsilon value
     148             :      * \returns 0 if a nearest neighbor could be found, else -1
     149             :      * \throws std::runtime_error
     150             :      */
     151             :     int findNearestNeighborIdxs(const std::vector<double>& ref_p,
     152             :                                 std::vector<int>& ref_idxs, double eps = 1e-6) const;
     153             : 
     154             :     /**
     155             :      * \brief Access a map entry using its indices.
     156             :      *
     157             :      * \param[in] ref_idxs A vector containing indices
     158             :      * \returns A vector containing the image values of the map at the specified
     159             :      *          location
     160             :      * \throws std::runtime_error
     161             :      */
     162             :     std::vector<double> at(const std::vector<int>& ref_idxs) const;
     163             : 
     164             : 
     165             : 
     166             : public:
     167             :     /**
     168             :      * \brief Constructor
     169             :      *
     170             :      * \param[in] domainDim The map's domain dimension
     171             :      * \param[in] imageDim The map's image dimension
     172             :      * \param[in] ref_axes A vector of vectors containing the entries of their
     173             :      *            respective axes in ascending order
     174             :      * \param[in] ref_flattenedMap The row-major flattened entries of the map
     175             :      *            (i.e. the map is flattened along its first axis)
     176             :      * \throws std::runtime_error
     177             :      */
     178             :     CharacteristicMap(int domainDim, int imageDim,
     179             :                       const std::vector<std::vector<double>>& ref_axes,
     180             :                       const std::vector<double>& ref_flattenedMap);
     181             : 
     182             :     /**
     183             :      * \brief Constructor
     184             :      *
     185             :      * \param[in] ref_mapString A string representation of a characteristic map
     186             :      *            (cf. example at the top of the file)
     187             :      * throws std::runtime_error
     188             :      */
     189             :     CharacteristicMap(const std::string& ref_mapString);
     190             : 
     191             :     /**
     192             :      * \brief Encode the map as a string.
     193             :      *
     194             :      * \returns A string representation of the characteristic map (cf. example at
     195             :      *          the top of the file)
     196             :      */
     197             :     std::string toString() const;
     198             : 
     199             :     /**
     200             :      * \brief Get the dimension of the map's domain.
     201             :      *
     202             :      * \returns The domain's dimension
     203             :      */
     204             :     int getDomainDim() const;
     205             : 
     206             :     /**
     207             :      * \brief Get the image dimension of the map.
     208             :      *
     209             :      * \returns The image dimension of the characteristic map
     210             :      */
     211             :     int getImageDim() const;
     212             : 
     213             :     /**
     214             :      * \brief Evaluate a point in the map using linear interpolation.
     215             :      *
     216             :      * Please note that the result may contain NaNs. That happens when...
     217             :      * a) ... the point in question has no nearest neighbor (that is, it lies
     218             :      *    outside of the domain). In that case, all entries of the vector are set
     219             :      *    to NaN.
     220             :      * b) ... an image value of the nearest neighbor is NaN. Then, the result is
     221             :      *    also NaN in that image dimension.
     222             :      * c) ... evaluation would require interpolating with a support point which is
     223             :      *    NaN in an image dimension. The corresponding result entry is set to NaN
     224             :      *    in that case.
     225             :      * \param[in] ref_p A point
     226             :      * \param[in] eps An epsilon value
     227             :      * \returns The (interpolated) image values of the map at the specified point
     228             :      * \throws std::runtime_error
     229             :      */
     230             :     std::vector<double> eval(const std::vector<double>& ref_p,
     231             :                              double eps = 1e-6) const;
     232             : };

Generated by: LCOV version 1.14