Agents moving along a gradient - gradient

I want to create a situation where the turtles check their previous patch with the patch they just moved to, if the new patch has a higher c value then the turtle will use the new_p1 in its calculation to switch between status 0 or 1 (this is modelling tumbling and running of e coli). After deciding to stay running (0) or switch to tumbling (1) it should update it's oldc value in order to make its decision for further moves. The turtles are also assigned either 0 or 1 status on spawn based on a calculation of equilibrium. My issue is that running the program I do not see the turtles accumulating on the right as they are supposed to (I've created a gradient along each patch where the further right the higher c value the patch has)
ask turtles [
if (status = 0)
[
fd 0.3
set heading heading + 10 * (2 * random-float 1.0 - 1.0)
set rsq xcor * xcor + ycor * ycor
set msq msq + rsq
ifelse (c > oldc)
[if ( random-float 100 < new_p1 ) [set status 1]][if ( random-float 100 < p1 ) [set status 1]]
set oldc c
]
fd 0.02
set heading heading + 180 * (2 * random-float 1.0 - 1.0)
set rsq xcor * xcor + ycor * ycor
set msq msq + rsq
if ( random-float 100 < p2 ) [set status 0]
set oldc c
]

I found the problem, in this case I should be using an ifelse instead of an if as it allows the tumble procedure to proceed after the run procedure has been run
ask turtles [
ifelse (status = 0)
[
fd 0.3
set heading heading + 10 * (2 * random-float 1.0 - 1.0)
set rsq xcor * xcor + ycor * ycor
set msq msq + rsq
ifelse (c > oldc)
[if ( random-float 100 < new_p1 ) [set status 1]][if ( random-float 100 < p1 ) [set status 1]]
set oldc c
]
[
fd 0.02
set heading heading + 180 * (2 * random-float 1.0 - 1.0)
set rsq xcor * xcor + ycor * ycor
set msq msq + rsq
if ( random-float 100 < p2 ) [set status 0]
set oldc c
]

Related

Debugging old Fortran code for sediment dynamics

I am looking at some Fortran code from an old scanned paper. The scan quality is not great so I may have copied it wrong. I tried to run this using an online Fortran compiler but it bombs out. Not being familiar with Fortran, I was wondering if someone can point out where the syntax does not make sense? The code is from a paper on sediment dynamics:
Komar, P.D. and Miller, M.C., 1975. On the comparison between the threshold of sediment motion under waves and unidirectional currents with a discussion of the practical evaluation of the threshold: Reply. Journal of Sedimentary Research, 45(1).
PROGRAM TSHOLD
REAL LI, LO
G = 981.0
PIE = 3.1416
RHOW = 1.00
READ (6O,1) DIAM, RHOS
1 FORMAT (2X, F6.3,2X, F5.3)
IF(DIAM .LT. 0.05) GO TO 5
A = 0.463 * PIE
B = 0.25
GO TO 7
5 A = 0.21
B = 0.50
7 PWR = 1.0 / (2.0 - B)
FAC = (A * (RHOS - RHOW) * G/(RHOW * PIE**B))**PWR
FAC1 = FAC * DIAM**((1.0 - B) * PWR)
T = 1.0
15 J = 1.20
LD = 156.13 * (T**2)
UM = FAC1 * T**(B*PWR)
WRITE(61,9) DIAM, T, UM
9 FORMAT(1H0, 10X, 17HGRAIN DIAMETER = ,F6.3,1X,2HCM //
1 11X, 14HWAVE PERIOD = ,F5.2, 1X, 3HSEC //
2 11X, 22HORBITAL VELOCITY, UM = ,F6.2, 1X, 6HCM/SECl //
3 20X, 6HHEIGHT, 5X, 5HDEPTH, 8X, 3HH/L, 6X, 7HH/DEPTH //
4 22X, 2HCM, 8X, 2HCM /)
C INCREMENT WAVE HEIGHT, CALCULATE DEPTH
H = 10.0
DO 12 K = 1.60
SING = PIE * H / (UM * T)
X = SING
IF(X.LT.1.0) GO TO 30
30 ASINH = X - 0.16666*X**3.0 + 0.07500* X ** 5.0 - 0.04464 * X ** 7.0
1 + 0.03038 * X ** 9.0 - 0.02237 * X ** 11.0
32 LI = LD * (SINH(ASINH)/COSH(ASINH))
OPTH = ASINH * LI / 6.2832
C CHECK WAVE STABILITY
RATIO = H / DPTH
IF(RATIO.GE.0.78) GO TO 11
STEEP = H / LI
TEST = 0.142 * (SINH(ASINH)/COSH(ASINH))
IF(STEEP.GE.TEST) GO TO 11
WRITE(61,10) H, OPTH, STEEP, RATIO
I0 FORMAT(IH0, 20X, F5.1, 4X, E9.3, 4X, F5.3, 4X, F4.2)
11 H = H + 10.0
12 CONTINUE
T = T + 1.0
15 CONTINUE
END
The problem is more likely that old Fortran requires fixed form code formatting where the number of spaces before a statement is very important.
Here are some general rules
Normal statements start at column 7 and beyond
Lines cannot exceed 72 columns
Any character placed on column 6 indicates the line is a continuation from the line above. I see that on the code above in the lines following 9 FORMAT(..
A number placed between columns 1-5 indicates a label, which can be a target of a GO TO statement, a DO statement or a formatting specification.
The character C on the first column, and sometimes any character on the first column indicate the line is a comment line.
see https://people.cs.vt.edu/~asandu/Courses/MTU/CS2911/fortran_notes/node4.html for more info.
Based on the rules above, here is how to enter the code, with the correct spacing. I run the F77 code through a converter to make it compatible with F90 and F77 at the same time. The code below might compile with the online compiler now.
PROGRAM TSHOLD
REAL LI, LO
G = 981.0
PIE = 3.1416
RHOW = 1.00
READ (60,1) DIAM, RHOS
1 FORMAT (2X, F6.3,2X, F5.3)
IF(DIAM .LT. 0.05) GO TO 5
A = 0.463 * PIE
B = 0.25
GO TO 7
5 A = 0.21
B = 0.50
7 PWR = 1.0 / (2.0 - B)
FAC = (A * (RHOS - RHOW) * G/(RHOW * PIE**B))**PWR
FAC1 = FAC * DIAM**((1.0 - B) * PWR)
T = 1.0
DO 15 J=1,20
LD = 156.13 * (T**2)
UM = FAC1 * T**(B*PWR)
WRITE(61,9) DIAM, T, UM
9 FORMAT(1H0, 10X, 17HGRAIN DIAMETER = ,F6.3,1X,2HCM // &
& 11X, 14HWAVE PERIOD = ,F5.2, 1X, 3HSEC // &
& 11X, 22HORBITAL VELOCITY, UM = ,F6.2, 1X, 6HCM/SECl // &
& 20X, 6HHEIGHT, 5X, 5HDEPTH, 8X, 3HH/L, 6X, 7HH/DEPTH // &
& 22X, 2HCM, 8X, 2HCM /)
! INCREMENT WAVE HEIGHT, CALCULATE DEPTH
H = 10.0
DO 12 K = 1,60
SING = PIE * H / (UM * T)
X = SING
IF(X.LT.1.0) GO TO 30
30 ASINH = X - 0.16666*X**3.0 + 0.07500* X ** 5.0 - 0.04464 * X ** 7.&
& + 0.03038 * X ** 9.0 - 0.02237 * X ** 11.0
32 LI = LD * (SINH(ASINH)/COSH(ASINH))
OPTH = ASINH * LI / 6.2832
! CHECK WAVE STABILITY
RATIO = H / DPTH
IF(RATIO.GE.0.78) GO TO 11
STEEP = H / LI
TEST = 0.142 * (SINH(ASINH)/COSH(ASINH))
IF(STEEP.GE.TEST) GO TO 11
WRITE(61,10) H, OPTH, STEEP, RATIO
10 FORMAT(G14.4, 20X, F5.1, 4X, E9.3, 4X, F5.3, 4X, F4.2)
11 H = H + 10.0
12 CONTINUE
T = T + 1.0
15 CONTINUE
END
I found several transcription errors, replacing commas with dots, zeros with the letter O, and a missing DO statement.

Why add a small number on the bounding box?

I found that on the implementation of Fast(er) RCNN, there is always a small value added to the width and height of the bounding box. Why add a small number to the width and height?
For example, in Fast RCNN, cfg.EPS (default is 1e-14) is added:
ex_widths = ex_rois[:, 2] - ex_rois[:, 0] + cfg.EPS
ex_heights = ex_rois[:, 3] - ex_rois[:, 1] + cfg.EPS
ex_ctr_x = ex_rois[:, 0] + 0.5 * ex_widths
ex_ctr_y = ex_rois[:, 1] + 0.5 * ex_heights
gt_widths = gt_rois[:, 2] - gt_rois[:, 0] + cfg.EPS
gt_heights = gt_rois[:, 3] - gt_rois[:, 1] + cfg.EPS
gt_ctr_x = gt_rois[:, 0] + 0.5 * gt_widths
gt_ctr_y = gt_rois[:, 1] + 0.5 * gt_heights
In Faster-RCNN, 1.0 is added to widths and heights.
ex_widths = ex_rois[:, 2] - ex_rois[:, 0] + 1.0
ex_heights = ex_rois[:, 3] - ex_rois[:, 1] + 1.0
ex_ctr_x = ex_rois[:, 0] + 0.5 * ex_widths
ex_ctr_y = ex_rois[:, 1] + 0.5 * ex_heights
gt_widths = gt_rois[:, 2] - gt_rois[:, 0] + 1.0
gt_heights = gt_rois[:, 3] - gt_rois[:, 1] + 1.0
gt_ctr_x = gt_rois[:, 0] + 0.5 * gt_widths
gt_ctr_y = gt_rois[:, 1] + 0.5 * gt_heights
I don’t know what is happening in the first case, but in the second case looks like the left and right locations are both inside the bounding box. The number of pixels spanned must therefore include both left and right locations. This is why 1 is added.
I have a strong feeling the code will continue with the areas of the boxes and use those for calculating the IoU. If so, you need to be sure the bounding box actually has some non-zero area.
My opinion.Actually,The pixels on the "bounding box border" are need to be calculated.SO you need to exclude them(by add 1).

Hoping to fast speed of reverse sort list

*When there are 3 thousand patches,the speed of netlogo is normal. But when I change the size of world(99*99), the speed is too slow about 5 minutes update 10 tick. I am eager to improve the speed of it. The following is the code.
to publish
set contribution_list ( reverse sort [cumulative-contribution] of patches)
let m count patches
if contribution > item (round( m * shibei-proportion) ) contribution_list
[set pcolor blue + 3]
if contribution > item (round( m * (shibei-proportion + bian-proportion)) ) contribution_list
[set pcolor blue + 2]
if contribution > item (round( m * (shibei-proportion + bian-proportion + dahongbao-proportion))) contribution_list
[set pcolor blue + 1]
set cumulative-contribution 0
end

Dynamic list in netlogo

I was unsure how to title this question, if somebody knows a more specific title, I'm happy to change it
I'm trying to develop a model in netlogo for my thesis where turtles buy water from 18 different wells. Each of the turtles has its distance to the individual wells stored in the breeds-own variable(s) adist_w_1 ,adist_w_2, ... etc.
What I want to do is model the consumption decisions of commercial establishments by first calculating the price of water (constant + x*adist_w_y), then figure out what the demand is at this price and subtract the demands at cheaper wells from this specific well.
price = 0.75 +0.15 * distance;
individual_demand_at_well_x = f (price_at_well) - demands_at_cheaper_wells
What I've done so far to this regard looks like this:
to calc-price-at-well
set earlier-demands 0
ask commercials [
let price_w_1 ((adist_w_1 / 1000) * 0.15 + 0.75 )
let price_w_2 ((adist_w_2 / 1000) * 0.15 + 0.75 )
let price_w_3 ((adist_w_3 / 1000) * 0.15 + 0.75 )
let price_w_4 ((adist_w_4 / 1000) * 0.15 + 0.75 )
let price_w_5 ((adist_w_5 / 1000) * 0.15 + 0.75 )
let price_w_6 ((adist_w_6 / 1000) * 0.15 + 0.75 )
let price_w_7 ((adist_w_7 / 1000) * 0.15 + 0.75 )
let price_w_8 ((adist_w_8 / 1000) * 0.15 + 0.75 )
let price_w_9 ((adist_w_9 / 1000) * 0.15 + 0.75 )
let price_w_10 ((adist_w_10 / 1000) * 0.15 + 0.75 )
let price_w_11 ((adist_w_11 / 1000) * 0.15 + 0.75 )
let price_w_12 ((adist_w_12 / 1000) * 0.15 + 0.75 )
let price_w_13 ((adist_w_13 / 1000) * 0.15 + 0.75 )
let price_w_14 ((adist_w_14 / 1000) * 0.15 + 0.75 )
let price_w_15 ((adist_w_15 / 1000) * 0.15 + 0.75 )
let price_w_16 ((adist_w_16 / 1000) * 0.15 + 0.75 )
let price_w_17 ((adist_w_17 / 1000) * 0.15 + 0.75 )
let price_w_18 ((adist_w_18 / 1000) * 0.15 + 0.75 )
let demand_w_1 5 * price_w_1 ;DUMMY! include demand function of price
let demand_w_2 5 * price_w_2
let demand_w_3 5 * price_w_3
let demand_w_4 5 * price_w_4
let demand_w_5 5 * price_w_5
let demand_w_6 5 * price_w_6
let demand_w_7 5 * price_w_7
let demand_w_8 5 * price_w_8
let demand_w_9 5 * price_w_9
let demand_w_10 5 * price_w_10
let demand_w_11 5 * price_w_11
let demand_w_12 5 * price_w_12
let demand_w_13 5 * price_w_13
let demand_w_14 5 * price_w_14
let demand_w_15 5 * price_w_15
let demand_w_16 5 * price_w_16
let demand_w_17 5 * price_w_17
let demand_w_18 5 * price_w_18
let demand-list (list demand_w_1 demand_w_2 demand_w_3 demand_w_4 demand_w_5 demand_w_6 demand_w_7 demand_w_8 demand_w_9 demand_w_10 demand_w_11 demand_w_12 demand_w_13 demand_w_14 demand_w_15 demand_w_16 demand_w_17 demand_w_18)
foreach sort demand-list
[
let cheapest-well item 0 demand-list
set final_t_dem (cheapest-well - earlier-demands)
set earlier-demands (earlier-demands + cheapest-well)
set demand-list remove cheapest-well demand-list
]
]
*whereas earlier-demands is a global, final_t_dem a commercials-own
This hopefully yields the cheapest well and reiterates until all wells are "treated". But now I'm clueless as to how I can extract the information which well gets which demand from individual turtles and, this is the goal, to sum them up.
In the end, I'd like to be able to say that commercial xy has an individual demand of x for well 1 and all commercials together have a demand of y.
I'd be glad to get advice and since I'm new to netlogo also an idea if this is a smart way to go with regard to model efficiency. Many thanks!

How to convert triangular matrix indexes in to row, column coordinates?

I have these indexes:
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,etc...
Which are indexes of nodes in a matrix (including diagonal elements):
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21
etc...
and I need to get i,j coordinates from these indexes:
1,1
2,1 2,2
3,1 3,2 3,3
4,1 4,2 4,3 4,4
5,1 5,2 5,3 5,4 5,5
6,1 6,2 6,3 6,4 6,5 6,6
etc...
When I need to calculate coordinates I have only one index and cannot access others.
Not optimized at all :
int j = idx;
int i = 1;
while(j > i) {
j -= i++;
}
Optimized :
int i = std::ceil(std::sqrt(2 * idx + 0.25) - 0.5);
int j = idx - (i-1) * i / 2;
And here is the demonstration:
You're looking for i such that :
sumRange(1, i-1) < idx && idx <= sumRange(1, i)
when sumRange(min, max) sum integers between min and max, both inxluded.
But since you know that :
sumRange(1, i) = i * (i + 1) / 2
Then you have :
idx <= i * (i+1) / 2
=> 2 * idx <= i * (i+1)
=> 2 * idx <= i² + i + 1/4 - 1/4
=> 2 * idx + 1/4 <= (i + 1/2)²
=> sqrt(2 * idx + 1/4) - 1/2 <= i
In my case (a CUDA kernel implemented in standard C), I use zero-based indexing (and I want to exclude the diagonal) so I needed to make a few adjustments:
// idx is still one-based
unsigned long int idx = blockIdx.x * blockDim.x + threadIdx.x + 1; // CUDA kernel launch parameters
// but the coordinates are now zero-based
unsigned long int x = ceil(sqrt((2.0 * idx) + 0.25) - 0.5);
unsigned long int y = idx - (x - 1) * x / 2 - 1;
Which results in:
[0]: (1, 0)
[1]: (2, 0)
[2]: (2, 1)
[3]: (3, 0)
[4]: (3, 1)
[5]: (3, 2)
I also re-derived the formula of Flórez-Rueda y Moreno 2001 and arrived at:
unsigned long int x = floor(sqrt(2.0 * pos + 0.25) + 0.5);
CUDA Note: I tried everything I could think of to avoid using double-precision math, but the single-precision sqrt function in CUDA is simply not precise enough to convert positions greater than 121 million or so to x, y coordinates (when using 1,024 threads per block and indexing only along 1 block dimension). Some articles have employed a "correction" to bump the result in a particular direction, but this inevitably falls apart at a certain point.