LCOV - code coverage report
Current view: top level - src/foreign/RoutingKit/include/routingkit - permutation.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 92.7 % 41 38
Test Date: 2026-09-23 15:43:02 Functions: 100.0 % 7 7

            Line data    Source code
       1              : #ifndef ROUTING_KIT_PERMUTATION_H
       2              : #define ROUTING_KIT_PERMUTATION_H
       3              : 
       4              : #include <routingkit/constants.h>
       5              : 
       6              : #include <vector>
       7              : #include <assert.h>
       8              : #include <algorithm>
       9              : 
      10              : namespace RoutingKit{
      11              : 
      12              : //
      13              : //  Applying a permutation p to a vector v consists of computing the vector {v[p[0]], v[p[1]], v[p[2]], ... , v[p[n]]}
      14              : //
      15              : //  Applying a permutation p to the elements of a vector v consists of computing the vector {p[v[0]], p[v[1]], p[v[2]], ... , p[v[n]]}
      16              : //
      17              : 
      18              : inline
      19              : bool is_permutation(const std::vector<unsigned>&p){
      20              :         std::vector<bool>found(p.size(), false);
      21              :         for(unsigned x:p){
      22              :                 if(x >= p.size())
      23              :                         return false;
      24              :                 if(found[x])
      25              :                         return false;
      26              :                 found[x] = true;
      27              :         }
      28              :         return true;
      29              : }
      30              : 
      31              : inline
      32        10595 : std::vector<unsigned>chain_permutation_first_left_then_right(const std::vector<unsigned>&p, const std::vector<unsigned>&q){
      33              :         assert(is_permutation(p) && "p must be a permutation");
      34              :         assert(is_permutation(q) && "q must be a permutation");
      35              :         assert(p.size() == q.size() && "p and q must permute the same number of objects");
      36        10595 :         std::vector<unsigned>r(p.size());
      37       632419 :         for(unsigned i=0; i<r.size(); ++i)
      38       621824 :                 r[i] = p[q[i]];
      39        10595 :         return r;
      40              : }
      41              : 
      42              : inline
      43              : std::vector<unsigned>chain_permutation_first_right_then_left(const std::vector<unsigned>&p, const std::vector<unsigned>&q){
      44              :         return chain_permutation_first_left_then_right(q, p);
      45              : }
      46              : 
      47              : template<class T>
      48          849 : std::vector<T> apply_permutation(const std::vector<unsigned>&p, const std::vector<T>&v){
      49              :         assert(is_permutation(p) && "p must be a permutation");
      50              :         assert(p.size() == v.size() && "permutation and vector must have the same size");
      51              : 
      52          849 :         std::vector<T>r(v.size());
      53        35089 :         for(unsigned i = 0; i<v.size(); ++i)
      54        34240 :                 r[i] = v[p[i]];
      55              : 
      56          849 :         return r; // NVRO
      57              : }
      58              : 
      59              : template<class T>
      60         4245 : std::vector<T> apply_permutation(const std::vector<unsigned>&p, std::vector<T>&&v){
      61              :         assert(is_permutation(p) && "p must be a permutation");
      62              :         assert(p.size() == v.size() && "permutation and vector must have the same size");
      63              : 
      64         4245 :         std::vector<T>r(v.size());
      65       421355 :         for(unsigned i = 0; i<v.size(); ++i)
      66       417110 :                 r[i] = std::move(v[p[i]]);
      67              : 
      68         4245 :         return r; // NVRO
      69              : }
      70              : 
      71              : template<class T>
      72        26253 : std::vector<T> apply_inverse_permutation(const std::vector<unsigned>&p, const std::vector<T>&v){
      73              :         assert(is_permutation(p) && "p must be a permutation");
      74              :         assert(p.size() == v.size() && "permutation and vector must have the same size");
      75              : 
      76        26253 :         std::vector<T>r(v.size());
      77       831563 :         for(unsigned i = 0; i<v.size(); ++i)
      78       805310 :                 r[p[i]] = v[i];
      79              : 
      80        26253 :         return r; // NVRO
      81              : }
      82              : 
      83              : template<class T>
      84        22039 : std::vector<T> apply_inverse_permutation(const std::vector<unsigned>&p, std::vector<T>&&v){
      85              :         assert(is_permutation(p) && "p must be a permutation");
      86              :         assert(p.size() == v.size() && "permutation and vector must have the same size");
      87              : 
      88        22039 :         std::vector<T>r(v.size());
      89      1033267 :         for(unsigned i = 0; i<v.size(); ++i)
      90      1011228 :                 r[p[i]] = std::move(v[i]);
      91              : 
      92        22039 :         return r; // NVRO
      93              : }
      94              : 
      95              : inline
      96              : void inplace_apply_permutation_to_elements_of(const std::vector<unsigned>&p, std::vector<unsigned>&v){
      97              :         assert(is_permutation(p) && "p must be a permutation");
      98              :         assert(std::all_of(v.begin(), v.end(), [&](unsigned x){return x < p.size();}) && "v has an out of bounds element");
      99              :         
     100       707908 :         for(unsigned i=0; i<v.size(); ++i)
     101       688852 :                 v[i] = p[v[i]];
     102              : }
     103              : 
     104              : inline
     105         1698 : std::vector<unsigned> apply_permutation_to_elements_of(const std::vector<unsigned>&p, const std::vector<unsigned>&v){
     106              :         assert(is_permutation(p) && "p must be a permutation");
     107              :         assert(std::all_of(v.begin(), v.end(), [&](unsigned x){return x < p.size();}) && "v has an out of bounds element");
     108              :         
     109         1698 :         std::vector<unsigned> r = v;
     110              :         inplace_apply_permutation_to_elements_of(p, r);
     111         1698 :         return r; // NVRO
     112              : }
     113              : 
     114              : 
     115              : inline
     116              : void inplace_apply_permutation_to_possibly_invalid_elements_of(const std::vector<unsigned>&p, std::vector<unsigned>&v){
     117              :         assert(is_permutation(p) && "p must be a permutation");
     118              :         assert(std::all_of(v.begin(), v.end(), [&](unsigned x){return x < p.size() || x == invalid_id;}) && "v has an out of bounds element");
     119              :         
     120            0 :         for(unsigned i=0; i<v.size(); ++i)
     121            0 :                 if(v[i] != invalid_id)
     122            0 :                         v[i] = p[v[i]];
     123              : }
     124              : 
     125              : inline
     126              : std::vector<unsigned> apply_permutation_to_possibly_invalid_elements_of(const std::vector<unsigned>&p, const std::vector<unsigned>&v){
     127              :         assert(is_permutation(p) && "p must be a permutation");
     128              :         assert(std::all_of(v.begin(), v.end(), [&](unsigned x){return x < p.size() || x == invalid_id;}) && "v has an out of bounds element");
     129              :         
     130              :         std::vector<unsigned> r = v;
     131              :         inplace_apply_permutation_to_elements_of(p, r);
     132              :         return r; // NVRO
     133              : }
     134              : 
     135              : 
     136              : inline
     137          849 : std::vector<unsigned> invert_permutation(const std::vector<unsigned>&p){
     138              :         assert(is_permutation(p) && "p must be a permutation");
     139              :         
     140          849 :         std::vector<unsigned> inv_p(p.size());
     141        16332 :         for(unsigned i=0; i<p.size(); ++i)
     142        15483 :                 inv_p[p[i]] = i;
     143              :         
     144          849 :         return inv_p; // NVRO
     145              : }
     146              : 
     147              : inline
     148              : std::vector<unsigned> identity_permutation(unsigned n){
     149        56709 :         std::vector<unsigned> p(n);
     150       580800 :         for(unsigned i=0; i<n; ++i)
     151       524091 :                 p[i] = i;
     152              :         return p; // NVRO
     153              : }
     154              : 
     155              : template<class RandomGenerator>
     156              : std::vector<unsigned> random_permutation(unsigned n, RandomGenerator&&gen){
     157              :         auto r = identity_permutation(n);
     158              :         std::shuffle(r.begin(), r.end(), std::forward<RandomGenerator>(gen));
     159              :         return r;
     160              : }
     161              : 
     162              : } // RoutingKit
     163              : 
     164              : #endif
     165              : 
        

Generated by: LCOV version 2.0-1