Ignore:
Timestamp:
04/01/21 17:07:37 (3 years ago)
Author:
Maciej Komosinski
Message:

Used a local random number generator for full determinism. Introduced a few refactorings for better performance.

Location:
cpp/frams/model/similarity
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/model/similarity/measure-distribution.cpp

    r1062 r1120  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2021  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    1515                { "simil_density", 0, 0, "Density of surface sampling", "f 1 100 10", FIELD(density), "", },
    1616                { "simil_bin_num", 0, 0, "Number of bins", "d 1 1000 128", FIELD(bin_num), "", },
    17                 { "simil_samples_num", 0, 0, "Number of samples", "d 1 1048576 1048576", FIELD(samples_num), "", },
     17                { "simil_samples_num", 0, 0, "Number of samples", "d 1 1048576 10000", FIELD(samples_num), "", }, //based on experiments, not much accuracy to gain when this is increased above 1000
    1818                { "evaluateDistance", 0, PARAM_DONTSAVE | PARAM_USERHIDDEN, "Evaluate model dissimilarity", "p f(oGeno,oGeno)", PROCEDURE(p_evaldistance), "Calculates dissimilarity between two models created from Geno objects.", },
    1919                { 0, },
     
    3737                        funs[i][j] = std::make_pair(0, 0);
    3838        }
    39        
     39
    4040        for (int i = 0; i < 2; i++)
    4141                sst_models[i] = new SolidsShapeTypeModel((*models[i]));
    42        
    43         SimilMeasureDistribution::calculateFuns();     
     42
     43        SimilMeasureDistribution::calculateFuns();
    4444        dist = SimilMeasureDistribution::compareFuns();
    45        
     45
    4646        for (int i = 0; i < 2; i++)
    4747        {
     
    6060                        return -1;
    6161                }
    62        
     62
    6363        density = params.at(0);
    6464        bin_num = params.at(1);
    6565        samples_num = params.at(2);
    66        
     66
    6767        return 0;
    6868}
    6969
    70 void SimilMeasureDistribution::calculateFun(std::pair<double, float> *fun, Model &sampled)
     70void SimilMeasureDistribution::calculateFun(std::pair<double, float> *fun, const Model &sampled)
    7171{
    7272        int size = sampled.getPartCount();
     
    7575        //Check if total number of points pairs is smaller than samples number
    7676        //but first, prevent exceeding int limits
    77         if (size < (int) sqrt((double) std::numeric_limits<int>::max()))
    78                 samples_taken = min(samples_num, size*size);
     77        //if (size < (int) sqrt((double) std::numeric_limits<int>::max()))
     78        //      samples_taken = min(samples_num, size*size);
     79
     80        rndgen.seed(55); //For determinism. Otherwise the descriptors (that choose samples pseudo-randomly) for the same Model can yield different values and so the dissimilarity between the object and its copy will not be 0.
     81        std::uniform_int_distribution<> uniform_distrib(0, sampled.getPartCount() - 1);
    7982
    8083        //Get sampled distribution
    81         std::vector<double> dist_vect = (this->*SimilMeasureDistribution::distribution_fun)(samples_taken, &sampled);
     84        std::vector<double> dist_vect;
     85        dist_vect.reserve(samples_taken); //we will add up to samples_taken elements to this vector
     86        (this->*SimilMeasureDistribution::distribution_fun)(samples_taken, uniform_distrib, sampled, dist_vect);
    8287
    8388        auto result = std::minmax_element(dist_vect.begin(), dist_vect.end());
     
    8691
    8792        //Create histogram
    88         vector<float> hist(bin_num);
     93        vector<int> hist(bin_num);
    8994        int ind = 0;
    9095
    9196        for (unsigned int j = 0; j < dist_vect.size(); j++)
    9297        {
    93                 ind = (int) std::floor((dist_vect.at(j)-min)*1/(max-min)*bin_num);
    94                 if (ind <= (bin_num-1))
    95                         hist[ind] += 1;
     98                ind = (int)std::floor((dist_vect.at(j) - min) * 1 / (max - min) * bin_num);
     99                if (ind <= (bin_num - 1))
     100                        hist[ind]++;
    96101                else if (ind == bin_num)
    97                         hist[bin_num-1] += 1;
     102                        hist[bin_num - 1]++;
    98103        }
    99104
     
    101106        for (int j = 0; j < bin_num; j++)
    102107        {
    103                 fun[j] = std::make_pair(min+(max-min)/bin_num*(j+0.5), hist[j]);
     108                fun[j] = std::make_pair(min + (max - min) / bin_num * (j + 0.5), hist[j]);
    104109        }
    105110
     
    107112        float total_mass = 0;
    108113        for (int j = 0; j < bin_num; j++)
    109     {
    110         total_mass += fun[j].second;
    111     }
     114        {
     115                total_mass += fun[j].second;
     116        }
    112117
    113118        for (int j = 0; j < bin_num; j++)
     
    129134}
    130135
    131 vector<double> SimilMeasureDistribution::D1(int samples_taken, Model *sampled)
    132 {
    133         vector<double> dist_vect;
    134         int size = sampled->getPartCount();
     136void SimilMeasureDistribution::D1(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect)
     137{
     138        int size = sampled.getPartCount();
    135139        double x = 0;
    136140        double y = 0;
    137141        double z = 0;
    138        
     142
    139143        for (int i = 0; i < size; i++)
    140144        {
    141                 Pt3D pos = sampled->getPart(i)->p;
     145                Pt3D pos = sampled.getPart(i)->p;
    142146                x += pos.x;
    143147                y += pos.y;
    144148                z += pos.z;
    145149        }
    146        
    147         x = x/size;
    148         y = y/size;
    149         z = z/size;
    150        
    151         Pt3D centroid = {x, y, z};
    152        
    153         for (int i = 0; i < samples_taken; i++)
    154         {
    155                 int p1 = rndUint(size);
    156                 double dist = sampled->getPart(p1)->p.distanceTo(centroid);
    157                 if (dist > 0)
    158                         dist_vect.push_back(dist);
    159         }
    160        
    161         return dist_vect;
    162 }
    163 
    164 vector<double> SimilMeasureDistribution::D2(int samples_taken, Model *sampled)
    165 {
    166         vector<double> dist_vect;
    167         int size = sampled->getPartCount();
    168         for (int i = 0; i < samples_taken; i++)
    169         {
    170                 int p1 = rndUint(size);
    171                 int p2 = rndUint(size);
    172                 double dist = sampled->getPart(p1)->p.distanceTo(sampled->getPart(p2)->p);
    173                 if (dist > 0)
    174                         dist_vect.push_back(dist);
    175         }
    176        
    177         return dist_vect;
    178 }
    179 
    180 vector<double> SimilMeasureDistribution::D3(int samples_taken, Model *sampled)
    181 {
    182         vector<double> dist_vect;
    183         int size = sampled->getPartCount();
    184         for (int i = 0; i < samples_taken; i++)
    185         {
    186                 int p1 = rndUint(size);
    187                 int p2 = rndUint(size);
    188                 int p3 = rndUint(size);
    189                
    190                 Pt3D v(sampled->getPart(p2)->p);
    191                 Pt3D w(sampled->getPart(p3)->p);
    192                 v -= sampled->getPart(p1)->p;
    193                 w -= sampled->getPart(p1)->p;
     150
     151        x = x / size;
     152        y = y / size;
     153        z = z / size;
     154
     155        Pt3D centroid = { x, y, z };
     156
     157        for (int i = 0; i < samples_taken; i++)
     158        {
     159                int p1 = distribution(rndgen);
     160                double dist = sampled.getPart(p1)->p.distanceTo(centroid);
     161                if (dist > 0)
     162                        dist_vect.push_back(dist);
     163        }
     164}
     165
     166void SimilMeasureDistribution::D2(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect)
     167{
     168        int size = sampled.getPartCount();
     169        for (int i = 0; i < samples_taken; i++)
     170        {
     171                int p1 = distribution(rndgen);
     172                int p2 = distribution(rndgen);
     173                double dist = sampled.getPart(p1)->p.distanceTo(sampled.getPart(p2)->p);
     174                if (dist > 0)
     175                        dist_vect.push_back(dist);
     176        }
     177}
     178
     179void SimilMeasureDistribution::D3(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect)
     180{
     181        for (int i = 0; i < samples_taken; i++)
     182        {
     183                int p1 = distribution(rndgen);
     184                int p2 = distribution(rndgen);
     185                int p3 = distribution(rndgen);
     186
     187                Pt3D v(sampled.getPart(p2)->p);
     188                Pt3D w(sampled.getPart(p3)->p);
     189                v -= sampled.getPart(p1)->p;
     190                w -= sampled.getPart(p1)->p;
    194191                Pt3D cross_prod(0);
    195192                cross_prod.vectorProduct(v, w);
    196                
     193
    197194                double dist = 0.5 * cross_prod.length();
    198195                if (dist > 0)
    199196                        dist_vect.push_back(dist);
    200197        }
    201        
    202         return dist_vect;
    203 }
    204 
    205 vector<double> SimilMeasureDistribution::D4(int samples_taken, Model *sampled)
    206 {
    207         vector<double> dist_vect;
    208         int size = sampled->getPartCount();
    209         for (int i = 0; i < samples_taken; i++)
    210         {
    211                 int a = rndUint(size);
    212                 int b = rndUint(size);
    213                 int c = rndUint(size);
    214                 int d = rndUint(size);
    215                
    216                 Pt3D ad(sampled->getPart(a)->p);
    217                 Pt3D bd(sampled->getPart(b)->p);
    218                 Pt3D cd(sampled->getPart(c)->p);
    219                
    220                 ad -= sampled->getPart(d)->p;
    221                 bd -= sampled->getPart(d)->p;
    222                 cd -= sampled->getPart(d)->p;
    223                
     198}
     199
     200void SimilMeasureDistribution::D4(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect)
     201{
     202        for (int i = 0; i < samples_taken; i++)
     203        {
     204                int a = distribution(rndgen);
     205                int b = distribution(rndgen);
     206                int c = distribution(rndgen);
     207                int d = distribution(rndgen);
     208
     209                Pt3D ad(sampled.getPart(a)->p);
     210                Pt3D bd(sampled.getPart(b)->p);
     211                Pt3D cd(sampled.getPart(c)->p);
     212
     213                ad -= sampled.getPart(d)->p;
     214                bd -= sampled.getPart(d)->p;
     215                cd -= sampled.getPart(d)->p;
     216
    224217                Pt3D cross_prod(0);
    225218                cross_prod.vectorProduct(bd, cd);
    226219                cross_prod.entrywiseProduct(ad);
    227                
    228                 double dist = cross_prod.length()/6;
    229                 if (dist > 0)
    230                         dist_vect.push_back(dist);
    231         }
    232        
    233         return dist_vect;
    234 }
    235 
    236 vector<double> SimilMeasureDistribution::A3(int samples_taken, Model *sampled)
    237 {
    238         vector<double> dist_vect;
    239         int size = sampled->getPartCount();
    240         for (int i = 0; i < samples_taken; i++)
    241         {
    242                 int p1 = rndUint(size);
    243                 int p2 = rndUint(size);
    244                 int p3 = rndUint(size);
    245                 double a = sampled->getPart(p1)->p.distanceTo(sampled->getPart(p3)->p);
    246                 double b = sampled->getPart(p3)->p.distanceTo(sampled->getPart(p2)->p);
    247                 double c = sampled->getPart(p1)->p.distanceTo(sampled->getPart(p2)->p);
    248                 double beta = acos((a*a + b*b - c*c)/(2*a*b));
    249        
     220
     221                double dist = cross_prod.length() / 6;
     222                if (dist > 0)
     223                        dist_vect.push_back(dist);
     224        }
     225}
     226
     227void SimilMeasureDistribution::A3(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect)
     228{
     229        int size = sampled.getPartCount();
     230        for (int i = 0; i < samples_taken; i++)
     231        {
     232                int p1 = distribution(rndgen);
     233                int p2 = distribution(rndgen);
     234                int p3 = distribution(rndgen);
     235                double a = sampled.getPart(p1)->p.distanceTo(sampled.getPart(p3)->p);
     236                double b = sampled.getPart(p3)->p.distanceTo(sampled.getPart(p2)->p);
     237                double c = sampled.getPart(p1)->p.distanceTo(sampled.getPart(p2)->p);
     238                double beta = acos((a * a + b * b - c * c) / (2 * a * b));
     239
    250240                if (!std::isnan(beta))
    251241                        dist_vect.push_back(beta);
    252242        }
    253        
    254         return dist_vect;
    255243}
    256244
    257245
    258246float dist(feature_t* F1, feature_t* F2)
    259 { 
    260         return abs((*F1)-(*F2));
     247{
     248        return abs((*F1) - (*F2));
    261249}
    262250
     
    266254        for (int j = 0; j < bin_num; j++)
    267255        {
    268                 points[j] = {fun[j].first};
     256                points[j] = { fun[j].first };
    269257                weights[j] = fun[j].second;
    270258        }
     
    275263        feature_t *points[2];
    276264        float *weights[2];
    277        
     265
    278266        for (int i = 0; i < 2; i++)
    279267        {
     
    283271        SimilMeasureDistribution::fillPointsWeights(fun1, points[0], weights[0]);
    284272        SimilMeasureDistribution::fillPointsWeights(fun2, points[1], weights[1]);
    285        
    286         signature_t sig1 = {bin_num, points[0], weights[0]},
    287         sig2 = {bin_num, points[1], weights[1]};
     273
     274        signature_t sig1 = { bin_num, points[0], weights[0] },
     275                sig2 = { bin_num, points[1], weights[1] };
    288276
    289277        float e = emd(&sig1, &sig2, dist, 0, 0, bin_num, bin_num);
    290        
     278
    291279        for (int i = 0; i < 2; i++)
    292280        {
  • cpp/frams/model/similarity/measure-distribution.h

    r1048 r1120  
    11// This file is a part of Framsticks SDK.  http://www.framsticks.com/
    2 // Copyright (C) 1999-2020  Maciej Komosinski and Szymon Ulatowski.
     2// Copyright (C) 1999-2021  Maciej Komosinski and Szymon Ulatowski.
    33// See LICENSE.txt for details.
    44
     
    88#include "simil-measure-base.h"
    99#include "EMD/emd.h"
     10#include <random>
    1011
    1112class SimilMeasureDistribution : public SimilMeasureBase
     
    1314public:
    1415        SimilMeasureDistribution();
    15         ~SimilMeasureDistribution(){};
     16        ~SimilMeasureDistribution() {};
    1617        int setParams(std::vector<double> params);
    1718        void calculateFuns();
    18         void calculateFun(std::pair<double, float> *fun, Model &sampled);
     19        void calculateFun(std::pair<double, float> *fun, const Model &sampled);
    1920        double compareFuns();
    2021        double EMD(std::pair<double, float> *fun1, std::pair<double, float> *fun2);
     
    2829        std::pair<double, float> *funs[2];
    2930        SolidsShapeTypeModel *sst_models[2];
    30         std::vector<double> (SimilMeasureDistribution::*distribution_fun)(int samples_taken, Model *sampled);
     31        void (SimilMeasureDistribution::*distribution_fun)(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect);
    3132
    3233        void fillPointsWeights(std::pair<double, float> *fun, feature_t *points, float *weights);
    3334        double getDistance();
    34         std::vector<double> D2(int samples_taken, Model *sampled);
    35         std::vector<double> D1(int samples_taken, Model *sampled);
    36         std::vector<double> D3(int samples_taken, Model *sampled);
    37         std::vector<double> D4(int samples_taken, Model *sampled);
    38         std::vector<double> A3(int samples_taken, Model *sampled);
     35        void D2(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect);
     36        void D1(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect);
     37        void D3(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect);
     38        void D4(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect);
     39        void A3(int samples_taken, std::uniform_int_distribution<> &distribution, const Model &sampled, std::vector<double> &dist_vect);
     40
     41private:
     42        std::mt19937 rndgen;
    3943};
    4044
Note: See TracChangeset for help on using the changeset viewer.