How can I shuffle the order of a matrix in NetLogo? - netlogo

How can I shuffle the contents of a matrix and preserve it as a matrix? The shuffle function works for lists but not for matrices
show shuffle [1 2 3 4 5]
1 2 3 5 4
set m matrix:from-row-list
[[1 2 3 4 5]]
show shuffle m
SHUFFLE expected input to be a list but got the
org.nlogo.extensions.matrix.MatrixExtension$LogoMatrix {{matrix: [ [
1 2 3 4 5 ] ]}} instead.

There may be an easier way, but you could jump to a list, shuffle, then come back to a matrix based on the dimensions of your original matrix.
extensions [ matrix ]
to setup
ca
let m matrix:from-row-list [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ]
let sm shuffled-matrix m
print matrix:pretty-print-text sm
reset-ticks
end
; Reporter returns a shuffled matrix
to-report shuffled-matrix [ mat ]
; Get the number of columns
let cols last matrix:dimensions mat
; Shuffle the matrix values as a list
let shuf-vals shuffle reduce sentence matrix:to-row-list mat
; Use the shuffled values to generate a new matrix
; with the same dimensions as the original
report matrix:from-row-list ( subsetter shuf-vals cols )
end
; Reporter returns a list cut into sublists
; based on the len value passed
to-report subsetter [ ls len ]
; Generate subsetting indices for the sublists
let vals ( range 0 ( length ls ) len )
; Make subsets of ls based on the subsetting indices
report map [ i -> sublist ls i ( i + len ) ] vals
end
A few example outputs from setup:
[[ 1 6 7 ]
[ 9 5 8 ]
[ 3 4 2 ]]
[[ 4 6 8 ]
[ 1 9 2 ]
[ 7 5 3 ]]
[[ 2 9 4 ]
[ 6 3 8 ]
[ 5 1 7 ]]

Related

NetLogo: How do I build a new vector based on randomly chosen values from another vector?

I have a vector 'original' with 10 digits. Now I want to create vector 'adapted' based on 'original'. 'adapted' is supposed to take n random values that are larger than 0 from 'original' in the same position and fill up the rest with 0s, e.g.:
original = [2 3 6 2 0 5 7 2 4 8]
adapted = [2 0 0 0 0 5 0 2 0 0]
to go
let n 3
let vector-dimension 10
let original []
repeat vector-dimension
[set original lput random 10 original]
print original
let adapted []
while [sum (map [ [v1] -> ifelse-value (v1 > 0) [1] [0] ] (adapted)) != n]
[set adapted (map [ [v1] -> ifelse-value ( (vector-dimension / n) * (100 / vector-dimension) > random-float 100) [v1] [0] ] (original)) ]
print adapted
end
This Code works but is slow. How can I do it faster?
How about:
to-report report-rand-n [ base n ]
let indices ( range 0 (length base))
let subset n-of n indices
let out ( map [ [ i v ] -> ifelse-value ( member? i subset ) [v] [0] ] indices base)
report out
end
This reporter makes a list of indices (0 through the length of the base passed), then randomly selects n number of those indices to pass to ifelse-value to return either the original value in base (if i is one of the selected indices) or 0.
Testing:
to test
let original [2 3 6 2 0 5 7 2 4 8]
print report-rand-n original 3
print report-rand-n original 3
print report-rand-n original 5
print report-rand-n original 5
end
observer> test
[2 0 6 0 0 0 0 0 4 0]
[2 0 0 0 0 0 0 2 0 8]
[2 0 0 0 0 5 0 2 4 8]
[0 0 6 2 0 5 0 0 0 8]
Edit:
to test
let original [2 3 6 2 0 5 7 2 4 8]
print word "testing: " original
print report-rand-n original 3
let few-digits [ 0 0 0 1 0 0 0 ]
print word "testing: " few-digits
print report-rand-n few-digits 3
print ""
end
to-report report-rand-n [ base n ]
; create list of indices
let indices ( range 0 (length base))
; To address point 1) in your comment:
; keep only indices that correspond to a value > 0 in base
let indices-over-zero filter [ i -> item i base > 0 ] indices
; To address point 2 in your comment:
; If the length of indices over zero is less than n, replace n
; with the length of indices over zero
if length indices-over-zero < n [
set n length indices-over-zero
]
let subset n-of n indices-over-zero
let out ( map [ [ i v ] -> ifelse-value ( member? i subset ) [v] [0] ] indices base)
report out
end

How can I multiply n elements of a matrix by a number in NetLogo?

I have a matrix m and I want to have a user defined function which allows me to control the elements that are multiplied by a value.
The function matrix:set-and-report looks promising but I'm not sure how to implement this for multiple elements.
For example, I would like to multiply the first 3 elements of the matrix by -1 to move from this:
let m matrix:from-row-list [1 2 3 4 5 6]
print m
to this:
let n matrix:from-row-list [-1 -2 -3 4 5 6]
With matrix:set-and-report you were indeed pretty close to a solution. Please check the example, I hope this is what you were looking for. The report function has matrix as an input. Than you specify the row, than the index were you want to start the multiplication, where to end it, and finally the multiplier.
Extensions [
matrix
]
to test
let m matrix:from-row-list [ [1 2 3 4 5 6] [1 2 3 4 5 6] ]
print (word "original matrix " m)
print (word "modified matrix " matrix-row-manipulation m 0 0 3 -1)
end
to-report matrix-row-manipulation [matrix row columen-index-start columen-index-end multiplier]
let index (range columen-index-start columen-index-end 1)
foreach index [ i ->
set matrix matrix:set-and-report matrix row i (matrix:get matrix row i * multiplier )
]
report matrix
end
This will return you:
observer> test
original matrix {{matrix: [ [ 1 2 3 4 5 6 ][ 1 2 3 4 5 6 ] ]}}
modified matrix {{matrix: [ [ -1 -2 -3 4 5 6 ][ 1 2 3 4 5 6 ] ]}}

How can I change the elements of a matrix if they satisfy some condition?

I'm working with the matrix extension in NetLogo. I want to be able to modify specific elements of the matrix if they equal some number.
For instance if the value is 0.95 I want to run random 2 on it so it comes out as a 1 or a 0. And if it's a 1.75 it comes out as a 1 or a 2 with random (3 - 1) + 1
This would change my matrix m from this:
let m matrix:from-row-list [[1 0.95 0.95] [2 1 1.75] [1 2 1] ]
to this:
[[1 1 0] [.05 1 2] [.05 .25 1] ]
Thanks
I'm not sure if I understand your updated matrix example- for example, why does the 2 in the second row become 0.05 in the output? I'm assuming you have some other rules for dealing with those numbers. Anyway, I think you can use matrix:map to accomplish what you're after- you may just have to set up the rules in your anonymous reporter to reflect what you're after. Here is an example using the rules you supplied for values of 0.95 and 1.75:
extensions [ matrix ]
to matrix-manipulation
let m matrix:from-row-list [[1 0.95 0.95] [2 1 1.75] [1 2 1] ]
let m2 matrix:map [ i -> val-change i ] m
print matrix:pretty-print-text m2
end
to-report val-change [ val ]
if val = 0.95 [
report random 2
]
if val = 1.75 [
report 1 + random 2
]
report val
end
Output becomes:
[[ 1 0 1 ]
[ 2 1 2 ]
[ 1 2 1 ]]

How to remove several items from a unsorted list in Netlogo

so i'm a bit struggling with Lists in Netlogo, so basically i've two lists and i want to remove the items that are in List 1 from List 2, for example:
List 1 : [8 6 9 7 1 3]
List 2: [5 9 8]
Resulting List : [6 7 1 3]
I've tried the following code but it returns an empty list:
if List 2 != []
[
foreach List 2
[
let p position ? List 1
if p = true
[
set List 1 remove-item p List 1
]
]
]
Any ideas ?
A combination of member? and filter will get you there:
let list1 [8 6 9 7 1 3]
let list2 [5 9 8]
let result filter [ x -> not member? x list2 ] list1
print result
Will print the desired:
[6 7 1 3]
Tip: whenever you find yourself trying to use an index for anything in NetLogo, you are probably not doing things in the optimal way. NetLogo has tons of functions (like filter, in this case) that operate on lists as a whole. There is rarely a need to explicitly loop through them.

Perl PDL not working as expected

I really don't understand PDL's input functions. Personally, I've been using the rcols feature to create pdls, as was recommended to me in various places around the web.
I have an input file like this :
3 -4 -1
0 5 2
3 5 6
2 5 2
5 5 5
5 5 6
which, I want to assign to a Piddle. When I assign it to a piddle like so,
my #pdls = rcols $in_fh, { COLSEP => "\\s" } ;
my $pdl = pdl(#pdls[1 .. $#pdls]);
When I print #pdls this is printed :
[
[ 3 0 3 2 5 5]
[-4 5 5 5 5 5]
[-1 2 6 2 5 6]
]
Which made me think it pulled my file by columns, and not rows. Which makes sense looking at the code, really. When I saved this output to a file(After stripping out all the brackets) this is how it looked. :
3 0 3 2 5 5
-4 5 5 5 5 5
-1 2 6 2 5 6
When I ran the same script on the new input file, the result does not follow the same process as before :
[
[ 0 -4 -1]
[ 3 0 0]
[ 0 5 2]
[ 0 0 0]
[ 0 5 6]
[ 3 0 0]
[ 0 5 2]
[ 2 0 0]
[ 0 5 5]
[ 5 0 0]
[ 0 5 6]
[ 5 0 0]
]
And I have no idea why it is doing so. In essence, I want to be able to read my text file into a piddle. Does anyone see what I'm missing, or able to offer any explanation?
Thanks for any help.
As is occasionally the case in PDL, the design of things with several dimensions can be a bit counter-intuitive. But it is designed overall so it's easy to just adjust dimensions. Here, rcols and wcols treat data in files in a FORTRAN-style column-major way. It is easy to adjust that using the transpose method:
pdl> p $x = sequence(3,4)
[
[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
]
pdl> wcols($x->transpose, 'myfile')
pdl> p pdl(rcols('myfile', {colsep => qr/\s+/}))->transpose
Reading data into ndarrays of type: [ Double Double Double ]
Read in 4 elements.
[
[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
]
Maybe its just better to make a "3,6 matrix of zeros" then set in each value individually, (which means putting the data from a file into a 1D pdl() first) I would use a open() to read it into a scaler then put that in a 1D piddle; which can be rather involved ... once you get it in a 1D piddle do this:
open(FILE,"yourfile"); while (<FILE>) { $x = $_; }
close FILE;
$y = zeros(3,6);
p $x = sequence(18);
[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]
for $c(0..5) { for $d(0..2) { $y($d,$c) .= $x($e++) }}
p $y
[ 0 1 2]
[ 3 4 5]
[ 6 7 8]
[ 9 10 11]
[12 13 14]
[15 16 17]