NetLogo addition of nominal values giving unusual results - netlogo

When a variable is being incremented by very small value (say 0.01), it is not giving proper (precise) results as expected.
Looking for suggestions(if any) to deal with the same.
globals[p]
to go
set p 0
while[p <= 1]
[
print p
set p p + 0.01
]
end

First read this:
http://floating-point-gui.de/
Then to subdivide an interval into n pieces, do this:
to-report subdivide [#xmin #xmax #n]
let ps n-values (#n + 1) [? / #n]
report map [#xmin + ? * (#xmax - #xmin)] ps
end

Related

Why Netlogo `range` command with step behaves different below 1

I would like Netlogo to make a range with steps below 1, but it does a different number of items than using the start number above 1.
For example,
show (range (0.75 - 0.20) (0.75 - 0.15) 0.05)
[0.55]
but,
show (range (1.75 - 0.20) (1.75 - 0.15) 0.05)
[1.55 1.6]
Is there any way to make that (range (0.75 - 0.20) (0.75 - 0.15) 0.05) gives also two values
[0.55 0.6].?
Netlogo uses a precision internally that mekes operation like this:
0.60 >= (0.55 + 0.05)
false
and
1.60 >= (1.55 + 0.05)
true
I do not know if this is a bug of Netlogo, but the first logic result is odd because it should give true not false.
A solution is a procedure to make range lists.
to-report my-range [ini fin stp]
let prec 2
ifelse fin >= (precision (ini + stp) prec) [
let mr (list ini)
let lv ((precision ((fin - ini)/ stp) 1) )
let val 0
repeat lv [
set val (last mr)
set mr (lput (precision (val + stp) prec) mr)
]
report mr
] [
report ini
]
end
Now
show my-range 0.55 0.60 0.05
[0.55 0.6]

Permanent Choices in NetLogo

In this model, if certain conditions are met, farmers invest in their Rate of Production (RoP). If other conditions are met, they invest in their Standard of Living (SoL).
Currently, this is executed via several if statements within the To Invest procedure at each time step.
How can I make the courses of action permanent. For example, if the first farm at tick 2 meets the conditions to invest in RoP, that farm should continue to do so at each subsequent time step, not have the option at tick 3 to invest in SoL. How can I make this action permanent?
to invest
let p random 100
set excess-prev-tick farm-excess
if ( farm-excess > 0 and p <= 30 ) [
set farm-RoP ( farm-RoP + farm-excess )]
if ( farm-excess > 0 and p > 30 and SoL < SoL-max ) [
set SoL ( SoL + 0.1 )]
if ( farm-excess > 0 and p > 30 ) [
set farm-RoC ( farm-RoC + ( count patches in-radius farm-size * 2 ))]
if farm-excess < 0 and SoL >= SoL-min [
set SoL ( SoL - 0.05) ]
set farm-excess (farm-ROP - farm-RoC)
set RoExp ((farm-excess - excess-prev-tick) / (excess-prev-tick))
end
The easiest way is to create a variable for each farmer (using a farmers-own statement) that is initialised as "undecided" and then becomes either "production" or "living" when the condition is met for one of them. You should then organise your invest code to have different calculations for different subgroups of farmers (so something like ask farmers with [invest-type = "undecided"][ <do stuff> ]

How can I sum up functions that are made of elements of the imported dataset?

See the code and error. I have already tried Do, For,...and it is not working.
CODE + Error from Mathematica:
Import of survival probabilities _{k}p_x and _{k}p_y (calculated in excel)
px = Import["C:\Users\Eva\Desktop\kpx.xlsx"];
px = Flatten[Take[px, All], 1];
NOTE: The probability _{k}p_x can be found on the position px[[k+2, x -16]
i = 0.04;
v = 1/(1 + i);
JointLifeIndep[x_, y_, n_] = Sum[v^k*px[[k + 2, x - 16]]*py[[k + 2, y - 16]], {k , 0, n - 1}]
Part::pkspec1: The expression 2+k cannot be used as a part specification.
Part::pkspec1: The expression 2+k cannot be used as a part specification.
Part::pkspec1: The expression 2+k cannot be used as a part specification.
General::stop: Further output of Part::pkspec1 will be suppressed during this calculation.
Part of dataset (left corner of the dataset):
k\x 18 19 20
0 1 1 1
1 0.999478086278185 0.999363078716059 0.99927911905056
2 0.998841497412202 0.998642656911039 0.99858030519133
3 0.998121451605207 0.99794428814123 0.99788275311401
4 0.997423447323642 0.997247180349674 0.997174407432264
5 0.996726703362208 0.996539285828369 0.996437857252448
6 0.996019178300768 0.995803204773039 0.99563600297737
7 0.995283481416241 0.995001861216016 0.994823584922968
8 0.994482556091416 0.994189960607964 0.99405569519175
9 0.993671079225432 0.99342255996206 0.993339856748282
10 0.992904079096455 0.992707177451333 0.992611817294026
11 0.992189069953677 0.9919796017009 0.991832027835091
Without having the exact same data files to work with it is often easy for each of us to make mistakes that the other cannot reproduce or understand.
From your snapshot of your data set I used Export in Mathematica to try to reproduce your .xlsx file. Then I tried the following
px = Import["kpx.xlsx"];
px = Flatten[Take[px, All], 1];
py = px; (* fake some py data *)
i = 0.04;
v = 1/(1 + i);
JointLifeIndep[x_, y_, n_] := Sum[v^k*px[[k+2,x-16]]*py[[k+2,y-16]], {k,0,n-1}];
JointLifeIndep[17, 17, 12]
and it displays 362.402
Notice I used := instead of = in my definition of JointLifeIndep. := and = do different things in Mathematica. = will immediately evaluate the right hand side of that definition. This is possibly the reason that you are getting the error that you do.
You should also be careful with your subscript values and make sure that every subscript is between 1 and the number of rows (or columns) in your matrix.
So see if you can try this example with an Excel sheet containing only the snapshot of data that you showed and see if you get the same result that I do.
Hopefully that will be enough for you to make progress.

How make a list of cumulative sum in netlogo

How can i make a list of cumulative sum of a other list?
i tried it that way:
;;all temperatrue-values around the turtle saved in list
set temperature_values (list [(output-heat + 1)^ Freedom] of neighbors)
;;build cumulative value of temperatures and put each value in list
let tempsum 0
set tempsum_list []
foreach temperature_values
[set tempsum (tempsum + ? )
set tempsum_list fput tempsum tempsum_list
]
but it doesn't work. can anyone fix this problem? it says that "+ excepted a input but gets a list instead".
your code for a cumulative sum works (except that I think you need lput rather than fput. You can see it with this:
to test
let ll [1 2 3 4]
let tempsum 0
let tempsum_list []
foreach ll
[ set tempsum (tempsum + ? )
set tempsum_list lput tempsum tempsum_list
]
print tempsum_list
end
Did the error highlight the line set temperature_values (list [(output-heat + 1)^ Freedom] of neighbors)? Try putting a space after between ) and ^. NetLogo is picky about space around mathematical operators.
As Jen suggested, you can use foreach. Another nice approach is reduce:
to-report partial-sums [#lst]
set #lst (fput [0] #lst) ;;prepare for reduce
report butfirst reduce [lput (?2 + last ?1) ?1] #lst
end
Similar to Alan's solution (Just an update for the recent version of NetLogo that replaces ? with -> for anonymous procedures.)
to-report partial-sums [lst]
report butfirst reduce [[result-so-far next-item] -> lput (next-item + last
result-so-far) result-so-far] fput [0] lst
end
This is like Alan's solution, just abstracted a bit further. (Perhaps too far, depending on your taste! I like JenB's solution as well.)
Let's first define a thing like reduce, but that keeps all the intermediate results:
to-report scan [fn xs]
report reduce [lput (runresult fn ?2 last ?1) ?1]
(fput (list first xs) butfirst xs)
end
Now we can use it to compute partial sums:
observer> show scan task + [1 2 3 4 5]
observer: [1 3 6 10 15]
but we are also free to swap in a different operation:
observer> show scan task * [1 2 3 4 5]
observer: [1 2 6 24 120]

Nested foreach in NetLogo

I am trying to calculate the Gini coefficient of a set of numbers. The Gini coefficient is half the mean absolute difference. That is, for every possible pair of numbers in the list, I need to take their absolute difference and add these differences together (and some other stuff). This is my code
to-report calc-Gini [list-Values]
let sumdiff 0
foreach list-Values
[ foreach list-Values
[ set sumdiff sumdiff + abs ( ?1 - ?2 )
]
]
report 0.5 * sumdiff / (mean list-Values * (length list-Values) ^ 2)
end
When I test it (eg show calc-Gini (list 1 2 3)) I get an error "task expected 2 inputs, but only got 1" on the second foreach.
I think the problem is that NetLogo wants to run through the foreach loops simultaneously. So if the list length is N, then it creates only N pairs (that is, first item in list1 and first item in list2, then the second item in each list etc) which is where the requirement for equal length lists comes from. But I need it to work with the N^2 pairs obtained by crossing the lists.
How can I make the nested foreach do what I want and/or is some other primitive more appropriate?
NetLogo doesn't have a mechanism for binding ?1 and ?2 to an outer and an inner task. When it sees ?1 and ?2 in your code, it expects that both inputs will come from the inner task. And since the inner foreach only provides one input, NetLogo complains.
You can get around that problem by simply assigning the input of the outer foreach to a local variable:
to-report calc-Gini [list-Values]
let sumdiff 0
foreach list-Values
[ let v ?
foreach list-Values
[ set sumdiff sumdiff + abs ( v - ? )
]
]
report 0.5 * sumdiff / (mean list-Values * (length list-Values) ^ 2)
end
That being said, here is an alternative implementation:
to-report calc-gini [ xs ]
report 0.5 * sum map [ sum-diff ? xs ] xs / (mean xs * (length xs) ^ 2)
end
to-report sum-diff [ x xs ]
report sum map [ abs (x - ?) ] xs
end
I can't solve your nested foreach approach, but this might be an alternative way to do your calculation:
If you use ordered data, you can use this equation for the Gini coefficient (given a vector $y$ with $y_i$, $i=1,...,n$)
$$ G(y) = \frac{1}{n} (n + 1 - 2 * \frac{ \sum_{i=1}^{n} (n + 1 - i) y_{i} }{ \sum_{i=1}^{n} y_i} $$
and the following reporter should deliver the result in NetLogo:
to-report calc-Gini [list-Values]
let values sort list-Values ; making sure values are in a non-decreasing order
let n length values
let i 1
let numerator []
foreach values
[ set numerator lput ( (n + 1 - i) * ? ) numerator
set i i + 1
]
report 1 / n * ( n + 1 - 2 * (sum(numerator) / sum(values)) )
end