2

In my python program, I have three variables a, b and c. They are all floats, and may be positive or negative with no upper and lower bounds.

How would I go about devising a function that takes these variables as weights and randomly chooses a corresponding action (A, B & C)?

Example:

a = 10
b = -2
c = 7

The function should perform A most of the time, C some times, and B the least often.

The 'weighted random functions' I found on this site do not deal with negative weights.

Edd
  • 3,724
  • 3
  • 26
  • 33
medakk
  • 81
  • 6
  • what *is* a negative weight? it makes no sense (in this context). – Karoly Horvath Oct 09 '14 at 07:50
  • 1
    -2 is a negative weight – Vincent Beltman Oct 09 '14 at 07:50
  • @VincentBeltman: no, that's an *example*. – Karoly Horvath Oct 09 '14 at 07:51
  • Why do you need negative weights? – Aman Gautam Oct 09 '14 at 07:52
  • 1
    @KarolyHorvath 10, -2 and 7 are examples of weights. Since -2 is negative its a negative weight ;) – Vincent Beltman Oct 09 '14 at 07:54
  • 4
    @VincentBeltman: will you please stop posting idiotic comments? – Karoly Horvath Oct 09 '14 at 07:58
  • Its a gene simulation program with payoffs alloted for activities. If an animal does extremely badly, it gets a negative weight and is less likely to produce an offspring ov its own types. I have made many assumptions with respect to the actual simulation which may or may not be accurate, but the negative weight problem cannot be avoided – medakk Oct 09 '14 at 07:59
  • *"the negative weight problem cannot be avoided"* - expect by doing something sensible like normalising all weights to between 0 (no chance of reproduction) and 1 (certain reproduction). – jonrsharpe Oct 09 '14 at 08:04
  • @jonrsharpe: yes, that would be great, but you probably don't want to use either 0 or 1, so it's still pretty vague. I guess there's *no* right way... – Karoly Horvath Oct 09 '14 at 08:07
  • Correct. But is it mathematically impossible to compute a random choice based on negative weights? – medakk Oct 09 '14 at 08:07
  • the problem is how to *properly interpret* them. until that is resolved, you cannot do math. maybe try a modified version of what @jonrsharpe suggested, and normalise weight to between 0.2 and 0.8. as you can see, it's an arbitrary interpretation, but at least you can do the math... a more proper interpretation needs the understanding of how those weights are created, and what's their exact meaning (e.g.: "less likely" is pretty vague). – Karoly Horvath Oct 09 '14 at 08:13
  • possible duplicate of [Select random item with weight](http://stackoverflow.com/questions/9259989/select-random-item-with-weight) – Andrey Oct 09 '14 at 10:51
  • If by weight you mean relative probability then how can it be negative? – Andrey Oct 09 '14 at 10:52
  • @Karoly supposing the weights were all positive, it would be a simple matter ov ratio and proportions. I would like to achieve the same using negative weights as well. – medakk Oct 09 '14 at 11:29
  • @Andrew no, the other question says negative weights can be ignored – medakk Oct 09 '14 at 11:29
  • The simplest solution seems to be to work the weights into [0,1] range...I shall try that – medakk Oct 09 '14 at 11:30
  • based on @dataman 's idea, I would first figure out the distribution of the weights. then at least you can *try* to treat it like you're doing math and not wild guessing. – Karoly Horvath Oct 09 '14 at 13:27
  • Unless you really mean [negative probability](https://en.wikipedia.org/wiki/Negative_probability), your weights should all be positive. Or do is this somehow related to e.g. electrical charge, which of course can be negative? – Tobias Kienzler Dec 02 '16 at 08:19
  • Negative numbers don't really make much sense, but if you want to add `-10` for example, you could instead consider adding a weight of `1/10`? – David Callanan Jul 17 '19 at 18:45

4 Answers4

2
weights = [10, -2, 7]
offset = min(weights)
positiveweights = [z - offset + 1 for z in weights]

Now you can use any weighted random function that requires positive weights.

nekomatic
  • 5,988
  • 1
  • 20
  • 27
  • 2
    Do the weights behave correctly though? An offset of `5` vs `0` could change the result to `[5, 6]` vs `[0, 1]` which from what I know behaves differently – David Callanan Jul 17 '19 at 18:43
1

Well, an easy way is to assume that the values of your variables come from a normal distribution with the mean equal to largest value(*) and an arbitrary standard deviation (e.g. sd=1).

Then, what you need to do is simply to find the probability of seeing a specific value such as -2 which can be solved by probability distribution function (pdf). Then you can use the probabilities as weights.

The good thing about this method is that you can have also negative values.

Solution:

import scipy.stats
variables = [10, -2, 7]
maximum = max(variables)
probabilities = scipy.stats.norm(maximum, 1).pdf([variables])

Result: array([[ 3.98942280e-01, 2.14638374e-32, 4.43184841e-03]])

The rest, you can figure out yourself.

(*) The reason for setting the meanto the largest value is to get the largest probability (weight) for it.

Dataman
  • 3,457
  • 3
  • 19
  • 31
  • I guess the "arbitrary" (lol. 1? really?) standard deviation has a *big* effect on the resulting probabilities, so you probably:) have to play with it till you're satisfied with the results. `e-32` definitely doesn't sound right. – Karoly Horvath Oct 09 '14 at 13:31
-2

Just my thought, what if you sum weights. And you get 19 + 4 (B positive is 2, diffrence is 4) + 7 = 30.

chanceA = 19 / 30 = 63%
chanceB = 2 / 30 = 6%
chanceC = 7 / 30 = 23%

You don't get 100% if you sum procentages but, it would maybe work :)

Jure
  • 799
  • 6
  • 25
-4

You can transform negative numbers to numbers. To numbers in [0;1] segment. like that

def chance(a):
   if a>0: 
       return a
   else: 
       return 1/abs(a) 

also you should return something on 0

Darth Kotik
  • 2,261
  • 1
  • 20
  • 29