python random with a skew

I am trying to create a very simple evolution algorithm for a creature simulator, what I would like to have is, both creatures have a trait and a dominance level, both noted by ints. their child’s trait will be a random number between creature A’s trait and creature B’s trait then skewed to the more dominant. So if A has a trait of 5 and dominance of 2 and B has a trait of 10 and a dominance of 7, the skew will be -5 so it skews more towards B. Their child is more likely to have a trait of 8 than 6. Is there a good way to do this?
I visualise it ending up like this:
A5-6–7—8—-9—–10B

I can’t figure out how much the skew should be until I am able to test the results, so for the time being it’s kind of arbitrary.

Thank you everyone for taking the time to help me.

my solution will give you stronger skew for bigger dominance differences:
it is using the fact that raising a value between 0 and 1 to a positive power will skew the result within the same range.
set the fine-tuning, as you see fit.

import random
a_trait = 5
a_dominance = 2
b_trait = 10
b_dominance = 7

target = random.random()
skew = abs(a_dominance - b_dominance) + 1
fine_tuning_multiplier = 0.3
skewed_target = target ** (skew * fine_tuning_multiplier)

trait_delta = abs(a_trait - b_trait)
target_trait = trait_delta * (1 - skewed_target)

if a_dominance > b_dominance:
  val = b_trait - target_trait
else:
  val = a_trait + target_trait

print "val:", int(round(val))

note that in this solution the traits must be sorted. (i.e. a_trait < b_trait)

40 consecutive runs resulted in:
8 8 9 8 9 10 6 7 7 10 8 8 9 9 10 9 9 7 10 6 10 7 10 9 10 10 7 8 8 7 10 5 6 6 9 9 10 10 6 6

From what I see, you need a weighted random selection, from range(parent_a.trait, parent_b.trait).

To distribute the weights linearly, the simplest thing you could do is construct a range of floats in such a way that the sum() of the range is 1.0, and each step would represent a probability of choosing that one step.

Example:

trait_delta = abs(pacent_a.trait - trait_b.trait)
trait_delta_sum = trait_delta * (trait_delta+1.) / 2.
weights = [x/trait_delta_sum for x in range(1, trait_delta+1)]

As I said above, the sum of the weights should be equal to one:

assert sum(weights) == 1.

Then generate a cumulative sum of the weights:

cumulative_weihts = [sum(weights[:x]) for x in range(trait_delta)]

Now just pick a random number, and find the index of the largest number that is smaller than said random number:

rand = random.random()
shift = sum[-1 for x in cumulative_weightn if r<x])

Finally, use the skew as an offset from the trait with the bigger dominance:

if parent_a.dominance > parent_b.dominance:
    trait = parent_a.dominance + skew
else:
    trait = parent_b.dominance + skew

Sure, that’s quite simple to do.

Just take the sum of both dominance values and take a random.randrange() value of these.

If that value is lower than the dominance value of parent A, you picked that parent’s trait, otherwise it’s parent B’s trait you picked:

import random

if random.randrange(parentA.dominance + parentB.dominance) < parentA.dominance:
    trait = parentA.trait
else:
    trait = parentB.trait

In other words, it’s a very simple weighted random selection between two options.

For your specific example, the sum of the dominances is 9, so the randrange() value is one between 0 and 8; if 0 or 1 is picked, parent A’s trait is selected, if 2, 3, 4, 5, 6, 7 or 8 is picked then parent B’s trait is selected instead.

If instead you are talking about picking a trait on a range from parent A’s trait value up to and including parent B’s trait value where traits are treated as a range, then your dominance values are used to ‘pull’ a trait value towards one or the other parent.

It basically comes down to a tug-of-war between the parents. With balanced dominance, the trait picked would, on average, come down to the average value of the two traits. But with one parent dominating over the other, the trait value picked ‘shifts’ towards the dominating parent.

This translates in a chance that the values below the midpoint are picked for parent A have a chance of parentA.dominance in (parentA.dominance + parentB.dominance), while the values above the midpoint have a chance of parentB.dominance in (parentA.dominance + parentB.dominance) of being picked.

import random

pick = random.random()

# sort parents by trait; smallest trait first
parents = sorted((parentA, parentB), key=attrgetter('trait'))
average = (parents[0].trait + parents[1].trait) / 2.0
weights = []
slots = (parents[1].trait - parents[0].trait + 1.0) * (parents[0].dominance + parents[1].dominance)
for i in range(parents[0].trait, parents[1].trait + 1):
    if i <= average:
        weights.append(sum(weights) + (parents[0].dominance / slots))
    else:
        weights.append(sum(weights) + (parents[1].dominance / slots))
    if weights[-1] > pick:
        return i

A quick demo picking traits between parent A and parent B using the above calculation:

>>> for i in range(40): print pickTrait(),
... 
9 9 9 10 6 9 8 10 7 9 9 8 8 8 9 8 9 9 7 5 8 8 9 5 9 9 10 10 10 10 5 5 9 9 8 9 10 7 8 9

6

If I understand your question correctly, you want a probability distribution function somewhat like below. The y axis is your dominance value and the x axis is the trait value.

To generate a value in this distribution, you basically take the area under the curve, 12.5 in this case. Choose a uniform random number between 0 and 12.5, fill in that much area starting from the left side, and see where it falls on the x axis. For example, say you chose 4.5. The area under the curve between 5 and 8 is 4.5, so your child’s trait is 8.

If my math is right, given a as the value between 0 and 12.5 you chose, d1 and d2 are the respective dominances, and t1 and t2 are the respective traits, your child’s trait is given by:

t1 + sqrt(2*a*(d2-d1)/(t2-t1))

You can do this by generating two random numbers.

Say you have trait A. The first ‘parent’ has a value of 2. The second a value of 8. You thus want a range of 2 to 8. Normally you’d generate a random number between 0 and 1.0, and multiply that by (8 – 2) and add it to 2, like:

N = (rand() * (8-2)) + 2;

Simple enough, but it doesnt trend in a particular direction.

Instead, generate two random numbers. Lets say you want the 8 (the high value) to be the ‘dominant’ trait. Generate two random values between 0 and 1.0, and use the highest of the two when calculating the new child’s value. That will ‘trend’ you towards 8.

If you wanted the low value to be dominant, do the same, using the lower of the two randomly generated numbers.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật