How to optimize the code to make the setup faster - graphics

I am facing a problem in terms of setup time. I have created a model where patches are highlighted using the following code:
ask patches [set pcolor scale-color gray proportion 0 max-value ]
I also have a switch whose purpose when true to is to do the following:
ask patches [ if switch? [set pcolor [color] of closest-turtle ]]
Every time i press the setup/go buttons in the interface it is very slow. I initially thought it might be due to the complexity of the model and checked for it but doesn't seem to be the case. It's being more likely due to the switch and so removed the switch and just went with the below setup but it still is causing a delay
ask patches [ set pcolor [color] of closest-turtle ]
Is there a way to get around this. I currently have to save the model, close it and open it again every-time i make a change.
Thanks in advance, appreciate the help!!
Below is my complete code:
breed [ parties party ]
globals [
total-votes
max-voteshare
largest-party
]
parties-own [
my-size
my-old-size
my-rule
my-benefit
my-benefit-chen
]
patches-own [
votes
vote-share
closest-party
closest-party-dist
nearest-neighbors
nearest-neighbors-dist
b
farthest-party
farthest-party-dist
b-c
f
h
votes-with-benefit
]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setup
clear-all
reset-ticks
create-voters
setup-parties
update-support
;update-voter-totals
setup-plot
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to create-voters
ask patches [
let x1 (pxcor - pop1-econ-mean) / sd-pop1
let y1 (pycor - pop1-soc-mean) / sd-pop1
;;set votes (voter-population / 2) * (red-size) * exp (-0.5 * ( x1 ^ 2 + y1 ^ 2)) / (2 * pi * sd-red ^ 2)
set votes ( (pop1) * exp (-0.5 * ( x1 ^ 2 + y1 ^ 2)) / (2 * pi * sd-pop1 ^ 2) )
let x2 (pxcor - pop2-econ-mean) / sd-pop2
let y2 (pycor - pop2-soc-mean) / sd-pop2
;set votes (votes) + (voter-population / 2) * (blue-size) * exp (-0.5 * ( x2 ^ 2 + y2 ^ 2)) / (2 * pi * sd-blue ^ 2) ]
set votes ((votes) + ( (pop2) * exp (-0.5 * ( x2 ^ 2 + y2 ^ 2)) / (2 * pi * sd-pop2 ^ 2) ))
set votes-with-benefit votes
]
set total-votes sum [ votes-with-benefit ] of patches
print (word "Max votes at one point = " precision (max[votes] of patches) 2)
print (word "Min vote at one point = " precision (min[votes] of patches) 2)
print (word "Max votes at one point = " precision (max[votes-with-benefit] of patches) 2)
print (word "Min vote at one point = " precision (min[votes-with-benefit] of patches) 2)
print (word "Total votes = " round(total-votes))
ask patches [set vote-share (votes-with-benefit / total-votes)]
set max-voteshare (max[vote-share] of patches)
ask patches [set pcolor scale-color gray vote-share 0 max-voteshare ]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setup-parties
create-parties 1 [set color red set label-color red set label who + 1 set size 3 setxy party1-left-right party1-lib-con ]
create-parties 1 [set color green set label-color red set label who + 1 set size 3 setxy party2-left-right party2-lib-con ]
if Num-of-parties >= 3
[ create-parties 1 [set color blue set label-color red set label who + 1 set size 3 setxy party3-left-right party3-lib-con ] ]
if Num-of-parties >= 4
[ create-parties 1 [set color orange set label-color red set label who + 1 set size 3 setxy party4-left-right party4-lib-con ] ]
if Num-of-parties >= 5
[ create-parties 1 [set color brown set label-color red set label who + 1 set size 3 setxy party5-left-right party5-lib-con ] ]
if Num-of-parties >= 6
[ create-parties 1 [set color yellow set label-color red set label who + 1 set size 3 setxy party6-left-right party6-lib-con ] ]
if Num-of-parties >= 7
[ create-parties 1 [set color lime set label-color red set label who + 1 set size 3 setxy party7-left-right party7-lib-con ] ]
if Num-of-parties >= 8
[ create-parties 1 [set color turquoise set label-color red set label "8" set size 3 setxy party8-left-right party8-lib-con ] ]
if Num-of-parties >= 9
[ create-parties 1 [set color cyan set label-color red set label who + 1 set size 3 setxy party9-left-right party9-lib-con ] ]
if Num-of-parties >= 10
[ create-parties 1 [set color magenta set label-color red set label who + 1 set size 3 setxy party10-left-right party10-lib-con ] ]
ask parties [ update-rule set my-old-size 1 set shape "default" set heading random-float 360]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to update-support
ask patches [ set closest-party min-one-of parties [distance myself]
set closest-party-dist [distance myself] of closest-party
set farthest-party max-one-of parties [distance myself]
set farthest-party-dist [distance myself] of farthest-party
set f ( -1 / ([my-old-size] of closest-party / total-votes) ) * (closest-party-dist + 0.0000000001)
set h ([my-old-size] of farthest-party / total-votes) * (farthest-party-dist ^ 2)
set b-c (f + h)
]
ask parties [set my-size sum [votes-with-benefit] of patches with [closest-party = myself]
set my-benefit mean[b] of patches with [closest-party = myself]
set my-benefit-chen mean[b-c] of patches with [closest-party = myself]
]
ask patches with [votes-with-benefit > 0.001] [ ifelse (b-c <= threshold)
[ set votes-with-benefit 0 set pcolor black ]
[set votes-with-benefit votes
set pcolor [color] of min-one-of parties [distance myself]
]
]
set largest-party max-one-of parties [my-size]
;ask patches with [votes-with-benefit >= 0.001] [ set pcolor [color] of closest-party ]
;ask patches [ set pcolor [color] of closest-party ]
;ask patches [set pcolor [color] of min-one-of turtles [distance myself]]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to update-rule
ask turtle 0 [set my-rule party1-rule ]
ask turtle 1 [set my-rule party2-rule ]
if Num-of-parties >= 3
[ ask turtle 2 [set my-rule party3-rule ] ]
if Num-of-parties >= 4
[ ask turtle 3 [set my-rule party4-rule ] ]
if Num-of-parties >= 5
[ ask turtle 4 [set my-rule party5-rule ] ]
if Num-of-parties >= 6
[ ask turtle 5 [set my-rule party6-rule ] ]
if Num-of-parties >= 7
[ ask turtle 6 [set my-rule party7-rule ] ]
if Num-of-parties >= 8
[ ask turtle 7 [set my-rule party8-rule ] ]
if Num-of-parties >= 9
[ ask turtle 8 [set my-rule party9-rule ] ]
if Num-of-parties >= 10
[ ask turtle 9 [set my-rule party10-rule ] ]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to adapt
if (my-rule = "hunter") [hunt]
if (my-rule = "aggregator") [aggregate]
if (my-rule = "predator") [prey]
end
to hunt
ifelse (my-size > my-old-size) [jump 1] [set heading heading + 90 + random-float 180 jump 1]
;set my-old-size my-size
end
to aggregate
if (my-size > 0)
[
set xcor (sum [votes * pxcor] of patches with [closest-party = myself] / my-size)
set ycor (sum [votes * pycor] of patches with [closest-party = myself] / my-size)
]
end
to prey
if (my-size < [my-size] of largest-party) [face largest-party jump 1]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to intermediate-steps
ask parties [adapt]
update-support
ask turtles [ set my-old-size my-size]
end
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
to setup-plot
set-current-plot "Voter Turnout"
;set-current-plot "Voter Benefit"
set-current-plot "Distribution of benefit across voters"
end
to update-turnout-plot
set-current-plot "Voter Turnout"
set-current-plot-pen "Party1"
plot 100 * [my-size] of turtle 0 / total-votes
set-current-plot-pen "Party2"
plot 100 * [my-size] of turtle 1 / total-votes
if Num-of-parties >= 3 [ set-current-plot-pen "Party3"
plot 100 * [my-size] of turtle 2 / total-votes ]
if Num-of-parties >= 4 [ set-current-plot-pen "Party4"
plot 100 * [my-size] of turtle 3 / total-votes ]
if Num-of-parties >= 5 [set-current-plot-pen "Party5"
plot 100 * [my-size] of turtle 4 / total-votes]
if Num-of-parties >= 6 [set-current-plot-pen "Party6"
plot 100 * [my-size] of turtle 5 / total-votes]
if Num-of-parties >= 7 [set-current-plot-pen "Party7"
plot 100 * [my-size] of turtle 6 / total-votes]
if Num-of-parties >= 8 [set-current-plot-pen "Party8"
plot 100 * [my-size] of turtle 7 / total-votes]
if Num-of-parties >= 9 [set-current-plot-pen "Party9"
plot 100 * [my-size] of turtle 8 / total-votes]
if Num-of-parties >= 10 [set-current-plot-pen "Party10"
plot 100 * [my-size] of turtle 9 / total-votes]
end
to update-b-chen
set-current-plot "Distribution of benefit across voters"
set-current-plot-pen "patches"
histogram [b-c] of patches
end
to go
intermediate-steps
update-turnout-plot
update-b-chen
tick
end

This is a bit after the fact but, in addition to the comments already posted, your switch code is a bit inefficient and could be optimized.
ask patches [ if switch? [set pcolor [color] of closest-turtle ]]
This tells every patch to check if the switch is on, then to make a decision. A more efficient way to code this would be:
if switch? TRUE [ask patches[set pcolor [color] of closest-turtle]]
This tells the observer to check the switch once (instead of once per patch) then tell the patches to do stuff. Not the full efficiency issue, but part of it

Related

how to set an " attraction" value or levels to certain patch colors Netlogo

I'm fairly new with coding and Netlogo. I hope someone could help me. I have tried and checked different models in the models library and samples in the internet. I still can't figure it out
So, my question are as follows:
Is there a way to set a value to a certain patch color? to be able to attract the turtle to that patch color
eg. I want the pcolor = orange to have an attraction level of 5 and 10 for pcolor = yellow
If the value of the pcolor is already set, how to make turtles stay on the patch?
eg. since pcolor = yellow 's attraction level is 10, let the turtles stay for 10 ticks), so turtles will stay on patch longer
I can already make the turtles go to the patches with orange and yellow..
here's my code:
to go
if turtles = 0
[ stop ]
ask turtles
[
navigate
attract
]
if ticks > 120 [ stop ]
tick
end
to navigate
facexy exit-x exit-y
if any? neighbors with [ pcolor = gray - 3 ]
[ die ]
ifelse any? neighbors with [ pcolor = gray or pcolor = orange or pcolor = yellow or pcolor = red or pcolor = black ]
[
facexy exit-x exit-y
]
[ rt random-float visitor-view-angle lt random-float visitor-view-angle ]
fd .5
end
to attract
;; awareness zone
if pxcor >= -4
and pycor >= 9
and pxcor <= 4
and pycor <= 15
[fd 0.5]
;;attraction zone
if pxcor >= -4
and pycor >= -8
and pxcor <= 4
and pycor <= 8
[ rt random-float visitor-view-angle lt random-float visitor-view-angle ]
fd 0.5
ifelse any? patches with [ pcolor = orange or pcolor = orange or pcolor = yellow or pcolor = red ]
[set heading towards one-of patches with [ pcolor = orange or pcolor = yellow or pcolor = red]]
[fd 0.5]
ifelse pxcor >= -4
and pycor >= -15
and pxcor <= 4
and pycor <= -9
[facexy exit-x exit-y]
[fd 0.5]
end

How to use numpy to speed up code that calculates center of mass?

I made a small block of code that - given n objects of specified masses and vector coordinates over time - will calculate the center of mass. I think the code looks clunky (it uses 3 for-loops), and was wondering if there were numpy methods to vectorize (or at least speed up) this method. As a note, the use of the class Body could probably be averted for this task, but is used in other relevant code not shown here.
import numpy as np
class Body():
def __init__(self, mass, position):
self.mass = mass
self.position = position
def __str__(self):
return '\n .. mass:\n{}\n\n .. position:\n{}\n'.format(self.mass, self.position)
Three objects are initialized.
mass = 100 # same for all 3 objects
ndim = 3 # 3 dimensional space
nmoments = 10 # 10 moments in time
## initialize bodies
nelems = ndim * nmoments
x = np.arange(nelems).astype(int).reshape((nmoments, ndim))
A = Body(mass, position=x)
B = Body(mass, position=x / 2.)
C = Body(mass, position=x * 2.)
bodies = [A, B, C]
total_mass = sum([body.mass for body in bodies])
# print("\n ** A **\n{}\n".format(A))
# print("\n ** B **\n{}\n".format(B))
# print("\n ** C **\n{}\n".format(C))
## get center of mass
center_of_mass = []
for dim in range(ndim):
coms = []
for moment in range(nmoments):
numerator = 0
for body in bodies:
numerator += body.mass * body.position[moment, dim]
com = numerator / total_mass
coms.append(com)
center_of_mass.append(coms)
center_of_mass = np.array(center_of_mass).T
# print("\n .. center of mass:\n{}\n".format(center_of_mass))
As verification that the code works, the print statements in the code above output the following:
** A **
.. mass:
100
.. position:
[[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]
[15 16 17]
[18 19 20]
[21 22 23]
[24 25 26]
[27 28 29]]
** B **
.. mass:
100
.. position:
[[ 0. 0.5 1. ]
[ 1.5 2. 2.5]
[ 3. 3.5 4. ]
[ 4.5 5. 5.5]
[ 6. 6.5 7. ]
[ 7.5 8. 8.5]
[ 9. 9.5 10. ]
[10.5 11. 11.5]
[12. 12.5 13. ]
[13.5 14. 14.5]]
** C **
.. mass:
100
.. position:
[[ 0. 2. 4.]
[ 6. 8. 10.]
[12. 14. 16.]
[18. 20. 22.]
[24. 26. 28.]
[30. 32. 34.]
[36. 38. 40.]
[42. 44. 46.]
[48. 50. 52.]
[54. 56. 58.]]
.. center of mass:
[[ 0. 1.16666667 2.33333333]
[ 3.5 4.66666667 5.83333333]
[ 7. 8.16666667 9.33333333]
[10.5 11.66666667 12.83333333]
[14. 15.16666667 16.33333333]
[17.5 18.66666667 19.83333333]
[21. 22.16666667 23.33333333]
[24.5 25.66666667 26.83333333]
[28. 29.16666667 30.33333333]
[31.5 32.66666667 33.83333333]]
Using numpy will speed things up and make the code cleaner. I'm not an expert in n-body problems so I've hopefully followed the algorithm OK,the results look to be the same. All the loops become implicit in numpy.
# ***** From the question *****
import numpy as np
class Body():
def __init__(self, mass, position):
self.mass = mass
self.position = position
def __str__(self):
return '\n .. mass:\n{}\n\n .. position:\n{}\n'.format(self.mass, self.position)
mass = 100 # same for all 3 objects
ndim = 3 # 3 dimensional space
nmoments = 10 # 10 moments in time
## initialize bodies
nelems = ndim * nmoments
x = np.arange(nelems).astype(int).reshape((nmoments, ndim))
A = Body(mass, position=x)
B = Body(mass, position=x / 2.)
C = Body(mass, position=x * 2.)
bodies = [A, B, C]
# **** End of code from the question ****
# Fill the numpy arrays
np_mass = np.array( [ body.mass for body in bodies ])[ :,None, None ]
# the [:, None, None] turns np_mass into a 3D array for correct broadcasting
np_pos = np.array( [ body.position for body in bodies ]) # 3D
np_mass.shape
# (3, 1, 1) # (n_bodies, 1, 1 ) - The two 'spare' dimensions force the broadcasting to be along the correct axes
np_pos.shape
# (3, 10, 3) # ( n_bodies, nmoments, ndims )
total_mass = np_mass.sum() # Sum the three masses
numerator = (np_mass * np_pos).sum(axis=0) # sum np_mass * np_pos along the body (0) axis.
com = numerator / total_mass # divide by total_mass
# Could be a oneliner
# com = (np_mass * np_pos).sum(axis=0) / np.mass.sum()
print(com)
# array([[ 0. , 1.16666667, 2.33333333],
# [ 3.5 , 4.66666667, 5.83333333],
# [ 7. , 8.16666667, 9.33333333],
# [10.5 , 11.66666667, 12.83333333],
# [14. , 15.16666667, 16.33333333],
# [17.5 , 18.66666667, 19.83333333],
# [21. , 22.16666667, 23.33333333],
# [24.5 , 25.66666667, 26.83333333],
# [28. , 29.16666667, 30.33333333],
# [31.5 , 32.66666667, 33.83333333]])
center_of_mass = (A.mass * A.position + B.mass * B.position + C.mass * C.position) / total_mass

Use of numba to speed up intersept calculation

I am making a game which involves shadow casting.
To calculate the points on the lines I made this function.
def raySegmentIntersept(ray_start, ray_dir, segment_start, segment_end):
segment_dir = segment_end - segment_start
"""
find point where parametric equasions intersept
A + t*r = B + u*s
find the coeficient t for ray
(A + t*r) x s = (B + t*s) x s
find the coeficient u for segment
(A + t*r) x r = (B + t*r) x r
where x is cross function and cross is v1[0] * v2[1] - v1[1] * v2[0]
"""
denominator = np.cross(ray_dir, segment_dir)
if denominator == 0:
return np.NaN
t = (np.cross(segment_start - ray_start, segment_dir) / denominator)
u = (np.cross(ray_start - segment_start, ray_dir) / -denominator)
"""
since u is a segment it must be 0 <= u <= 1
since t is a ray it must be 0 <= t
"""
if 0 <= u <= 1 and 0 <= t:
return ray_start + ray_dir * t
return np.NaN
all four arguments (ray_start, ray_dir, segment_start, segment_end) are numpy arrays, (think of them as vectors, ie. shape=(2,).
I thought, that since this function is used quite a lot and it uses only maths in it, is it possible to speed it up?
The input looks (when printed) like this, where each line would be a different input
[ 120. 120.] [-0.70710678 -0.70710678] [160 240] [240 240]
[ 120. 120.] [-0.70710678 -0.70710678] [240 320] [160 320]
[ 120. 120.] [-0.70710678 -0.70710678] [320 240] [320 320]
[ 120. 120.] [-0.70710678 -0.70710678] [320 320] [240 320]
[ 120. 120.] [-0.70710678 -0.70710678] [160 320] [160 400]
[ 120. 120.] [-0.70710678 -0.70710678] [ 80 320] [ 80 400]
I would like to start to look at numba and maybe how to use the GPU for the computation. Is there a possibility to use any of the numba decorators? Do I need to refactor the code somehow?
Thanks
EDIT
The code consists of:
def raySegmentIntersept(ray_start, ray_dir, segment_start, segment_end):
...
class Vision:
def see(self, obstacles):
# prepare for calculation
# call self.getInterceptsWithWalls(endpointAngles, visibleLines)
def getInterceptsWithWalls(sellf endpointAngles, visibleLines):
# for angle in enpointAngles do
# for tile in visibleLines
# for line in tile
# intercept = raySegmentIntersept(
# ray_start,
# ray_dir,
# segment_start,
# segment_end)

Haskell, not sure how to

In one Haskell guide we are ask to calculate the weight of a tree based on this conditions:
From 0 to 3 meters it weighs 300 Kg/meter.
Over 3 it weighs 200 Kg/meter.
This is what I tried. It's close but doesn't solve it completely:
weightTree high = 900 + (high - 3) * 200
import Control.Monad (sequence_)
weightTree :: (Num a, Ord a) => a -> a
weightTree height = lowerWeight + upperWeight
where lowerWeight = 300 * lowerHeight
upperWeight = 200 * upperHeight
lowerHeight = (max 0 . min 3) height
upperHeight = max 0 (height - 3)
main :: IO ()
main = sequence_ $ test <$> [-1..5]
where test h = putStrLn $ concat [ "Height "
, show h
, ", weight "
, show (weightTree h)
]
Output:
Height -1, weight 0
Height 0, weight 0
Height 1, weight 300
Height 2, weight 600
Height 3, weight 900
Height 4, weight 1100
Height 5, weight 1300
So, after a few days i came out with a better way to solve this. Thanks to everyone who reply me, here i leave you what i end up doing (maybe it can help someone else):
weightTree height = (min height 3) * 300 + ((max height 3) - 3) * 200

Customize color ranges in Gnuplot

I have a contour plot running just fine and it is generating an equal amount of color for different values.
What I want is to generate the label on the right side to have a right color for each block.
current result:
What I want is to have this value on each block:
---- 300
---- 100
---- 70
---- 30
---- 10
---- 1
---- 0
Edit:
When I add this code:
set cbtics ('300' 300, '100' 100, '30' 30, '10' 10, '1' 1, '0.5' 0.5, '0.1' 0.1, '0.01' 0.01, '0' 0);
set palette defined (0.1 "#4CAF4F",0.3 "#65B443",0.5 "#7FBA38",0.7 "#98BF2D",0.9 "#B2C521",1.0 "#CBCA16",2 "#E5D00B",3 "#FFD600",4 "#FFC400",5 "#FFB300",6 "#FFA100",7 "#FF9000",8 "#FF7E00",10 "#FF6D00",30 "#F85A00",50 "#F14800",70 "#EA3600",90 "#E32400",100 "#DC1200",300 "#D50000")
The result is a uneven:
I want the ticks to be even but could not make it.
I would recommend that you rescale your output from the scale 0 to 300 to a scale in which the values vary linearly between the manually defined labels on the color bar:
rescale(x) = ( x >= 0. && x < 1. ? x : \
x >= 1. && x < 10. ? 1.+(x-1.)/(10.-1.) : \
x >= 10. && x < 30. ? 2.+(x-10.)/(30.-10.) : \
x >= 30. && x < 70. ? 3.+(x-30.)/(70.-30.) : \
x >= 70. && x < 100. ? 4.+(x-70.)/(100.-70.) : \
x >= 100. && x < 300. ? 5.+(x-100.)/(300.-100.) : \
1/0)
set cbrange [0:6]
set cbtics ("0" 0, "1" 1, "10" 2, "30" 3, "70" 4, "100" 5, "300" 6)
set pm3d
splot rescale(x**2+y**2)
If you want to limit the colors to one per block, add the following line:
set palette maxcolors 6
Finally, note that if you have a map the labeling is sufficient as is. If you have a 3D plot, you might want to also relabel the z axis:
set ztics ("0" 0, "1" 1, "10" 2, "30" 3, "70" 4, "100" 5, "300" 6)

Resources