Ignore:
Timestamp:
06/22/23 03:29:05 (15 months ago)
Author:
Maciej Komosinski
Message:
  • turn -0.0 into 0.0 if we have minimum==0.0, so that it does not look as if we got a value below 0.0 (minimum) after mutation (even though -0.0==0.0)
  • implemented stochastic rounding for the mutation of integer parameters
File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpp/frams/genetics/genooperators.cpp

    r1247 r1254  
    55#include <ctype.h>  //isupper()
    66#include <algorithm> // std::min, std::max
     7#include <cmath> // std::floor()
    78#include "genooperators.h"
    89#include <common/log.h>
     
    203204                if (result > mx) result = mx - (result - mx); else
    204205                        if (result < mn) result = mn + (mn - result);
    205                 //wrap (just in case 'result' exceeded the allowed range so much that after reflection above it exceeded the other boundary):
     206                //wrap (just in case 'result' exceeded the allowed range so much that after the reflection above it exceeded the other boundary):
    206207                if (result > mx) result = mn + fmod(result - mx, mx - mn); else
    207208                        if (result < mn) result = mn + fmod(mn - result, mx - mn);
     
    210211                        //reflect and wrap above may have changed the (limited) precision, so try to round again (maybe unnecessarily, because we don't know if reflect+wrap above were triggered)
    211212                        double result_try = round(result, 3);
    212                         if (mn <= result_try && result_try <= mx) result = result_try; //after rounding still witin allowed range, so keep rounded value
    213                 }
    214         }
     213                        if (mn <= result_try && result_try <= mx) result = result_try; //after rounding still within allowed range, so keep rounded value
     214                }
     215        }
     216        clipNegativeZeroIfNeeded(result, mn); //so we don't get -0.0 when minimum is 0.0
    215217        return result;
    216218}
     
    222224}
    223225
    224 void GenoOperators::setIntFromDoubleWithProbabilisticDithering(ParamInterface &p, int index, double value) //TODO
    225 {
    226         p.setInt(index, (paInt)(value + 0.5)); //TODO value=2.499 will result in 2 and 2.5 will result in 3, but we want these cases to be 2 or 3 with almost equal probability. value=2.1 should be mostly 2, rarely 3. Careful with negative values (test it!)
     226void GenoOperators::setIntFromDoubleWithProbabilisticDithering(ParamInterface &p, int index, double value)
     227{
     228        // Deterministic rounding to the closest integer:
     229        //value += 0.5; // value==2.499 will become int 2 and value==2.5 will become int 3, but we want these cases to be 2 or 3 with almost equal probability (stochastic rounding).
     230
     231        //stochastic rounding (value==2.1 should turn in most cases to int 2, rarely to int 3; value==-2.1 should become mostly int -2, rarely int -3):
     232        double lower = std::floor(value);
     233        value = rndDouble(1) < (value - lower) ? lower + 1 : lower;
     234
     235        p.setInt(index, (paInt)value);
    227236}
    228237
Note: See TracChangeset for help on using the changeset viewer.