I'm struggling with the following problem using these variables:
set variablex .5
set threshhold-list [0 .3 .6]
set variable-list [0 0 1]
I have three agenttypes 0,1,2 that correspond to the index position of threshhold-list and variable-list. So Agent 0 has threshold 0 and variable 0, Agent 1 has threshold .3 and variable 0, and Agent 2 has threshold .6 and variable 1.
What I'd like to do is check if any agent has a threshold greater than zero and less than variablex. If so, update that agent's variable on the variable list to variablex. That is, for the variables above I'd like to run logic that produces a new variable-list like this one:
variable-list [0 .5 1]
But if variablex was .7, it would produce [0 .7 .7].
I've got some code I've been hacking away at but I feel like it's way more complicated than the problem and so I'm wondering if someone could point me in the right direction. Thanks so much!
There are a few different ways to approach the problem, but if I was in your situation, I would first write a small reporter that gives me the value that should be stored at each index:
to-report new-value [ i ]
let t item i threshhold-list
report ifelse-value (t > 0 and t < variablex)
[ variablex ] ; the variable's new value should be variable x
[ item i variable-list ] ; the variable's value should not change
end
Once you have that, you can use either foreach or map to change your variable list:
to update-variables-with-foreach
foreach range length variable-list [ i ->
set variable-list replace-item i variable-list new-value i
]
end
to update-variables-with-map
set variable-list map new-value range length variable-list
end
Here is a somewhat verbose test to check that both versions would give you the expected results:
globals [
variablex
threshhold-list
variable-list
]
to test
clear-all
set threshhold-list [0 .3 .6]
set variablex .5
set variable-list [0 0 1]
update-variables-with-foreach
print variable-list
set variablex .5
set variable-list [0 0 1]
update-variables-with-map
print variable-list
set variablex .7
set variable-list [0 0 1]
update-variables-with-foreach
print variable-list
set variablex .7
set variable-list [0 0 1]
update-variables-with-map
print variable-list
end
That being said, as much as I think it is fun to play with lists, I think you are approaching your problem in a very unnetlogoish way.
NetLogo's world is a world of turtles and patches and links, not a world of arrays and indices and numbers.
You could do something along the lines of:
globals [
variable-x
]
turtles-own [
threshhold
variable
]
to setup
clear-all
set variable-x .5
(foreach [0 .3 .6] [0 0 1] [ [t v] ->
create-turtles 1 [
set threshhold t
set variable v
]
])
ask turtles [ update-variable ]
ask turtles [ show variable ]
end
to update-variable ; turtle procedure
if threshhold > 0 and threshhold < variable-x [
set variable variable-x
]
end
I don't know what you're ultimately trying to achieve, but if I could offer general advice, it would be to try to embrace to NetLogo mindset. Every time you're tempted to use an index of some kind in your code, take a step back and think again: there is probably a better (as in "more netlogoish") way to do it.
Related
I have a 2*2 matrix called orders:
0 0
0 0
created by:
set orders matrix:from-row-list [[0 0] [0 0]]
and I would like to change it to be a 3*2 matrix:
0 0
0 0
10 50
How to do this please? (I guess you have to create a new matrix also called orders to overwrite the existing orders, but I couldn't figure out the syntax.)
The easiest way would probably be to first convert your matrix to a list, than add the new row to the list, and convert it back to a matrix. Not very elegant, but the report function below should do the trick:
extensions [ matrix ]
to-report matrix-add-row [matrix row-added]
let temp-list matrix:to-row-list matrix ;; converts the matrix to a list
set temp-list lput row-added temp-list ;; the new row is added to the list
report matrix:from-row-list temp-list ;; converts the list back to a matrix
end
to test
let orders matrix:from-row-list [[0 0] [0 0]]
show orders
show matrix-add-row orders [ 10 50 ]
end
This would return you:
observer> test
observer: {{matrix: [ [ 0 0 ][ 0 0 ] ]}}
observer: {{matrix: [ [ 0 0 ][ 0 0 ][ 10 50 ] ]}}
Of course, you have to make sure that the dimensions of the matrix and the row added match.
Just in case this helps someone else, what I did in the end was use a new agent breed 'orders' in place of the matrix, with each orders turtle essentially being what would have been a row in the matrix. I told the orders to sit on the same patch as the turtle that owned it, which was easy as the turtles in that model don't move. The advantage is that I had access to a wide range of processing possibilities that I didn't have with the matrix. Of course if you do this and the order of the rows matters, you need to include some way of managing this (something like orders-own [index] would do).
I have a set of 100 bits named bits, i just want to do this operation:
100 - absolute_value( # of 1's - # of 0's ). I've tried various forms, one of these like:
100 - abs (length filter [x -> x = 1] bits - length filter [x -> x = 0] bits)
But no matter what, the result always is 100, i don't understand why because if i remove the "100 - " the result of the abs operation alone is diferent than 0.
Any advice will be apreciated, also i've notice that when i do a random request consecutively the result doesn't change too much
turtles-own [
bits
fitness
]
to setup
clear-all
create-turtles population-size [
set bits n-values world-width [one-of [0 1]]
ifelse fitness-function?
[ calculate-fitness-alt ]
[ calculate-fitness ]
hide-turtle
]
to calculate-fitness-alt
set fitness 100 - abs (length filter [x -> x = 1 ] bits - length filter [x -> x = 0 ] bits)
end
I'm trying to calculate the mean of nested lists. I have tried using the map function, but the default gives the mean in the opposite dimension that I am interested in. See the below example:
set a [[1 1][2 2][3 3]] ; create a nested list
set b map mean a ; b equals [1 2 3]
This answer gives [1 2 3] for b. However I am interested in the answer [2 2] by taking the mean in the "other" dimension. I would imagine there is a way to do this with map but haven't figured it out.
to go
print column-means [
[ 1 1 ]
[ 2 2 ]
[ 3 3 ]
]
end
to-report column-means [ matrix ]
if length (remove-duplicates map length matrix) > 1 [
error "All rows must be the same length"
]
report n-values length first matrix [ mean extract ? matrix ]
end
to-report extract [ i row ]
report map [ item i ? ] row
end
A possible solution is the following
set a [[1 2 3] [1 2 3]]
set b map mean a
this will give you [2 2] for b.
Good morning,
I need to create a list of [0,1], which length is defined by the user (global variable). There is an easy solution for this:
set listInd (list n-values numOfInd [random 2])
But I need to make sure, that the list has exactly three ones in it and they are placed on random positions. Is there a way to do this?
Regards.
You can create 3 random numbers (indices) and then create a list with 1 on the positions defined by this index list:
to-report rand-list[n k]
let ind-list n-of k n-values n [?]
report n-values n [ifelse-value (member? ? ind-list) [1][0]]
end
Usage:
show rand-list 10 3
; result:
; [0 1 0 0 0 0 1 0 0 1]
An alternative to bergant's solution would be to gather the desired amount of ones and zeros, then mix them together randomly:
to-report rand-list [n k]
let zeros n-values (n - k) [0]
let ones n-values k [1]
report shuffle sentence zeros ones
end
I am currently working to create a pictorial representation of the Levy C-Curve in NetLogo using an IFS construction scheme. I have found two functions which describe how to iteratively map the locations of two turtles and should result in the desired curve after thousands of iterations. Here is my code so far:
;;;;;; some useful complex operations
; to take re(z) of a complex number a + bi inputed as the list of coordinates [a b]
to-report re [z]
report first z
end
; to take im(z)
to-report im [z]
report last z
end
; to multiply two complex numbers
to-report complex_mul [z1 z2]
report list (re z1 * re z2 - im z1 * im z2)
(re z1 * im z2 + im z1 * re z2)
end
; to add complex numbers
to-report complex_add [z1 z2]
report list (re z1 + re z2)
(im z1 + im z2)
end
; to dilate complex numbers by a scalar fraction
to-report complex/real [z1 real]
report list (re z1 / real)
(im z1 / real)
end
; to initialize
to setup
ca
setup-turtles
reset-ticks
end
; create 2 turtles located at the initial set of points {0, 1}
to setup-turtles
crt 2
ask turtle 0 [ setxy 0 0]
ask turtle 1 [ setxy 1 0]
ask turtles [ pd]
end
; to create the first function to transform the turtle's location
to-report nextz_1 [z]
report complex/real (complex_mul [1 -1] z) 2
end
; to create the second function to transform the turtle's location
to-report nextz_2 [z]
report complex_add [1 0]
(complex/real (complex_mul [1 1]
(complex_add z [-1 0]))
2)
end
; finally we are creating the Levy Curve
to levy
ask turtles [ run one-of (list task setxy re (nextz_1 [xcor ycor]) im (nextz_1 [xcor ycor])
task setxy re (nextz_2 [xcor ycor]) im (nextz_2 [xcor ycor])
)
]
end
However, I'm receiving an error message in my "levy" code block where I call re (nextz_1 [xcor ycor]) etc., saying that NetLogo is expecting a constant value in place of xcor and ycor.
How would I fix this issue?
At http://ccl.northwestern.edu/netlogo/docs/faq.html#listexpectedconstant the NetLogo FAQ says:
If a list contains only constants, you can write it down just by putting square brackets around it, like [1 2 3].
If you want your list to contain items that may vary at runtime, the list cannot be written down directly. Instead, you build it using the list primitive.
You actually got this right in some other places in your code, but in the levy procedure, you need to replace e.g. [xcor ycor] with list xcor ycor.
To NetLogo, [xcor ycor] looks like a reporter block, not like a list.