Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Pie Chart Probability


  • Please log in to reply
25 replies to this topic
miningold
  • Members
  • 52 posts
  • Last active: Aug 15 2009 01:47 AM
  • Joined: 20 Nov 2008
Imagine I have a pie chart with a spinner in the center. The pie chart has 4 different colors on it, Red, Green, Blue, Yellow. Each color takes up a certain amount of space on the pie chart, and the amount changes for each situation. If I were to spin the spinner how would I determine where the spinner would land, factoring in the probability of each color (size of slice).

The way I have my information is setup differently, but it uses the exact same concept. If you have any questions please let me know.

Thank you for your help.

  • Guests
  • Last active:
  • Joined: --
red_probability=25

green_probability=25

blue_probability=25

yellow_probability=25



random, spinner, 0, 100

if spinner between 0 and %red_probability%

msgbox, RED_%spinner%

bound_lower1:= red_probability

bound_upper1:= red_probability + green_probability

if spinner between %bound_lower1% and %bound_upper1%  

msgbox, GREEN_%spinner%

bound_lower2:= bound_upper1

bound_upper2:= bound_upper1 + blue_probability

if spinner between %bound_lower2% and %bound_upper2%  

msgbox, BLUE_%spinner%

bound_lower3:= bound_upper2

bound_upper3:= bound_upper2 + yellow_probability

if spinner between %bound_lower3% and %bound_upper3%  

msgbox, YELLOW_%spinner%


miningold
  • Members
  • 52 posts
  • Last active: Aug 15 2009 01:47 AM
  • Joined: 20 Nov 2008
Thanks that helps. However, in my situation I have upwards of 20 different "slices" and the number of slices may change. So is there a way to make a function of a sorts that allows for a changing number of slices?

Again thank you

sinkfaze
  • Moderators
  • 6367 posts
  • Last active: Nov 30 2018 08:50 PM
  • Joined: 18 Mar 2008
Something like this?

Spinner(num) {

  Random, var, 0, % num * 10
  Loop % num {
    slice := A_Index * num
    if var between 0 and %slice%
    {
      MsgBox, Slice %A_Index% was randomly selected
      break
    }
  }

}

#v::Spinner(7)
;Spinner(11)
;Spinner(24)


MasterFocus
  • Moderators
  • 4323 posts
  • Last active: Jan 28 2016 01:38 AM
  • Joined: 08 Apr 2009
sinkfaze, your code considers that all slices have the same probability, right?
(If so, I suppose a one-line random command would be enough)

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Antonio França -- git.io -- github.com -- ahk4.net -- sites.google.com -- ahkscript.org

Member of the AHK community since 08/Apr/2009. Moderator since mid-2012.


miningold
  • Members
  • 52 posts
  • Last active: Aug 15 2009 01:47 AM
  • Joined: 20 Nov 2008

Something like this?

Spinner(num) {

  Random, var, 0, % num * 10
  Loop % num {
    slice := A_Index * num
    if var between 0 and %slice%
    {
      MsgBox, Slice %A_Index% was randomly selected
      break
    }
  }

}

#v::Spinner(7)
;Spinner(11)
;Spinner(24)

Please Explain.

miningold
  • Members
  • 52 posts
  • Last active: Aug 15 2009 01:47 AM
  • Joined: 20 Nov 2008

sinkfaze, your code considers that all slices have the same probability, right?
(If so, I suppose a one-line random command would be enough)

In my situation they all have different probabilities

miningold
  • Members
  • 52 posts
  • Last active: Aug 15 2009 01:47 AM
  • Joined: 20 Nov 2008
I might try to give some more insight for what I am looking for. A while ago I tried making a genetic algorithm with AHK, Sinkfaze actually helped me with it. However, I never got it working, so I gave up. I decided to try and make another one, with less work-arounds and hopefully functional.

My current script is this:
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
CoordMode , Mouse, Screen

StartX := A_ScreenWidth/2
Loop
{
	StringRight , LastChar, StartX, 1
	If LastChar = 0
		StringTrimRight , StartX, StartX, 1
	Else
	{
		Break
	}
}
Loop
{
	StringRight , LastChar, StartX, 1
	If LastChar = .
		StringTrimRight , StartX, StartX, 1
	Else
	{
		Break
	}
}
StartY := A_ScreenHeight/2
Loop
{
	StringRight , LastChar, StartY, 1
	If LastChar = 0
		StringTrimRight , StartY, StartY, 1
	Else
		Break
}
Loop
{
	StringRight , LastChar, StartY, 1
	If LastChar = .
		StringTrimRight , StartY, StartY, 1
	Else
		Break
}
Gui, Add, Text, x16 y23 w50 h20 , Target X:
Gui, Add, Edit, x66 y20 w90 h20 vPrimeX, %StartX%
Gui, Add, Text, x166 y23 w50 h20, Target Y:
Gui, Add, Edit, x216 y20 w90 h20 vPrimeY, %StartY%
Gui, Add, Button, x316 y15 w50 h30 , Test

Gui , Add, Text, x16 y62 w80 h20 , Population Size:
Gui , Add, Edit, x106 y60 w80 h20 vNumberSeeds, 20

Gui , Add, Text, x196 y62 w70 h20 , Seed Length:
Gui , Add, Edit, x276 y60 w90 h20 vSeedLength, 10

Gui , Add, Text, x16 y102 w90 h20 , Mutation Rate (`%):
Gui , Add, Edit, x116 y100 w70 h20

Gui , Add, Text, x196 y102 w100 h20 , Crossover Rate (`%):
Gui , Add, Edit, x296 y100 w70 h20

Gui , Add, Button, x16 y140 w90 h30 +Default vStart, Start
Gui , Add, Button, x16 y140 w90 h30 +Hidden vNext, Next
Gui , Add, Button, x146 y140 w90 h30 , Pause
Gui , Add, Button, x276 y140 w90 h30 , Cancel

Gui , Add, Tab, x8 y180 w373 h290 , Seeds|Generations
Gui , Tab, 1
Gui , Add, ListView, w350 h250 +ReadOnly +NoSortHdr vSeeds, Generation|Seed|X|Y|Fitness
Gui , Tab, 2
Gui , Add, ListView, w350 h250 +ReadOnly +NoSortHdr vGenerations, Generation|Avg Fit|Best Fit|X|Y

Gui, Show, x322 y188 h489 w391, Mouse Genetic Algorithm
Return

ButtonCancel:
GuiClose:
ExitApp

ButtonHere:
MsgBox , Yes here, but doesn't mean you have to click on it :)
Return

ButtonPause:
Pause
Return

ButtonTest:
Gui , Submit, NoHide
Random , Rans, 1, 10
MouseMove , PrimeX, PrimeY, Rans
Return

RandI(min, max) ; Random integer (< 53-bit) from Globally Unique ID  ;This Takes a little time to run
{
	VarSetCapacity(A,16)
	DllCall("rpcrt4\UuidCreate","Str",A)
	Address := &A - 1
	r = 0
	Loop 8
		r := (r + (*(Address+A_Index) ^ *(Address+A_Index+8)))/256.0
	Return min + Floor(r*(max-min+1))
}
;;RandI(min, max)  ;Doesn't seem to work, probably because of delay
;{
;	High := max ;+1,000,000,000 is limit
;	Low := min ;-1,000,000,000 is limit
;	UrlDownloadToFile,http://www.random.org/integers/?num=1&min=%Low%&max=%High%&col=1&base=10&format=plain&rnd=new,%A_Temp%\number.txt
;	FileRead,random,%A_Temp%\number.txt
;	Return random
;}

;RandI(Min, Max)
;{
;   Random , Number, Min, Max
;   Return Number
;}

FirstGen(NumberSeeds, SeedLength)
{
	loop , 1000
	{
		r := RandI(0,9)
		f := RandI(0,3)
		d%r% .= f
	}
	n := RandI(0,9)
	m := d%n%
	Length := SeedLength*6
	StringRight , Seed, m, %Length%
	Return Seed
}

ProteinSynthesis(Seed, SeedLength, Temp)
{
	Result = 
	Protein =
	Loop , 2
	{
		Result =
		Loop , %SeedLength%
		{
			CodonIndex := A_Index
			Read := CodonIndex*3
			Trim := (CodonIndex-1)*3
			StringRight , SeedCodon, Seed, %Read%
			StringTrimRight , ProteinCodon, SeedCodon, %Trim%
			if ProteinCodon between 000 and 003
				Protein .= "0"
			else if ProteinCodon between 010 and 013
				Protein .= "1"
			else if ProteinCodon between 020 and 023
				Protein .= "2"
			else if ProteinCodon between 030 and 033
				Protein .= "3"
			else if ProteinCodon between 040 and 043
				Protein .= "4"
			else if ProteinCodon between 100 and 103
				Protein .= "5"
			else if ProteinCodon between 110 and 113
				Protein .= "6"
			else if ProteinCodon between 120 and 123
				Protein .= "7"
			else if ProteinCodon between 130 and 133
				Protein .= "8"
			else if ProteinCodon between 200 and 203
				Protein .= "9"
			else if ProteinCodon between 210 and 213
				Protein .= "+"
			else if ProteinCodon between 220 and 223
				Protein .= "-"
			else if ProteinCodon between 230 and 233
				Protein .= "*"
			else if ProteinCodon between 300 and 303
				Protein .= "/"
		}
		Protein := RegExReplace(RegExReplace(Protein,"([\+\*/-])[\+\*/-]+","$1"),"([\+\*/-])[0]","$1") 
		Protein := RegExReplace(RegExReplace(Protein,"^[\*\+/-0]+(.*)","$1"),"(.*)[\*\+/-]+$","$1")	
		FileDelete , %Temp%
		FileAppend , #NoTrayIcon`nFileDelete %Temp%`nFileAppend `% %Protein%`, %Temp%, %Temp%
		RunWait , %Temp%
		FileRead ,  Result, %Temp%
		FileDelete , %Temp%
		Result := Abs(Result)
		Loop
		{
			StringRight , LastChar, Result, 1
			If LastChar = 0
				StringTrimRight , Result, Result, 1
			Else
				Break
		}
		Loop
		{
			If LasChar = .
				StringTrimRight , Result, Result, 1
			Else
				Break
		}
		If Result =
			Result = 0
		If A_Index = 1
		{
			Result .= "X"
			ResultX := Result
		}
		Else If A_Index = 2
		{
			Result .= "Y"
			ResultY := Result
		}
	}
	Result := ResultX . ResultY
	Return Result
}

FillSeeds(Result, Num, GenerationIndex)
{
	Gui , ListView, Seeds
	StringGetPos , Pos, Result, X
	StringLeft , ValueX, Result, %Pos%
	Pos += 1
	StringTrimLeft , ValueY, Result, %Pos%
	StringGetPos , Pos, ValueY, Y
	StringLeft , ValueY, ValueY, %Pos%
	LV_Add("", GenerationIndex, Num, ValueX, ValueY)
}

FillGenerations(NumberSeeds, GenerationIndex)
{
	Gui , ListView, Seeds
	Prime := LV_GetCount()-NumberSeeds
	AllFitness = 0
	BestFitness = 0
	Loop , %NumberSeeds%
	{
		Start := Prime+A_Index
		LV_GetText(Fitness, Start, 5)
		AllFitness += Fitness
		If (Fitness > BestFitness)
		{
			BestFitness := Fitness
			LV_GetText(ValueX, Start, 3)
			LV_GetText(ValueY, Start, 4)
		}
	}
	AvgFitness := AllFitness/NumberSeeds
	Gui , ListView, Generations
	LV_Add("", GenerationIndex, AvgFitness, BestFitness, ValueX, ValueY)
	Random , RanS, 0, 100
	MouseMove , ValueX, ValueY, RanS
}

Fitness(PrimeX, PrimeY, NumberSeeds, GenerationIndex)
{
	Gui , ListView, Seeds
	Prime := LV_GetCount()-NumberSeeds
	AdditionX = 0
	AdditionY = 0
	Loop , %NumberSeeds%
	{
		Start := Prime+A_Index
		LV_GetText(ValueX, Start, 3)
		LV_GetText(ValueY, Start, 4)
		ValueX := Abs(PrimeX-ValueX)
		ValueY := Abs(PrimeY-ValueY)
		If ValueX = 
			ValueX := 0
		If ValueY = 
			ValueY := 0
		ValueX := 1/ValueX
		ValueY := 1/ValueY
		If ValueX = 
			ValueX := 0
		If ValueY = 
			ValueY := 0
		AdditionX += ValueX
		AdditionY += ValueY
	}
	Loop , %NumberSeeds%
	{
		Start := Prime+A_Index
		LV_GetText(ValuePrimeX, Start, 3)
		LV_GetText(ValuePrimeY, Start, 4)
		ValueX := Abs(PrimeX-ValuePrimeX)
		ValueY := Abs(PrimeY-ValuePrimeY)
		If ValueX = 
			ValueX := 0
		If ValueY = 
			ValueY := 0
		FitnessX := (1/ValueX)/AdditionX
		FitnessY := (1/ValueY)/AdditionY
		If FitnessX = 
			FitnessX := 0
		If FitnessY = 
			FitnessY := 0
		Fitness := (FitnessX+FitnessY)/2
		If Fitness =
			Fitness := 0
		Seed := (Start+NumberSeeds)-LV_GetCount()
		LV_Modify(Start, "", GenerationIndex, Seed, ValuePrimeX, ValuePrimeY, Fitness)		
	}
} 

ButtonStart:
Gui , Submit, NoHide
GuiControl , Hide, Start
GuiControl , Show , Next
GuiControl , +Default, Next
CoordMode , Mouse, Screen
SetFormat , Float, 4.18 ;In accordance with RandomI including DLLCall
GenerationIndex = 1
Temp = %A_ScriptDir%\$Temp$.ahk
FileDelete , Generation%GenerationIndex%.txt
FileDelete , Result%GenerationIndex%.txt

Num = 0
GuiControl , -Redraw, Seeds
Loop , %NumberSeeds%
{
	Num += 1
	SeedIndex := A_Index
	Seed := FirstGen(NumberSeeds, SeedLength)
	Result := ProteinSynthesis(Seed, SeedLength, Temp)
	FillSeeds(Result, Num, GenerationIndex)
	FileAppend , %Seed%`r`n, Generation%GenerationIndex%.txt
	FileAppend , %Result%`r`n, Result%GenerationIndex%.txt
}
Fitness(PrimeX, PrimeY, NumberSeeds, GenerationIndex)
Gui , ListView, Seeds
LV_ModifyCol(3)
LV_ModifyCol(4)
LV_ModifyCol(5)
GuiControl , +Redraw, Seeds
FillGenerations(NumberSeeds, GenerationIndex)
Gui , ListView, Generations
LV_ModifyCol(2)
LV_ModifyCol(3)
LV_ModifyCol(4)
LV_ModifyCol(5)
The code is big long and probably not helpful for you, however, it help me explain what I need. (P.S. this script contains no attempt at a spinner function)

In the Genetic Algorithm (GA) I have some values generated and then they are given a fitness (how close they are to the target). Their fitness determines the size of their "Slice". The size of the slices is completely random, and the number of slices is determined at the beginning of the script. I want to be able to randomly choose one of the values, the closer they are to the target the higher chance of being picked they will have (aka bigger slice).

Thank you

miningold
  • Members
  • 52 posts
  • Last active: Aug 15 2009 01:47 AM
  • Joined: 20 Nov 2008
In my first attempt a the GA for the spinner function I used a txt file.
Say I have the colors: green, blue, red, yellow

Blue = 36
green = 2
red = 13
yellow = 49

So I had the function write 36 blue line by line, then 2 greens, the 13 reds, then 49 yellows. Then I randomly chose one line from the file, which ever color I ended up with was the selected color. However, I thought this was a work-around and that there should be a way i can do it without writing to a file.

Thank you

miningold
  • Members
  • 52 posts
  • Last active: Aug 15 2009 01:47 AM
  • Joined: 20 Nov 2008

Something like this?

Spinner(num) {

  Random, var, 0, % num * 10
  Loop % num {
    slice := A_Index * num
    if var between 0 and %slice%
    {
      MsgBox, Slice %A_Index% was randomly selected
      break
    }
  }

}

#v::Spinner(7)
;Spinner(11)
;Spinner(24)

Please Explain.


I do not need this explained anymore, I get it now thanks.
And like MasterFocus wrote, this considers that all slices have the same probability, which i do not need

Thank you though

MasterFocus
  • Moderators
  • 4323 posts
  • Last active: Jan 28 2016 01:38 AM
  • Joined: 08 Apr 2009
Good. Let me test a few things and see what I can do.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Antonio França -- git.io -- github.com -- ahk4.net -- sites.google.com -- ahkscript.org

Member of the AHK community since 08/Apr/2009. Moderator since mid-2012.


miningold
  • Members
  • 52 posts
  • Last active: Aug 15 2009 01:47 AM
  • Joined: 20 Nov 2008

Good. Let me test a few things and see what I can do.

Thanks

MasterFocus
  • Moderators
  • 4323 posts
  • Last active: Jan 28 2016 01:38 AM
  • Joined: 08 Apr 2009
EDIT:
Solution provided here.
Thanks to [VxE] for the original code (next post).

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Antonio França -- git.io -- github.com -- ahk4.net -- sites.google.com -- ahkscript.org

Member of the AHK community since 08/Apr/2009. Moderator since mid-2012.


VxE
  • Moderators
  • 3622 posts
  • Last active: Dec 24 2015 02:21 AM
  • Joined: 07 Oct 2006
A random selection from a weighted set is easily calculated by choosing a random weight between zero and the total weight, then removing items one at a time until the weight of the items removed exceeds the randomly chosen weight. Then the last item removed is the one selected.

Random,, % A_Now ^ A_TickCount ; as good as any seed
Blue = 36
green = 2
red = 13
yellow = 49 
VarsListItDo =
( ltrim
	Blue
	Green
	Red
	Yellow
)
F5::MsgBox % WeightedRandomVarName(VarsListItDo)

WeightedRandomVarName( list )
{
	Local R := 0 ; Global everything else
	Loop, Parse, list, `n, `r %A_Tab%
		R += Abs(%A_LoopField%) ; Abs() was required here... I don't know why
	Random, R, 0, % R
	Loop, Parse, list, `n, `r %A_Tab%
		If ( 0 >= R -= %A_LoopField% )
			Return A_LoopField
}
Aah yes... floating numbers are just fine in this code.

  • Guests
  • Last active:
  • Joined: --
red = 11

blue = 22

green = 33

teal = 44

yellow = 55





loop %red%

list = %list%`nred



loop %blue%

list = %list%`nblue



loop %green%

list = %list%`ngreen



loop %teal%

list = %list%`nteal



loop %yellow%

list = %list%`nyellow



sort, list, random



Loop, parse, list, `n

{

if A_LoopField !=

{

chosen = %A_LoopField%

break

}

}



msgbox, % chosen

msgbox, % list