Welcome to the Onshape forum! Ask questions and join in the discussions about everything Onshape.

First time visiting? Here are some places to start:
  1. Looking for a certain topic? Check out the categories filter or use Search (upper right).
  2. Need support? Ask a question to our Community Support category.
  3. Please submit support tickets for bugs but you can request improvements in the Product Feedback category.
  4. Be respectful, on topic and if you see a problem, Flag it.

If you would like to contact our Community Manager personally, feel free to send a private message or an email.

Pseudo-random number generator

ysuhysuh Member Posts: 3 EDU
I need a random number generator that does not need to be true random number. Any idea on implementing a (pseudo-)random number generator? 
Tagged:

Comments

  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,173
    Here's a simple linear congruential PRNG I wrote some time back (and how to use it) -- more sophisticated stuff would need more work...

    function lcprng(seed is number) returns function
    {
        const a = 1103515245;
        const c = 12345;
        const m = 2^31;
        var state = new box(seed);
        return function() {
            state[] = (a * state[] + c) % m;
            return state[];
        };
    }
    annotation { "Feature Type Name" : "My Feature" }
    export const myFeature = defineFeature(function(context is Context, id is Id, definition is map)
        precondition
        {
            // Define the parameters of the feature type
        }
        {
            var x = lcprng(1);
            println(x());
            println(x());
            println(x());
            println(x());
            println(x());
        });

    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • ysuhysuh Member Posts: 3 EDU
    Brilliant! Thanks for quick answer. However, I want a new "random" number whenever a new feature instance is created. Since the initial seed value is fixed to 1, in this case, I think it will always generate the same number. 
  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,173
    You can attach the rng to the context using setVariable (and read it in later features using getVariable) or you can turn the feature id passed in into a seed (that's a little bit of work -- you probably need to call splitIntoCharacters and then do individual character-to-number lookups in a map -- post here if you need help with this.)
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • ysuhysuh Member Posts: 3 EDU
    Thanks a lot. The idea of using the feature id should work. It will generate the same number for each feature when it is regenerated, which is good.
  • ulrich_petriulrich_petri Member Posts: 5 ✭✭
    I'm using this function to generate a seed from the id:
    const chrMap = {
        'A':  0, 'B':  1, 'C':  2, 'D':  3, 'E':  4, 'F':  5, 'G': 6, 
        'H':  7, 'I':  8, 'J':  9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 
        'O': 14, 'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 
        'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25,
        'a': 26, 'b': 27, 'c': 28, 'd': 29, 'e': 30, 'f': 31, 'g': 32, 
        'h': 33, 'i': 34, 'j': 35, 'k': 36, 'l': 37, 'm': 38, 'n': 39, 
        'o': 40, 'p': 41, 'q': 42, 'r': 43, 's': 44, 't': 45, 'u': 46, 
        'v': 47, 'w': 48, 'x': 49, 'y': 50, 'z': 51,
        '_': 99, '-': 98
    };
    
    function idToNum(input is string) returns number {
        var out is string = "";
        for (var char in splitIntoCharacters(input)) {<br>        var res = match(char, REGEX_NUMBER);
            if (res.hasMatch) {
                out = out ~ toString(res.captures[0]);
            } else {
                out = out ~ toString(chrMap[char]);
            }
        }
        return stringToNumber(out) % 100000;
    }
    
    // Usage with the rng:
    
    var rng = lcprng(idToNum(id[0]));

  • greg_frost204greg_frost204 Member Posts: 12 ✭✭
    I realise this is a very old post, but ulrich_perti's code snippet seems to be incomplete. Any chance you could post the whole function?
  • _anton_anton Member, Onshape Employees Posts: 258
    edited May 2020
    @greg_frost204

    I imagine you could do something like this (source):
    const chrMap = {
        'A':  0, 'B':  1, 'C':  2, 'D':  3, 'E':  4, 'F':  5, 'G': 6, 
        'H':  7, 'I':  8, 'J':  9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 
        'O': 14, 'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 
        'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25,
        'a': 26, 'b': 27, 'c': 28, 'd': 29, 'e': 30, 'f': 31, 'g': 32, 
        'h': 33, 'i': 34, 'j': 35, 'k': 36, 'l': 37, 'm': 38, 'n': 39, 
        'o': 40, 'p': 41, 'q': 42, 'r': 43, 's': 44, 't': 45, 'u': 46, 
        'v': 47, 'w': 48, 'x': 49, 'y': 50, 'z': 51,
        '0': 52, '1': 53, '2': 54, '3': 55, '4': 56, '5': 57, '6': 58,
        '7': 59, '8': 60, '9': 61,
        '_': 62, '-': 63
    };
    
    // hashes a string into the [0, 2^32-1] range (picked arbitrarily)
    function hash(input is string) returns number
    {
        const mod = 2^32;
        var result = 5381;
        for (var char in splitIntoCharacters(input))
        {
            result = (result * 33 + chrMap[char]) % mod;
        }
        return result;
    }

  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    @ilya_baran
    How would I approach limiting the domain of the values to 0 to 1 (or any arbitrary value range)?
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    If I knew the theoretical max and min of the RNG then maybe this would work. Is this how you'd go about it?

        export function remap(value, rngMin, rngMax, targetMin, targetMax)
    {
        return (value-rngMin)*(targetMax-targetMin)/(rngMax-rngMin)+ targetMin;
    }
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • ilya_baranilya_baran Onshape Employees, Developers, HDM Posts: 1,173
    The remap function looks right.  If you look at the code, the output is taken modulo 2^31, so the prng range is integers between 0 and 2^31 - 1, inclusive.
    Ilya Baran \ VP, Architecture and FeatureScript \ Onshape Inc
  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    edited August 2020
    Thanks for explaining, Ilya. I think I stopped studying math before I learned what modulo is  :# I'll try this out!
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
  • Evan_ReeseEvan_Reese Member Posts: 2,060 PRO
    hey! it works! thanks again
     
    Evan Reese / Principal and Industrial Designer with Ovyl
    Website: ovyl.io
Sign In or Register to comment.