Implementing a time lag in NetLogo - modeling

I am trying to implement a time lag for a performance indicator in a NetLogo program. This is what I'm currently trying to code, but I don't know how to implement the (t-1) factor in the following formula:
performance(t) = θ × performance(t−1) + (1 − θ) π(t), 0 < θ < 1
For now I left it like this:
ask turtles [
set performance theta * performance + (1 - theta) * profit
]
But my model doesn't give legitimate results (since this formula doesn't take the time lag into account, as far as I know).
Entire code :
globals [
N ; Number of firms
price ; Market price
totOutput ; Total production of firms
meanProd ; Average productivity of firms
maxProd ; Maximal productivity of firms
minProd ; Minimal productivity of firms
meanProf-innov ; Average profit of innovators
meanProf-imit ; Average profit of pure imitators
HK ; Concentration index over capital
HQ ; Concentration index over output
; Other parameters
rIn ; Innovative R&D calibration parameter
rIm ; Imitative R&D calibration parameter
aIn ; Innovative R&D calibration parameter
aIm ; Imitative R&D calibration parameter
avgRIn ; NEW -> Represents the Average Rate of R&D Investments by Innovators
avgRIm ; NEW -> Represents the Average Rate of R&D Investments by Imitators
avgCapitalProfit
CapitalProfit
Ae
Ue
Entrynumber
sumCapSq
totCapital
]
breed [Innovators Innovator]
breed [Imitators Imitator]
Innovators-own [
output ; output of the firm
prod ; productivity of the firm
capital ; capital stock of the firm
profit ; gross profit of the firm
rInF ; Each innovator's innovative R&D parameter will be the common rIn
rImF ; Each innovator's imitative R&D parameter will the common rIm
RDIn ; Innovative R&D investment of the firm
RDIM ; Imitative R&D investment of the firm
RInCapital ; NEW -> See below (Formula for new rates) , it is equal to rImF * capital for each innovator
RImCapital ; NEW -> See below (Formula for new rates) , it is equal to rImF * capital for each imitator
prodInnovate ; Productivity discovered thanks to the innovation
prodImitate ; Productivity discovered thanks to the imitation
performance ; NEW -> Performance Indicator
]
Imitators-own [
output ; output of the firm
prod ; productivity of the firm
capital ; capital stock of the firm
profit ; net profit of the firm
rImF ; Each imitator's imitative R&D parameter will be the common rIm
rInF ; Each imitator's innovative R&D parameter will be zero
RDIn ; Innovative R&D investment of the imitator will be 0
RDIM ; Imitative R&D investment of the firm
RInCapital ; NEW -> See below (Formula for new rates) , it is equal to rImF * capital for each innovator
RImCapital ; NEW -> See below (Formula for new rates) , it is equal to rImF * capital for each imitator
prodInnovate ; Productivity discovered thanks to the innovation
prodImitate ; Productivity discovered thanks to the imitation
performance ; NEW -> Performance indicator
]
to setup
clear-all
create-Innovators nbInnov
create-Imitators nbImit
set N nbInnov + nbImit
; Initial capital stock of the firms in order to have zero desired net investment (investment just compensates the depreciation in the initial Cournot equilibrium)
let K0 ( (Dem * A0 * ( N * Eta - 1))/(N * Eta * c) ^ (1 / Eta )) / (N * A0)
; Innovation and imitation parameters
set aIn 0.125
set aIm 1.25
; Innovation and imitation parameters deducted from probabilities
; NEW Investment R&D Rates
set rIn probInnov / ( K0 * aIn)
set rIm probImitate / ( K0 * aIm)
; Setting these parameters at the firm level for each type of firm
ask Innovators [
set prod A0
set capital K0
set rInF random-float 0.004 + 0.005 ; NEW -> Gives a number following a Uniform distribution between 0.005 and 0.009
set rImF random-float 0.0004 + 0.0003 ; NEW -> Gives a number following a Uniform distribution between 0.0003 and 0.0007
]
ask Imitators [
set prod A0
set capital K0
set rInF 0
set rImF random-float 0.0004 + 0.0003 ; NEW -> Gives a number following a Uniform distribution between 0.0003 and 0.0007
]
ask Turtles [
set performance 0
]
reset-ticks
end
to go
if ticks > nbPeriods [stop]
ask turtles [ ; NEW
if capital < Kmin [ die ] ; NEW
if performance < performance-min [ die ] ; NEW
] ; NEW
; NEW
; Eventually, hereafter is the problem of decision that decides wheter a company should enter the industry or not
ask turtles [ ; NEW
if (price * Ae - c > entry-barrier + ue) [ ; NEW
hatch entryNumber [ ; NEW
set performance 0.1 ; NEW
set capital random-normal (sumCapSq / totCapital) 5 ; NEW
set RDIm random-normal (RImCapital / totCapital) 0.01 ; NEW
set RDIn random-normal (RInCapital / totCapital) 0.01 ; NEW
]
]
]
; Fixing the output of each firm
ask turtles [
set output prod * capital
]
;Computing the total output and the intraperiod price
set totOutput sum [output] of turtles
set price invDemand totOutput
;Productivity indicators of the current period
set maxProd max [prod] of turtles
set meanProd mean [prod] of turtles
set minProd min [prod] of turtles
;Concentration indicators of the current period
set totCapital sum [capital] of turtles
set HK (totCapital) ^ 2 / sum [capital ^ 2] of turtles
set HQ (totOutput) ^ 2 / sum [output ^ 2] of turtles
; Moving towards the next period (new productivity and capital stock)
ask turtles [
; Compute net profits
set profit (price * prod - c) * capital - RDIn - RDIm
; NEW Formulas used to calculate new rates
set capitalProfit sum [capital * profit] of turtles ;NEW
set avgCapitalProfit capitalProfit / totCapital ;NEW
set RInCapital sum [(rInF * capital)] of turtles ;NEW
set RImCapital sum [(rImF * capital)] of turtles ;NEW
set avgRIn (RInCapital) / (totCapital) ;NEW
set avgRIm (RImCapital) / (totCapital) ;NEW
; Compute R&D investments
]
ask turtles [
set RDIn rInF * aIn * capital
set RDIm rImF * aIm * capital
; Below are the original commands of the original model, kept this way should an error arise
; OLD set RDIn (rInF * aIn * capital)
; OLD set RDIm (rImF * aIm * capital)
; Compute productivities discovered thanks to innovation and imitation
set prodInnovate innovation
set prodImitate imitation
; Set the new productivity of the firm
set prod max (list prod prodInnovate prodImitate)
; Compute the new capital stock of the firm
set capital investK
]
;profit indicators
set meanProf-innov mean [profit] of Innovators
set meanProf-imit mean [profit] of Imitators
; NEW
; Below we code the performance indicator
ask turtles [
set profit (price * prod - c) * capital - RDIn - RDIm
set performance theta * performance + (1 - theta) * profit
]
tick
; NEW
; The group of commands below represents the entry process of decision
set entryNumber round (entry-trials-rate * N) ; NEW
let prodCapital sum [prod * capital] of turtles ; NEW
let avgA prodCapital / totCapital ; NEW
set Ae random-normal avgA STD ; NEW
set ue random-normal 0 0.1 ; NEW
set sumCapSq sum [capital ^ 2] of turtles ; NEW
; NEW
; Below are is the command representing the exit process of decision
; NEW R&D RATES
; Hereafter we compute the new rates following the satisficing rule à la Simon
ask turtles [
if performance < avgCapitalProfit [
set rInF (1 - beta) * rInF + beta * avgRIn + random-normal 0 sigma-n
set rImF (1 - beta) * rImF + beta * avgRIm + random-normal 0 sigma-m
]
]
end ;INVESTK
; Imitation procedure
to-report imitation
; Draw a number between 0 and 1
let draw random-float 1.
; Compare it with the rescaled value of the R&D
ifelse draw <= RDIm [report maxProd][report 0.]
end
; Innovation procedure
to-report innovation
; Draw a number between 0 and 1
let draw random-float 1.
; Compare it with the rescaled value of the R&D
ifelse draw <= RDIn [report random-normal prod STD][report 0.]
end
;Investment procedure
to-report investK
; Compute the current market share of the firm
let marketShare output / totOutput
; Compute the current margin of the firm
let margin c / (prod * price)
; The target price
let target-price (margin * ETA) / (ETA - marketShare)
; Compute the desired investment of the firm
let desInvest (DEPREC + 1 - ( target-price / price) )
; Compute maximal possible investment (No external financing)
let maxInvest (DEPREC + profit)
; Possible investment
let posInvest min (list desInvest maxInvest)
; Compute the effective investment rate of the firm (it cannot be negative)
let investmentRate max (list posInvest 0.)
report ((1 - DEPREC) + investmentRate) * capital
end
; The constant-elasticity inverse demand function
to-report invDemand [totQuant]
report Dem / (totQuant ^ Eta)
end

You code already does the (t-1). You can see this by doing:
ask turtles
[ print performance
set performance theta * performance + (1 - theta) * profit
print performance
]
We might need more of the code and an example of what is going wrong

Related

Intersect of two planes - divide by zero

I have following alghoritm to find line intersection of two planes:
public static function getIntersectOf2Planes ( self $P1 , self $P2 )
{
/* Line equation in parametric form:
x = x0 + t*a
y = y0 + t*b
z = z0 + t*c
*/
$x0 = ( $P1->B * $P2->D - $P2->B * $P1->D ) / ( $P1->A * $P2->B - $P2->A * $P1->B ) ;
$a = ( $P1->B * $P2->C - $P2->B * $P1->C );
$y0 = ( $P2->A * $P1->D - $P1->A * $P2->D ) / ( $P1->A * $P2->B - $P2->A * $P1->B ) ;
$b = ( $P2->A * $P1->C - $P1->A * $P2->C );
$z0 = 0;
$c = ( $P1->A * $P2->B - $P2->A * $P1->B );
$IntersectionLine = new Line3D( $x0, $a, $y0, $b, $z0, $c );
return $IntersectionLine;
}
and it works fine, but to compute $x0 and $y0 i have to divide by:
( $P1->A * $P2->B - $P2->A * $P1->B )
and in some cases, the value of this expression is equal to zero, so I get an "dividing by zero" error :(
What should I do in this case?
I know, that the case when this expression is equal to zero, doesn't mean that there is no intersection, because it's happen when I have planes perpendicular to one of the axies.
For example for:
Plane1:
A = 0
B = 0
C = 100
D = 0
Plane2:
A = 50
B = 0
C = 0
D = -250
so the equation of line should exists.
PS I wrote this code with a view to:
https://math.stackexchange.com/questions/2766615/line-by-two-planes-intersection?noredirect=1#comment5706281_2766615
In short, you have to implement the intersection algorithm for the case when (a1*b2 - a2*b1) = 0 (ie. when the planes are not independent when you set z=0).
To expand on that, first we need to understand how you got this far. First let us write down the equation of two planes:
a1x + b1y + c1z + d1 = 0
and
a2x + b2y + c2z + d2 = 0
When two planes intersect, the intersection is a line. So, the most usual way to solve that is by finding a point first on such a line and then figuring out its orientation (a, b, c) in your case. The orientation is a straight forward cross product. The intersection point is typically calculated by setting one of the co-ordinates to 0 and then solving the 2 linear equations that you get. In your code, this is done by setting:
z = 0
But this only works when the equations
a1x + b1y + d1 = 0 and a2x + b2y + d2 = 0
are capable of giving a solution for x and y, which is not the case when a1b2-a2b1=0. So In such cases, you can solve the same by setting either x or y to 0 which again gives two linear equations that you can solve to obtain a point on the line. Then you can compute the parametric form much like how you did. For example (setting y to 0):
x0 = (c1d2 - c2d1)/(a1c2 - a2c1)
y0 = 0
z0 = (a2d1 - a1d2)/(a1c2 - a2c1)
But for this to be a defined value you need to have (a1c2 - a2c1) to be non-zero. Does this help?

Fortran error: Program received signal SIGSEGV: Segmentation fault - invalid memory reference

I'm try to run an ocean temperature model for 25 years using the explicit method (parabolic differential equation).
If I run for a year a = 3600 or five years a = 18000 it works fine.
However, when I run it for 25 years a = 90000 it crashes.
a is the amount of time steps used. And a year is considered to be 360 days. The time step is 4320 seconds, delta_t = 4320..
Here is my code:
program task
!declare the variables
implicit none
! initial conditions
real,parameter :: initial_temp = 4.
! vertical resolution (delta_z) [m], vertical diffusion coefficient (av) [m^2/s], time step delta_t [s]
real,parameter :: delta_z = 2., av = 2.0E-04, delta_t = 4320.
! gamma
real,parameter :: y = (av * delta_t) / (delta_z**2)
! horizontal resolution (time) total points
integer,parameter :: a = 18000
!declaring vertical resolution
integer,parameter :: k = 101
! declaring pi
real, parameter :: pi = 4.0*atan(1.0)
! t = time [s], temp_a = temperature at upper boundary [°C]
real,dimension(0:a) :: t
real,dimension(0:a) :: temp_a
real,dimension(0:a,0:k) :: temp
integer :: i
integer :: n
integer :: j
t(0) = 0
do i = 1,a
t(i) = t(i-1) + delta_t
end do
! temperature of upper boundary
temp_a = 12. + 6. * sin((2. * t * pi) / 31104000.)
temp(:,0) = temp_a(:)
temp(0,1:k) = 4.
! Vertical resolution
do j = 1,a
do n = 1,k
temp(j,n) = temp(j-1,n) + (y * (temp(j-1,n+1) - (2. * temp(j-1,n)) + temp(j-1,n-1)))
end do
temp(:,101) = temp(:,100)
end do
print *, temp(:,:)
end program task
The variable a is on line 11 (integer,parameter :: a = 18000)
As said, a = 18000 works, a = 90000 doesn't.
At 90000 get I get:
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
RUN FAILED (exit value 1, total time: 15s)
I'm using a fortran on windows 8.1, NetBeans and Cygwin (which has gfortran built in).
I'm not sure if this problem is caused through bad compiler or anything else.
Does anybody have any ideas to this? It would help me a lot!
Regards
Take a look at the following lines from your code:
integer,parameter :: k = 101
real,dimension(0:a,0:k) :: temp
integer :: n
do n = 1,k
temp(j,n) = temp(j-1,n) + (y * (temp(j-1,n+1) - (2. * temp(j-1,n)) + temp(j-1,n-1)))
end do
Your array temp has bounds of 0:101, you loop n from 1 to 101 where in iteration n=101 you access temp(j-1,102), which is out of bounds.
This means you are writing to whatever memory lies beyond temp and while this makes your program always incorrect, it is only causing a crash sometimes which depends on various other things. Increasing a triggers this because column major ordering of your array means k changes contiguously and is strided by a, and as a increases your out of bounds access of the second dimension is further in memory beyond temp changing what is getting overwritten by your invalid access.
After your loop you set temp(:,101) = temp(:,100) meaning there is no need to calculate temp(:,101) in the above loop, so you can change its loop bounds from
do n = 1,k
to
do n = 1, k-1
which will fix the out of bounds access on temp.

Partition line into equal parts

This is a geometry question.
I have a line between two points A and B and want separate it into k equal parts. I need the coordinates of the points that partition the line between A and B.
Any help is highly appreciated.
Thanks a lot!
You just need a weighted average of A and B.
C(t) = A * (1-t) + B * t
or, in 2-D
Cx = Ax * (1-t) + Bx * t
Cy = Ay * (1-t) + By * t
When t=0, you get A.
When t=1, you get B.
When t=.25, you a point 25% of the way from A to B
etc
So, to divide the line into k equal parts, make a loop and find C, for t=0/k, t=1/k, t=2/k, ... , t=k/k
for(int i=0;i<38;i++)
{
Points[i].x = m_Pos.x * (1 - (i/38.0)) + m_To.x * (i / 38.0);
Points[i].y = m_Pos.y * (1 - (i/38.0)) + m_To.y * (i / 38.0);
if(i == 0 || i == 37 || i == 19) dbg_msg("CLight","(%d)\nPos(%f,%f)\nTo(%f,%f)\nPoint(%f,%f)",i,m_Pos.x,m_Pos.y,m_To.x,m_To.y,Points[i].x,Points[i].y);
}
prints:
[4c7cba40][CLight]: (0)
Pos(3376.000000,1808.000000)
To(3400.851563,1726.714111)
Point(3376.000000,1808.000000)
[4c7cba40][CLight]: (19)
Pos(3376.000000,1808.000000)
To(3400.851563,1726.714111)
Point(3388.425781,1767.357056)
[4c7cba40][CLight]: (37)
Pos(3376.000000,1808.000000)
To(3400.851563,1726.714111)
Point(3400.851563,1726.714111)
which looks fine but then my program doesn't work :D.
but your method works so thanks

Finding mean of array of ints

Say you have an array of int (in any language with fixed size ints). How would you calculate the int closest to their mean?
Edit: to be clear, the result does not have to be present in the array. That is, for the input array [3, 6, 7] the expected result is 5. Also I guess we need to specify a particular rounding direction, so say round down if you are equally close to two numbers.
Edit: This is not homework. I haven't had homework in five years. And this is my first time on stackoverflow, so please be nice!
Edit: The obvious approach of summing up and dividing may overflow, so I'm trying to think of an approach that is overflow safe, for both large arrays and large ints. I think handling overflow correctly (without cheating and using a different type) is by far the hardest part of this problem.
Here's a way that's fast, reasonably overflow-safe and can work when the number of elements isn't known in advance.
// The length of someListOfNumbers doesn't need to be known in advance.
int mean(SomeType someListOfNumbers) {
double mean = 0, count = 0;
foreach(element; someListOfNumbers) {
count++;
mean += (element - mean) / count;
}
if(count == 0) {
throw new UserIsAnIdiotException(
"Problem exists between keyboard and chair.");
}
return cast(int) floor(mean);
}
Calculate the sum by adding the numbers up, and dividing by the number of them, with rounding:
mean = (int)((sum + length/2) / length;
If you are worried about overflow, you can do something like:
int mean = 0, remainder = 0
foreach n in number
mean += n / length
remainder += n % length
if remainder > length
mean += 1
remainder -= length
if remainder > length/2
mean += 1
print "mean is: " mean
note that this isn't very fast.
um... how about just calculating the mean and then rounding to an integer? round(mean(thearray)) Most languages have facilities that allow you to specify the rounding method.
EDIT: So it turns out that this question is really about avoiding overflow, not about rounding. Let me be clear that I agree with those that have said (in the comments) that it's not something to worry about in practice, since it so rarely happens, and when it does you can always get away with using a larger data type.
I see that several other people have given answers that basically consist of dividing each number in the array by the count of the array, then adding them up. That is also a good approach. But just for kicks, here's an alternative (in C-ish pseudocode):
int sum_offset = 0;
for (int i = 1; i < length(array); i++)
sum_offset += array[i] - array[i-1];
// round by your method of choice
int mean_offset = round((float)sum_offset / length(array));
int mean = mean_offset + array[0];
Or another way to do the same thing:
int min = INT_MAX, max = INT_MIN;
for (int i = 0; i < length(array); i++) {
if (array[i] < min) min = array[i];
if (array[i] > max) max = array[i];
}
int sum_offset = max - min;
// round by your method of choice
int mean_offset = round((float)sum_offset / length(array));
int mean = mean_offset + min;
Of course, you need to make sure sum_offset does not overflow, which can happen if the difference between the largest and smallest array elements is larger than INT_MAX. In that case, replace the last four lines with something like this:
// round by your method of choice
int mean_offset = round((float)max / length(array) - (float)min / length(array));
int mean = mean_offset + min;
Trivia: this method, or something like it, also works quite well for mentally computing the mean of an array whose elements are clustered close together.
Guaranteed not to overflow:
length ← length of list
average ← 0
for each result in the list do:
average ← average + ( result / length )
end for
This has significant problems with accuracy if you're using ints due to truncation (the average of six 4's comes out as 0)
Welcome. fish, hope your stay is a pleasant one.
The following pseudo-code shows how to do this in the case where the sum will fit within an integer type, and round rounds to the nearest integer.
In your sample, the numbers add sum to 16, dividing by 3 gives you 5 1/3, which rounds to 5.
sum = 0
for i = 1 to array.size
sum = sum + array[i]
sum = sum / array.size
sum = round (sum)
This pseudocode finds the average and covers the problem of overflow:
double avg = 0
int count = 0
for x in array:
count += 1
avg = avg * (count - 1) / count // readjust old average
avg += x / count // add in new number
After that, you can apply your rounding code. If there is no easy way to round in your language, then something like this will work (rounds up when over .5):
int temp = avg - int(avg) // finds decimal portion
if temp <= 0.5
avg = int(avg) // round down
else
avg = int(avg) + 1 // round up
Pseudocode for getting the average:
double mean = 0
int count = 0
foreach int number in numbers
count++
mean += number - mean / count
round(mean) // rounds up
floor(mean + 0.5) // rounds up
ceil(mean - 0.5) // rounds down
Rounding generally involves adding 0.5, then truncating (floor), which is why 3.5 rounds up to 4. If you want 3.5 to round down to 3, do the rounding code yourself, but in reverse: subtract 0.5, then find the ceiling.
Edit: Updated requirements (no overflow)
ARM assembly. =] Untested. Won't overflow. Ever. (I hope.)
Can probably be optimized a bit. (Maybe use FP/LR?) =S Maybe THUMB will work better here.
.arm
; r0 = pointer to array of integers
; r1 = number of integers in array
; returns mean in r0
mean:
stmfd sp!, {r4,r5}
mov r5, r1
mov r2, 0 ; sum_lo
mov r3, 0 ; sum_hi
cmp r1, 0 ; Check for empty array
bz .end
.loop:
ldr r4, [r0], #4
add r2, r2, r4
adc r3, r3, #0 ; Handle overflow
sub r1, r1, #1 ; Next
bnz .loop
.end:
div r0, r2, r3, r5 ; Your own 64-bit/32-bit divide: r0 = (r3r2) / r5
bx lr

What's the probability that X *consecutive* bits in an array of N bits is set to 1?

I'm trying to code a simple, sufficiently accurate filter for validating a piece of hardware in an RTL simulation. We're simulating the randomness inherent in a chip's flip-flops, by randomly initializing all the flip-flops in the design to either 0 or 1. This corresponds to the chip's flip-flops getting some random value during power-up. We're also randomizing the flops in the reset tree ( where reset tree has no feedback loops ), which means that you can get false glitching on your reset lines.
e.g.
|||
VVV Nth reset-tree flop
+----+ +----+ +----+ / / +----+
reset_in | | 0 | | 1 | | 0 / / | | reset_out
-------->D Q>----->D Q>----->D Q>---- / ... / -->D Q>----
| | | | | | \ \ | |
| | | | | | \ \ | |
+^---+ +^---+ +^---+ / / +^---+
| | | / / |
clk ------+------------+------------+---------/ / ---+
You'll see a 0->1->0 which looks like a reset, but is really a glitch.
I want to build a filter that looks for a certain number of consecutive 1 values to determine whether the reset I just saw was the reset coming from the reset controller or a spurious reset.
I know this is statistics and maybe related to the Poisson distribution, but how do I determine the probability that any X consecutive bits in a set of N bits are 1?
P.S. Yes. I am aware of 4-val RTL simulation. We're doing that also, but some Verilog constructs don't have sufficient pessimism when propagating X's and Z's.
EDIT: The below doesn't answer the question, sorry... Comment clarified that the real problem is about the probability of x consecutive 1s out of n bits, not just the simple thing I assumed.
Had a quick look at this: http://www.mathhelpforum.com/math-help/probability-statistics/64519-probability-consecutive-wins.html which may be what you are looking for - it seems to deal with working out the probability of a run of toin cosses out of a larger population of toin cosses, so sounds similar. But its late and I am tired so I haven't decoded the math :)
OBSOLETE:
It sounds like you are basically dealing with binominal probability - see http://en.wikipedia.org/wiki/Binomial_probability.
I have to admit I haven't done the calculations for about 20 years, so somewhat rusty...
Basically, binominal allows you to "add together" the probability of an event occuring multiple times, where there is only two possible outcomes each time.
Order is significant in your case so it should be as simple as multiplying the probabilites;
For 1 bit it is 50%
For 2 bits it is 50%^2 = 25%
For 3 bits it is 50%^3 = 12.5%
Look at it another way;
1 bit only has 2 possible combinations, one of which is all 1s = 50%
2 bits have 4 possible combinations (10, 01, 11, 00), only one of which is all 1s - so 25%
3 bit have 2^3 = 8 possible combinations, only one of which is all 1s, so 1/8 = 12.5%
So... probability of n bits all being 1 = 1/(2^n).
If you want a quick test to see if a sequence of bits is random based on the longest streak of 1's, you can use the fact that the expected longest streak of 1's in N bits is Θ(log(N)).
Furthermore, the probability that the longest streak exceeds r*log₂(N) bits is at most 1/N^(r-1), and similarly the probability that the longest streak is less than log₂(N)/r bits is at most 1/N^(r-1).
These results are derived in the section on "Streaks" in the chapter on "Counting and Probability" in Introduction to Algorithms
OK, here's what I found:
P = 1 - Q(X)
where
Q(X) = [1 - 1/2(Z)]/[(X + 1 - XZ) x 1/2 x Z^(X+1)]
where
Z = 1 + (1/2)(1/2)^X + (X+1)[(1/2)(1/2)^X]^2 + ...
The link with some of the math is here:
Math Forum
you can do a recursive program (python):
prob (x,n) gives your desired result
import math
def prob(x,n,i=0):
if i == x: return 1
if (x+i) > n: return 0
t = .5 * prob(x,n-1,i+1) + .5 * prob(x,n-1,i)
return t
My approach to this would be to define a FSA that accepts bit patterns of the correct type, and then simulate the pattern for each number of bits. i.e.
State state_map[] = {
0 => { 0 -> 0; 1 -> 1; accepts = false },
1 => { 0 -> 0; 1 -> 2; accepts = false },
2 => { 0 -> 0; 1 -> 3; accepts = false },
3 => { 0 -> 3; 1 -> 3; accepts = true }
};
state[t: 0, s: 0] = 1.0;
state[t: 0, s: 1] = 0.0;
state[t: 0, s: 2] = 0.0;
state[t: 0, s: 3] = 0.0;
for (t = 0; t < N; t++)
for (s = 0; s<NUM_STATES; s++)
state[t: t+1, s: state_map[s].0] += state[t, s] * .5
state[t: t+1, s: state_map[s].1] += state[t, s] * .5
print "Probability: {0}", state[t: N, s: 3],

Resources