list3 = list1 - list2 (netlogo) - list

I am new to NetLogo, for patient-surgeon model, I need to create a list3 which is list1 - list2. The list1 and list2 are comprised of the who number of the patients extracted from another list (for example, SET list1 lput WHO list-n).
I am using below code to subtract the list but I am not able to do so as model does not recognize ? or ?1. Please help me how to subtract two lists for n values.
set list1 []
set list2 []
;; emptying the list to add the who number of patients
;; then setting the list as per the who number of agent
;; setup patients
SET list1 lput WHO list-n
SET list2 lput WHO list-k
What I want: list3 = list1 - list2
Query used:
to test-lists
let list3 []
foreach list2 [
if (item (position ? list2) list1 = 1)[
set list3 lput ? list3
]
]
end
But I get the error:
nothing named ? is defined
As per the manual, "? is always equivalent to ?1" and need not be defined. Kindly suggest how to go about with the subtraction of the list.

Related

Netlogo code for sorting agents in lists according to their properties

I am trying to sort my agents [industries] into a list and make many further lists based on that initial list sequence.
Each industry has two properties [bid-cap] and [bid-price]. I want first, a sorted list [low-bid-ind] of agents according to their ascending bid-prices, then I want to use the same sequence and fetch the values of [bid-cap] and make a list [low-cap-list], then I want to fetch bid-price for same sequence as [low-bid-ind] list and save it in a list [low-cap-list]. I only make this list so I can make another list with cumulative sum values of the [bid-cap] of agents.
Following is my code. There's an error : LPUT expected input to be a list but got the number 0 instead.
But it doesn't show where the error occurs in the code.
set agentlist-low []
set low-bid-ind []
set low-cap-list []
set sum-low-bid []
set agentlist-low industries with [group = 0]
set low-bid-ind sort-on [bid-price] agentlist-low
foreach low-bid-ind
[ the-industry ->
set low-cap-list lput ([bid-cap] of the-industry) low-cap-list ]
let sum-low 0
let m 0
foreach low-bid-ind
[set m m + 1
set sum-low sum-low + item m low-cap-list
set sum-low-bid lput sum-low sum-low-bid ]
print sum-low-bid
Can anyone help with this problem?
I have looked at Netlogo help and other questions on the internet but I am unable to find an answer.
I cannot reproduce the error you are getting. Are you sure that you are setting low-cap-list and sum-low-bid to empty lists in your actual code? That kind of error normally comes when lput is given a list which has not been initialized, as uninitialized variables in NetLogo are set to 0.
But more generally, NetLogo has a map operation that eliminates the need for looping over lists in most cases. So the loop
foreach low-bid-ind
[ the-industry ->
set low-cap-list lput ([bid-cap] of the-industry) low-cap-list ]
can be written more economically as
set low-cap-list map [the-industry -> [bid-cap] of the-industry] low-bid-ind
and the code segment
let sum-low 0
let m 0
foreach low-bid-ind
[set m m + 1
set sum-low sum-low + item m low-cap-list
set sum-low-bid lput sum-low sum-low-bid ]
can be written as a single line
set sum-low-bid map [m -> sum sublist low-cap-list 0 (m + 1)] range (length low-bid-ind)
map creates a list by performing the operation in brackets on each item in the list it is given. In the latter case, that input list is simply the numbers from 0 to the length of the low-bid-ind list.

Grouping lists by elements in Netlogo

Let us say I have a model in Netlogo and am now interested in developing a reporter/procedure that groups lists according to their first element.
For the sake of example, let's say
globals[list1 list2 list3 listoflists
ordered-list-a
ordered-list-b
]
to setup
set list1 ["a" "b" "c"]
set list2 ["a" "c" "d"]
set list3 ["b" "a" "c"]
set listoflists (list list1 list2 list3)
end
I want to create a list of lists such that in each list you have lists starting with the same element. Hence, the desired output is
[[["a" "b" "c"]["a" "c" "d"]]["b" "a" "c"]]]
i.e, where the first element aggregates all lists with an a in first place, and the second all those starting with a "b".
Ideally, this should be scalable for a large number. I tried
to create-list
set ordered-list-a []
set ordered-list-b []
(foreach listoflists [[i] ->
if item 0 i = "a" [set ordered-list-a lput i ordered-list-a]
if item 0 i = "b" [set ordered-list-b lput i ordered-list-b]
])
end
and then creating a list from a and b, which does the trick, but a) it's incredibly messy, b) requires that I know beforehand the length of the list, which I don't in the real case (it's a turtle procedure) and c) it seems like a lot of unnecessary coding.
Is there some way to extend the procedure above to any number of starting elements (maybe inside a while cycle?) and does not require the creation of a list for each initial list element?
Many thanks
I'm assuming the desired output is supposed to be: [[["a" "b" "c"]["a" "c" "d"]][["b" "a" "c"]]]. I believe you were missing a [ before the second group.
Anyway, a simple, but somewhat inefficient way would be:
; items is a list of items to be grouped
; key is an anonymous reporter that extracts the group label from a single item
to-report group-by [ items key ]
let keys remove-duplicates map key items
report map [ k -> filter [ x -> (runresult key x) = k ] items ] keys
end
Note that the above is a completely generalized grouping function. To use it in your case, you would do:
group-by listoflists [ l -> first l ]
A more efficient way would be to use the table:group-items reporter from the table extension.
table:group-items listoflists [ l -> first l ]

NetLogo: Summing up the first element of a list in a list

I have a list that contains elements that are lists with two entries themselves:
list1 [ [15, w1] [20, w2] [30, w3] ...]
now, in a different function, I want to include a sum of the first element in each of the lists in list1 (i.e. 15 + 20 +30 ...)
what I've tried is
let weigh_dem (t_d_f * price_w) - (sum (foreach list1 [[a b] -> a] ))
but I get the error message "expected reporter.
Since I'm new on netlogo I would be glad to get advice on this, also if there is a previous post about this that I didn't see, I'd be happy to get a hint! Thanks!
You're looking for map instead of foreach. It works pretty much just like foreach except that it returns the results in a list (whereas foreach just executes the command for each item in the list). Also, the argument to the anonymous procedure when using either foreach or map on list1 will be a list containing the two items. So you need to use first to get the first item out:
let weigh_dem t_d_f * price_w - sum map [ pair -> first pair ] list1

Netlogo adding to list of lists

I am looking to add patch variable values to a list of empty lists. The patches are divided into different zones, and I'm trying to see how certain patch variables differ by zone.
I have an empty list of lists (actually contains 12 lists, but for simplicity):
set mylist [[] [] [] []]
And a list corresponding to the different zones:
set zone-list [1 2 3 4]
Here's how I'm trying to build the lists:
(foreach mylist zone-list [set ?1 lput (sum-zone-variable ?2) ?1])
to-report sum-zone-variable [ n ]
report (sum [patch-variable] of patches with [zone = n])
end
When I run this, mylist stays empty (ie unchanged). I think the problem is with the foreach statement, but I can't figure out what it is. Any help?
I can see the thinking behind foreach mylist [ set ?1 ... ], but NetLogo doesn't work that way. set ?1 ... has no effect on the original list. NetLogo lists are immutable, and ?1 is not a reference to an updatable location in a list — it's just a temporary variable into which a value has been copied. So set ?1 ... is something you will basically never write.
If I understand your question correctly, the relevant primitive here is map. This should do the job:
set mylist (map [lput (sum-zone-variable ?2) ?1] mylist zonelist)
Your basic approach is ok except that you must assign to a name. E.g.,
globals [mylist zone-list n-zones]
patches-own [zone zone-variable]
to setup
set n-zones 4
set zone-list n-values n-zones [?]
ask patches [set zone one-of zone-list]
set mylist n-values n-zones [[]]
end
to go
ask patches [set zone-variable random-float 1]
foreach zone-list [
let total sum [zone-variable] of patches with [zone = ?]
let oldvals item ? mylist
set mylist replace-item ? mylist (lput total oldvals)
]
end
However, you might want to use the table extension for this.

Remove a number in a lis that does not appear in another list - Haskell

I have two lists of numbers. In each are the numbers [1,2,3,4] but in one there is an extra fifth number eg.
list1 = [1,2,3,4]
list2 = [1,2,3,4,5]
I need to enforce that list2 is the same as list1, by either removing the 5th number from list2 or replacing list2 with another copy of list1?
Can this be done?
This question is worded a bit strangely. If you're looking to mutate one of the lists, then the answer is no: that is not possible. Otherwise, you can of course just use list1 instead of list2 anywhere you need it.
Data.List provides the intersect method, which seems exactly what's being requested.
The most easy and performant way to enforce that list2 is the same as list1 would be to say
let list2 = list1 in .......
This would not even require that the list elements are comparable.
[ x | x <- list1, x `elem` list2 ]
and here's another one though I like Louis_Wasserman's solution most
filter (`elem` [1..4]) [1..12]
>>> [1,2,3,4]
or
filter (flip elem [1..4]) [1..12]
>>> [1,2,3,4]
fliter (\x ->x `elem` [1..4]) [1..12]
>>> [1,2,3,4]
if list two is irrelevant why do you use it in the first place ??
and another one came to my mind:
const [1..4] list2
>>> [1,2,3,4]
the last one just ignores the second list and fills in the first.