HI, I was wondering if its possible to use more than 1 attribute as percentages in an stochastic rule, something like this:
attr mytrattribute1 = 0
attr mytrattribute2 = 0
attr mytrattribute3 = 0
Function01 -->
mytrattribute1% : Do something
mytrattribute2% : Do something
mytrattribute3% : Do something
else: Do something
I tried using P() like this:
Function01 -->
case p (mytrattribute1): Do something
case p (mytrattribute2): Do something
case p (mytrattribute3): Do something
else: Do something
but it does not accept more than one attr, i really wouldn't like to hardcode this percentages =/
thank you guys for your attention!
I'm not sure the second piece of code with p() actually does the same thing as the first piece of code. In the second piece of code, the case statements are run through sequentially, which the second case statement is only reached if the first case statement fails. Consider the following example.
Let's say we want our result to be:
30%: A.
20%: B.
10%: C.
else: D.
I don't think the following is a replacement for the above:
case p(0.3): A.
case p(0.2): B.
case p(0.1): C.
else: D.
because the second statement will only be reached if the first statement is false. The chance that the first statement is false is 0.7. When considering the combination with the first statement, he second statement's code (B) will be evaluated with probability 0.7*0.2. Then, the third statement's code (C) has probability 0.7*0.8*0.1 of being reached. I think that's how it would theoretically work, but you can write tests to evaluate it and see if this does happen.
Workaround:
Here's a workaround for the above example. You could pick a random number in [0,1] and based on its value, choose to evaluate the appropriate case statement. This way, you can vary the attributes a, b, and c which control the percentages.
attr a = 0.3
attr b = 0.2
attr c = 0.1
Rule1 -->
Rule2(rand(0,1))
Rule2(x) -->
case x<a: A.
case x>=a && x<a+b: B.
case x>=a+b && x<a+b+c: C.
else: D.
Thanks for the workaround Cheryl. I've seen this question a couple of times, so it is clearly relevant to a few people.
I've tried applying this to a more complex situation and it really fell over unfortunately. I want to drive a mix of potential housetypes (currently 9 but could be much more in other scenarios) across multiple sites (start shapes) for an existing urban area. I tried applying the workaround and I think the sheer number of types caused the problem.
I realise that having a large number of start shapes means the probability approach of % and 'p' conditions could see a significant divergence from intended % mix - but it was the cascading logic of the check that I think made it fall over.
It would be really good if there were a workaround - or better still, a new feature added to the code base - that can cope with a bigger range of possible attribute inputs.
attr Mix_A = 0.05
@Percent
attr Mix_B = 0.10
@Percent
attr Mix_C = 0.15
@Percent
attr Mix_D = 0.15
@Percent
attr Mix_E = 0.15
@Percent
attr Mix_F = 0.15
@Percent
attr Mix_G = 0.10
@Percent
attr Mix_H = 0.15
@Percent
attr Mix_J = 0.0
BuildForm(Storeys)-->
case Typol == "House":
alignScopeToGeometry(yUp, any, longest)
HouseMixer1(Storeys, HouseGroupCount,1)-
else: BuildForm2(Storeys,1,4.5,Typol,1000)
HouseMixer1(Storeys, HGCount,Count)-->
HouseMixer2(Storeys, HGCount, rand(0,1))
HouseMixer2(Storeys,HGCount,Mix)-->
case Mix>=Mix_A+Mix_B+Mix_C+Mix_D+Mix_E+Mix_F+Mix_G+Mix_H
&& Mix<Mix_A+Mix_B+Mix_C+Mix_D+Mix_E+Mix_F+Mix_G+Mix_H+Mix_J: BuildForm2(Storeys,HGCount,HouseWidth_J,"J",HouseJ_GFA)
case Mix>=Mix_A+Mix_B+Mix_C+Mix_D+Mix_E+Mix_F+Mix_G
&& Mix<Mix_A+Mix_B+Mix_C+Mix_D+Mix_E+Mix_F+Mix_G+Mix_H: BuildForm2(Storeys,HGCount,HouseWidth_H,"H",HouseH_GFA)
case Mix>=Mix_A+Mix_B+Mix_C+Mix_D+Mix_E+Mix_F
&& Mix<Mix_A+Mix_B+Mix_C+Mix_D+Mix_E+Mix_F+Mix_G: BuildForm2(Storeys,HGCount,HouseWidth_G,"G",HouseG_GFA)
case Mix>=Mix_A+Mix_B+Mix_C+Mix_D+Mix_E
&& Mix<Mix_A+Mix_B+Mix_C+Mix_D+Mix_E+Mix_F: BuildForm2(Storeys,HGCount,HouseWidth_F,"F",HouseF_GFA)
case Mix>=Mix_A+Mix_B+Mix_C+Mix_D
&& Mix<Mix_A+Mix_B+Mix_C+Mix_D+Mix_E: BuildForm2(Storeys,HGCount,HouseWidth_E,"E",HouseE_GFA)
case Mix>=Mix_A+Mix_B+Mix_C
&& Mix<Mix_A+Mix_B+Mix_C+Mix_D: BuildForm2(Storeys,HGCount, HouseWidth_D,"D",HouseD_GFA)
case Mix>=Mix_A+Mix_B
&& Mix<Mix_A+Mix_B+Mix_C: BuildForm2(Storeys,HGCount, HouseWidth_C,"C", HouseC_GFA)
case Mix>=Mix_A
&& Mix<Mix_A+Mix_B: BuildForm2(Storeys,HGCount, HouseWidth_B,"B", HouseB_GFA)
case Mix<Mix_A: BuildForm2(Storeys,HGCount,HouseWidth_A,"A",HouseA_GFA)
else: BuildForm2(Storeys,HGCount,4.5,"X",1000)
True. It gets a bit messy when you have a lot of items in your mix. In 2019.1, it is possible to use an array to hold the mix percentages and then get an index into this array, which represents an item in your mix.
const mix = [Mix_A, Mix_B, Mix_C, Mix_D, Mix_E, Mix_F, Mix_G, Mix_H, Mix_J]
const randNum = rand(0, getSum(mix))
const ind = getInd(randNum, 0, 0)
getSum(mix) = getSumRecursive(mix, 0, 0)
getSumRecursive(mix, currInd, currSum) =
case currInd==size(mix):
currSum
else:
getSumRecursive(mix, currInd+1, currSum+mix[currInd])
getInd(num, currInd, currSum) =
case currInd==size(mix):
-1
case num < currSum+mix[currInd]:
currInd
else:
getInd(num, currInd+1, currSum+mix[currInd])
Rule -->
case ind==0: A.
case ind==1: B.
case ind==2: C.
// ...
else: J.