Triangular noise

Hello,

Does anybody know a way to create noise based on the triangular distribution, in a similar way as enoise and gnoise are used to generate the uniform distribution and the normal distribution, respectively? I have managed to calculate the probability density function for the triangular distribution, using two separate functions (one function for the range up to and including the mode and another function for the range beyond the mode) but do not know how to proceed from that point onwards. Any help would be highly welcome.

Eduard
Hi Eduard,

I once had a similar problem. I have written a function that may be what you're looking for. The function returns a number in the intervall [-1,1] whereas p(-1)=p(1)=0 and the probability is linear in both intervalls [-1,0] and [0,1].
function triangle()

    variable V_triangle
    do
        V_triangle=enoise(1)
    while(abs(V_triangle)+enoise(0.5)+0.5 > 1)
    return V_triangle
end

I think you can easily adjust the function to your needs.
Many thanks for the answers. Both of you have helped me already a lot. While I am trying to come to terms with the "Rejection" method I have some follow up questions. These are related to my special interest in asymmetrical triangular distributions. (So far I have read nothing about this type of distributions in the literature.)

A.G., can the rejection method also be used when we try to generate noise from a triangular distribution that is characterised by two instead of one function? (For an asymmetrical triangular distribution with a lower scale of 10, an upper scale of 50, and a mode of 40, I have calculated the probability density functions (x-10)/600 and (50-x)/200).
And what distribution can best be used to sample from? Is that one uniform distribution or the combination of two uniform distributions, such as U (0,50) for the width and U (0,0.06) for the height of a rectangle that envelopes the triangular distribution.

Andreas, the function which you wrote is also helpful. What I get from it is that you are in fact drawing from a symmetrical triangular distribution with a zero mode and lower and upper scale parameters of -1 and +1. I am thinking about ways in which the function might be extended so that it can also be used for asymmetrical triangular distributions, but suggestions are of course always welcome.

Eduard
Hi Eduard,

I have modified the function a bit.
function assymTriangle(lowerScale,upperScale,mode)
    variable lowerScale,upperScale,mode

    variable V_triangle
    variable scale=(upperScale-lowerScale)/2
    variable scaleShift=lowerScale+scale
    variable slope1=1/(mode-lowerScale)
    variable slope2=1/(mode-upperScale)
    variable rejectionVar,whileVar
   
    do
        V_triangle=enoise(scale)+scaleShift     // range: [lowerScale,upperScale]
        rejectionVar=enoise(0.5)+0.5        // range: [0,1]
        // test, if V_triangle lies between lowerScale and mode or mode and upperScale,
        // for the former case calculate slope of the line trough points (V_triangle,rejectionVar) and (lowerScale,0)
        // and reject V_triangle if this slope is greater than slope1 -> whileVar=1
        // for the latter case calculate slope of the line trough points (V_triangle,rejectionVar) and (upperScale,0)
        // and reject V_triangle if this slope is less than slope2 -> whileVar=1
        whileVar= V_triangle<mode ? (rejectionVar/(V_triangle-lowerScale)>slope1) : (rejectionVar/(V_triangle-upperScale)<slope2)
    while(whileVar)
   
    return V_triangle
end

The funtion test if a point defined by two random values x and y lies inside of the triangle or outside. The triangle is defined in an x/y coordinate system by three points (lowerScale,0), (mode,1) and (upperScale,0). For the former case accept x as a valid sampling value, for the latter case reject it.
Hello Andreas,

Thank you very much for the code. You contributed much more than I could have hoped for and the function delivers what I am looking for. I have one final question if I may. Do you know a way to transfer the outcome of the function (V_triangle) to a wave, so that I can collect for example 100 accepted sample values? So far the only way I see is to repeat the command Print assymTriangle(10,50,40) or an equivalent command a 100 times.

Thanks again for any reply.

Eduard
Nothing easier than that:
make/o/n=100 W_triangularNoise = assymTriangle(10,50,40)

You can even create a histogram to illustrate the sampling:
Make/N=40/O W_triangularNoise_Hist;DelayUpdate
Histogram/B={10,1,40} W_triangularNoise,W_triangularNoise_Hist;DelayUpdate
Display W_triangularNoise_Hist
This is great. Thanks for that. I calculated the mean, standard deviation and the probability of the mode for a sample of 10,000 draws and found them all very close to the expected values. With my relatively short experience, the versatile Igor Pro has still many undiscovered features and I have been encouraged again to learn more about the program.

Eduard