I'm having performace issues with a query in Gremlin using AWS Neptune graph database.
This is the scenario:
Basically, there are 5000+ users connected by the same IP node.
I want all users that have a connection with the ip node at a date that matches one of the dates of the connections from user-1 with a window of 1 day. For example, starting from user-1 I want to find only user-2 and user-4.
I already have a query that works, thanks to the responses in this question I posted a while back, and looks something like this:
g.V('user-1')
.outE().as('ip_edges')
.inV().inE('uses_ip').as('related')
.where(P.lte('related')).by(math('ip_edges - 86400000').by('date_millis')).by('date_millis')
.where(P.gte('related')).by(math('ip_edges + 86400000').by('date_millis')).by('date_millis')
.outV()
But I'm experiencing performance issues in this scenario because the query is traversing through all of the 5000+ edges of the ip node.
I understand that Neptune has indexes that should allow me to filter edges by the property date_millis without having to go through all 5000+ edges. But I'm failing to write a query that actually uses those indexes.
This is how the profiling of the query looks like (the node ids are a bit different because i simplified it for the example here):
*******************************************************
Neptune Gremlin Profile
*******************************************************
Query String
==================
g.V('user-lt1001').outE().as('ip_edges').inV().inE('uses_ip').as('related').where(P.lte('related')).by(math('ip_edges - 86400000').by('at_millis')).by('at_millis').where(P.gte('related')).by(math('ip_edges + 86400000').by('at_millis')).by('at_millis').outV()
Original Traversal
==================
[GraphStep(vertex,
[user-lt1001
]), VertexStep(OUT,edge)#[ip_edges
], EdgeVertexStep(IN), VertexStep(IN,
[uses_ip
],edge)#[related
], WherePredicateStep(lte(related),
[
[MathStep(ip_edges - 86400000,
[value(at_millis)
])
], value(at_millis)
]), WherePredicateStep(gte(related),
[
[MathStep(ip_edges + 86400000,
[value(at_millis)
])
], value(at_millis)
]), EdgeVertexStep(OUT)
]
Optimized Traversal
===================
Neptune steps: [
NeptuneGraphQueryStep(Edge) {
JoinGroupNode {
PatternNode[(?1=<user-lt1001>, ?5, ?3, ?6) . project ?1,?6,?3 . IsEdgeIdFilter(?6) .
],
{estimatedCardinality=3, expectedTotalOutput=2, indexTime=0, joinTime=0, numSearches=1, actualTotalOutput=2
}
PatternNode[(?8, ?10=<uses_ip>, ?3, ?11) . project ?3,?11 . IsEdgeIdFilter(?11) .
],
{estimatedCardinality=10022, indexTime=0, joinTime=13, numSearches=1
}
}, annotations={path=[Vertex(?1):GraphStep, Edge(?6):VertexStep#[ip_edges
], Vertex(?3):EdgeVertexStep, Edge(?11):VertexStep#[related
]
], joinStats=true, optimizationTime=1, maxVarId=12, executionTime=633
}
},
NeptuneTraverserConverterStep
]
+ not converted into Neptune steps: [WherePredicateStep(lte(related),
[
[MathStep(ip_edges - 86400000,
[value(at_millis)
]), ProfileStep
], value(at_millis)
]), NoOpBarrierStep(2500), WherePredicateStep(gte(related),
[
[MathStep(ip_edges + 86400000,
[value(at_millis)
]), ProfileStep
], value(at_millis)
]), NoOpBarrierStep(2500), EdgeVertexStep(OUT)
]
WARNING: >> WherePredicateStep(lte(related),
[
[MathStep(ip_edges - 86400000,
[value(at_millis)
]), ProfileStep
], value(at_millis)
]) << (or one of its children) is not supported natively yet
Physical Pipeline
=================
NeptuneGraphQueryStep
|-- StartOp
|-- JoinGroupOp
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?1=<user-lt1001>, ?5, ?3, ?6) . project ?1,?6,?3 . IsEdgeIdFilter(?6) .
],
{estimatedCardinality=3, expectedTotalOutput=2
})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?8, ?10=<uses_ip>, ?3, ?11) . project ?3,?11 . IsEdgeIdFilter(?11) .
],
{estimatedCardinality=10022
})
Runtime (ms)
============
Query Execution: 633.282
Traversal Metrics
=================
Step Count Traversers Time (ms) % Dur
-------------------------------------------------------------------------------------------------------------
NeptuneGraphQueryStep(Edge) 9358 9358 20.431 3.23
NeptuneTraverserConverterStep 9358 9358 23.427 3.70
WherePredicateStep(lte(related),
[
[MathStep(ip_e... 7 7 588.350 92.96
MathStep(ip_edges - 86400000,
[value(at_millis)
]) 9358 9358 293.918
NoOpBarrierStep(2500) 7 7 0.036 0.01
WherePredicateStep(gte(related),
[
[MathStep(ip_e... 5 5 0.542 0.09
MathStep(ip_edges + 86400000,
[value(at_millis)
]) 7 7 0.285
NoOpBarrierStep(2500) 5 5 0.023 0.00
EdgeVertexStep(OUT) 5 5 0.118 0.02
>TOTAL - - 632.929 -
Predicates
==========
# of predicates: 38
Results
=======
Count: 5
Output: [v[user-lt1001
], v[user-lt1004
], v[user-lt1001
], v[user-lt1003
], v[user-lt1002
]
]
Index Operations
================
Query execution:
# of statement index ops: 18737
# of unique statement index ops: 4686
Duplication ratio: 4.00
# of terms materialized: 0
To compare execution times, while this query takes 600+ ms, the same query without those 5000 extra edges takes 8ms.
EDIT 1
Here's a query that improves the execution times, but stills traverses all the edges.
g.V('user-1')
.outE().as('ip_edges')
.values('at_millis').math('_ + 86400001').as('plus_one_day')
.select('ip_edges').values('at_millis').math('_ - 86400001').as_('minus_one_day')
.select('ip_edges')
.inV().inE('uses_ip').as('result')
.values('at_millis')
.where(P.between('minus_one_day', 'plus_one_day'))
.select('result')
.outV()
And this is the profiling of this query:
*******************************************************
Neptune Gremlin Profile
*******************************************************
Query String
==================
g.V('user-lt1001').outE().as('ip_edges').values('at_millis').math('_ + 86400001').as('plus_one_day').select('ip_edges').values('at_millis').math('_ - 86400001').as_('minus_one_day').select('ip_edges').inV().inE('uses_ip').as('result').values('at_millis').where(P.between('minus_one_day', 'plus_one_day')).select('result').outV()
Original Traversal
==================
[GraphStep(vertex,
[user-lt1001
]), VertexStep(OUT,edge)#[ip_edges
], PropertiesStep([at_millis
],value), MathStep(_ + 86400001)#[plus_one_day
], SelectOneStep(last,ip_edges), PropertiesStep([at_millis
],value), MathStep(_ - 86400001)#[minus_one_day
], SelectOneStep(last,ip_edges), EdgeVertexStep(IN), VertexStep(IN,
[uses_ip
],edge)#[result
], PropertiesStep([at_millis
],value), WherePredicateStep(and(gte(minus_one_day), lt(plus_one_day))), SelectOneStep(last,result), EdgeVertexStep(OUT)
]
Optimized Traversal
===================
Neptune steps: [
NeptuneGraphQueryStep(PropertyValue) {
JoinGroupNode {
PatternNode[(?1=<user-lt1001>, ?5, ?3, ?6) . project ?1,?6 . IsEdgeIdFilter(?6) .
],
{estimatedCardinality=3, expectedTotalOutput=2, indexTime=0, joinTime=0, numSearches=1, actualTotalOutput=2
}
PatternNode[(?6, ?7=<at_millis>, ?8, <~>) . project ?6,?8 .
],
{estimatedCardinality=8892, indexTime=0, joinTime=0, numSearches=1
}
}, annotations={path=[Vertex(?1):GraphStep, Edge(?6):VertexStep#[ip_edges
], PropertyValue(?8):PropertiesStep
], joinStats=true, optimizationTime=1, maxVarId=9, executionTime=271
}
},
NeptuneTraverserConverterStep
]
+ not converted into Neptune steps: [MathStep(_ + 86400001)#[plus_one_day
], NoOpBarrierStep(2500), SelectOneStep(last,ip_edges), NoOpBarrierStep(2500), PropertiesStep([at_millis
],value), MathStep(_ - 86400001)#[minus_one_day
], NoOpBarrierStep(2500), SelectOneStep(last,ip_edges), NoOpBarrierStep(2500), EdgeVertexStep(IN), VertexStep(IN,
[uses_ip
],edge)#[result
], PropertiesStep([at_millis
],value), WherePredicateStep(and(gte(minus_one_day), lt(plus_one_day))), NoOpBarrierStep(2500), SelectOneStep(last,result), NoOpBarrierStep(2500), EdgeVertexStep(OUT)
]
WARNING: >> MathStep(_ + 86400001)#[plus_one_day
] << (or one of its children) is not supported natively yet
Physical Pipeline
=================
NeptuneGraphQueryStep
|-- StartOp
|-- JoinGroupOp
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?1=<user-lt1001>, ?5, ?3, ?6) . project ?1,?6 . IsEdgeIdFilter(?6) .
],
{estimatedCardinality=3, expectedTotalOutput=2
})
|-- SpoolerOp(1000)
|-- DynamicJoinOp(PatternNode[(?6, ?7=<at_millis>, ?8, <~>) . project ?6,?8 .
],
{estimatedCardinality=8892
})
Runtime (ms)
============
Query Execution: 271.410
Traversal Metrics
=================
Step Count Traversers Time (ms) % Dur
-------------------------------------------------------------------------------------------------------------
NeptuneGraphQueryStep(PropertyValue) 2 2 0.338 0.12
NeptuneTraverserConverterStep 2 2 0.058 0.02
MathStep(_ + 86400001)#[plus_one_day
] 2 2 0.085 0.03
NoOpBarrierStep(2500) 2 2 0.027 0.01
SelectOneStep(last,ip_edges) 2 2 0.015 0.01
NoOpBarrierStep(2500) 2 2 0.012 0.00
PropertiesStep([at_millis
],value) 2 2 0.215 0.08
MathStep(_ - 86400001)#[minus_one_day
] 2 2 0.064 0.02
NoOpBarrierStep(2500) 2 2 0.051 0.02
SelectOneStep(last,ip_edges) 2 2 0.014 0.01
NoOpBarrierStep(2500) 2 2 0.012 0.00
EdgeVertexStep(IN) 2 2 0.097 0.04
VertexStep(IN,
[uses_ip
],edge)#[result
] 9358 9358 28.307 10.45
PropertiesStep([at_millis
],value) 9358 9358 233.549 86.18
WherePredicateStep(and(gte(minus_one_day), lt(p... 5 5 8.080 2.98
NoOpBarrierStep(2500) 5 5 0.042 0.02
SelectOneStep(last,result) 5 5 0.013 0.01
NoOpBarrierStep(2500) 5 5 0.013 0.00
EdgeVertexStep(OUT) 5 5 0.012 0.00
>TOTAL - - 271.012 -
Predicates
==========
# of predicates: 38
Results
=======
Count: 5
Output: [v[user-lt1001
], v[user-lt1003
], v[user-lt1002
], v[user-lt1004
], v[user-lt1001
]
]
Index Operations
================
Query execution:
# of statement index ops: 9366
# of unique statement index ops: 4686
Duplication ratio: 2.00
# of terms materialized: 0
Any help will be really appreciated! Thanks!
Looking at the profile, there is quite a bit more going on than just looking things up in an index. First of all there are a lot more than 5K edges being found. The number of traversers indicates the actual number is 9,358 (so almost 10K). For each of those edges the time property has to be found and the math step applied. This is done twice, once for each where, but note that most of the time is spent on the first where as that filters out most of the edges. The second where has a lot less work to do. If this IP address node has the potential to grow and grow in degree (number of edges connected) you likely will want to change your data model to add some intermediate nodes that break the times up into chunks or ranges something similar and then precompute a value and use that to home in on the data you need. Given the amount of work the query is having to do the time does not seem that unreasonable.
I'm trying to set up firms (turtles) in an industry (world) by assigning them different sizes according to their income (firms-own). The distinction between small, medium and large size should be dependent on the percentage of income in relation to the total income.
More specifically, dependent on their income I want the firms with the 30% lowest income to be of size 0.5, the firms with the 60% middle income to be of size 1, and the firms with the 10% highest income to be of size 1.5.
So far I have:
breed [ firms firm ]
firms-own [
income
]
to setup
create-firms number-of-firms [ ;; number of firms to be defined through slider
set income random 100
if income = "low" [ set size 0.5 ] ;; firms with low output are of a small size
if income = "medium" [ set size 1 ] ;; firms with medium output are of a medium size
if income = "high" [ set size 1.5 ] ;; firms with high output are of a large size
end
I know the code does not work because I have not told the firms when to set their firms-own to "low", "medium", or "high". But I don't know how to get them to set it by percentage of the total income.
Thanks for your input here!
If you only have the three classes, you could probably get away with a nested ifelse statement:
breed [ firms firm ]
firms-own [
income
income-class
]
to setup
ca
create-firms 10 [
while [ any? other turtles-here ] [
move-to one-of neighbors
]
set income random 100
]
let firm-incomes sort [income] of firms
print firm-incomes
ask firms [
ifelse income < item ( length firm-incomes / 3 ) firm-incomes [
set income-class "low"
set size 0.5
] [
ifelse income < item ( length firm-incomes * 9 / 10 ) firm-incomes [
set income-class "medium"
set size 1
] [
set income-class "high"
set size 1.5
]
]
]
; Just to check output:
foreach sort-on [ income ] turtles [
t ->
ask t [
show income
show income-class
]
]
reset-ticks
end
Outputs something like:
[16 20 20 47 52 58 69 83 88 97]
(firm 9): 16
(firm 9): "low"
(firm 0): 20
(firm 0): "low"
(firm 3): 20
(firm 3): "low"
(firm 5): 47
(firm 5): "medium"
(firm 7): 52
(firm 7): "medium"
(firm 4): 58
(firm 4): "medium"
(firm 2): 69
(firm 2): "medium"
(firm 1): 83
(firm 1): "medium"
(firm 6): 88
(firm 6): "medium"
(firm 8): 97
(firm 8): "high
Luke Cs answer is pretty good, thumbs up! In case of only 3 income classes, you could also work max-n-of for the 10 % highest income firms and with min-n-of for 30 % lowest income firms. Everything else could be considered medium, but please check the example code below:
breed [ firms firm ]
firms-own [
income
income-class
]
to setup
clear-all
create-firms number-of-firms [ ;; number of firms to be defined through slider
set income random 100
set color red
setxy random-xcor random-ycor
]
ask ( max-n-of ( number-of-firms * 0.1 ) firms [income] ) [ set income-class "high" set size 1.5] ;; the 10% firms with the highest value of income
ask ( min-n-of ( number-of-firms * 0.3 ) firms [income] ) [ set income-class "low" set size 0.5] ;; the 30% firms with the lowest value of income
ask firms with [income-class = 0 ] [set income-class "medium" set size 1] ;; all firms who have no income-class yet are set to "medium"
end
How can I write a code that permit to an agent to change a value of a variables of a patches,where the agent is not above? It is the case of a farmer, in a previous question I asked how to create the farm. Is it possible that an agent could change a variable of different patches during the same tick? thank you very much for your help.
After 1 tick
After 30 tick
It is a special feature of NetLogo that an agent can directly change the value of a variable of the patch it is directly over (i.e., ask turtle 0 [ set pcolor blue ] will turn the patch under turtle 0 to blue), but any turtle can ask any patch to change one of its variables.
For example:
ask turtles [
ask patch-ahead 1 [
set pcolor green
]
]
will tell all turtles to change to color of the patch ahead of them (not directly under) to green.
They can also ask multiple patches to do stuff, like in the in-radius example found in the user manual:
ask turtles [
ask patches in-radius 3 [
set pcolor red
]
]
If this is related to your Farmer question you can use following:
When you want to make changes on a group of patches with a common property you should filter them with their common property , for example if the belong so same Farmer just ask Farm if you want to make changes on a patches from a farm which has food = 1 you can ask
ask farm with [food = 1]
In summary, I think you should include these kind of condition in your cultivate procedure to filter which patch is being changed.
ask farm with [land-sustainability < 2.1 or water-level = 1]
[
set food 1
set pcolor green
]
ask farm with [The condition which they should set fuel to 1]
[
set fuel 1
set pcolor red
]
UPDATE
turtles-own [
profit-from-fuel
profit-from-food
expected-fuel-sell-price
expected-food-sell-price
profit
farm
farm-size
;risk-attitude-food
;risk-attitude-fuel
]
patches-own [
fuel-yeld
food-yeld
land-sustainability
water-level
belongs-to
food
fuel
]
globals [
fuel-sell-price
food-sell-price
governs
]
to setup
clear-all
clear-all-plots
create-farmers
setup-land
reset-ticks
ask turtles
[ set-farm-in-radius farm-size ]
set fuel-sell-price 30 ;+ random 2 + random -2
set food-sell-price 30 ;+ random 2 + random -2
end
to create-farmers
create-turtles 30
[
set shape "person"
setxy random-pxcor random-pycor
set profit-from-fuel 0 ; indicizzazione del profitto iniziale a 0
set profit-from-food 0 ; indicizzazione del profitto iniziale a 0
set farm-size random 5 + 1
set label farm-size
]
end
to setup-land
ask patches [set belongs-to nobody]
ask patches
[
set pcolor 3
set food-yeld 10000
set fuel-yeld 10000
set land-sustainability random 5
set water-level random 3
]
end
to set-farm-in-radius [d]
move-to one-of patches with [not any? other patches in-radius d with [belongs-to != nobody]]
set farm patches in-radius farm-size
ask farm [set belongs-to myself]
let c random 6 + 61
ask farm [set pcolor c]
end
to set-farm-distance [d]
move-to one-of patches with [not any? other patches with [belongs-to != nobody and distance myself < d]]
set farm patches with [distance myself < d]
ask farm [set belongs-to myself]
let c random 6 + 61
ask farm [set pcolor c]
end
to go
tick
ask turtles [
set expected-fuel-sell-price fuel-sell-price + random 5 + random -5
if expected-fuel-sell-price < 0 [set expected-fuel-sell-price 1]
set expected-food-sell-price food-sell-price + random 5 + random -5
if expected-food-sell-price < 0 [set expected-food-sell-price 1]
set profit profit-from-fuel + profit-from-food
if profit = 0 [ set profit 1 ]
]
set fuel-sell-price fuel-sell-price + random 5 + random -5
if fuel-sell-price < 0 or fuel-sell-price = 0 [set fuel-sell-price 1 ]
set food-sell-price food-sell-price + random 5 + random -5
if food-sell-price < 0 or food-sell-price = 0 [set food-sell-price 1]
ask turtles [
cultivate
ask farm [recolor-farm]
set profit profit-from-food + profit-from-fuel
;if water-level > 0.95 [ set profit profit - (profit * ( 2 / profit )) ] valutare se inserire anche una failing probability
]
if ticks = Duration [ stop ]
if ticks > Duration [stop]
end
to cultivate
ifelse land-sustainability < 2.1 or water-level = 1
[
set profit-from-food food-sell-price * (((food-yeld ) ^ (1 - alfa)) * (((water-level) ^ (1 - gamma)) * ((land-sustainability) ^ (gamma)) ^ alfa))
ask farm with [land-sustainability < 2.1 or water-level = 1]
[
set food 1
]
]
[
let utility-from-food ((food-yeld * expected-food-sell-price * land-sustainability) ^ risk-attitude ) / risk-attitude
let utility-from-fuel ((food-yeld * expected-fuel-sell-price * land-sustainability) ^ (1 - risk-attitude) ) / ( 1 - risk-attitude)
ifelse utility-from-food < utility-from-fuel
[
set profit-from-fuel fuel-sell-price * (((fuel-yeld ) ^ (1 - alfa)) * (((water-level) ^ (1 - gamma)) * ((land-sustainability) ^ (gamma)) ^ alfa))
ask farm with [land-sustainability >= 2.1 or water-level != 1][
set fuel 1
]
]
[
set profit-from-food food-sell-price * (((food-yeld ) ^ (1 - alfa)) * (((water-level) ^ (1 - gamma)) * ((land-sustainability) ^ (gamma)) ^ alfa))
ask farm with [land-sustainability >= 2.1 or water-level != 1] [
set food 1
]
]
]
end
to recolor-farm
if food = 1 [set pcolor green ]
if fuel = 1 [set pcolor red]
end
This is another way that you can do it:
turtles-own [
profit-from-fuel
profit-from-food
expected-fuel-sell-price
expected-food-sell-price
profit
farm
farm-size
;risk-attitude-food
;risk-attitude-fuel
]
patches-own [
fuel-yeld
food-yeld
land-sustainability
water-level
belongs-to
food
fuel
]
globals [
fuel-sell-price
food-sell-price
governs
]
to setup
clear-all
clear-all-plots
create-farmers
setup-land
reset-ticks
ask turtles
[ set-farm-in-radius farm-size ]
set fuel-sell-price 30 ;+ random 2 + random -2
set food-sell-price 30 ;+ random 2 + random -2
end
to create-farmers
create-turtles 30
[
set shape "person"
setxy random-pxcor random-pycor
set profit-from-fuel 0 ; indicizzazione del profitto iniziale a 0
set profit-from-food 0 ; indicizzazione del profitto iniziale a 0
set farm-size random 5 + 1
set label farm-size
]
end
to setup-land
ask patches [set belongs-to nobody]
ask patches
[
set pcolor 3
set food-yeld 10000
set fuel-yeld 10000
set land-sustainability random 5
set water-level random 3
]
end
to set-farm-in-radius [d]
move-to one-of patches with [not any? other patches in-radius d with [belongs-to != nobody]]
set farm patches in-radius farm-size
ask farm [set belongs-to myself]
let c random 6 + 61
ask farm [set pcolor c]
end
to set-farm-distance [d]
move-to one-of patches with [not any? other patches with [belongs-to != nobody and distance myself < d]]
set farm patches with [distance myself < d]
ask farm [set belongs-to myself]
let c random 6 + 61
ask farm [set pcolor c]
end
to go
tick
ask turtles [
set expected-fuel-sell-price fuel-sell-price + random 5 + random -5
if expected-fuel-sell-price < 0 [set expected-fuel-sell-price 1]
set expected-food-sell-price food-sell-price + random 5 + random -5
if expected-food-sell-price < 0 [set expected-food-sell-price 1]
set profit profit-from-fuel + profit-from-food
if profit = 0 [ set profit 1 ]
]
set fuel-sell-price fuel-sell-price + random 5 + random -5
if fuel-sell-price < 0 or fuel-sell-price = 0 [set fuel-sell-price 1 ]
set food-sell-price food-sell-price + random 5 + random -5
if food-sell-price < 0 or food-sell-price = 0 [set food-sell-price 1]
ask turtles [
cultivate
ask farm [recolor-farm]
set profit profit-from-food + profit-from-fuel
;if water-level > 0.95 [ set profit profit - (profit * ( 2 / profit )) ] valutare se inserire anche una failing probability
]
if ticks = Duration [ stop ]
if ticks > Duration [stop]
end
to cultivate
let r risk-attitude
let e-f expected-fuel-sell-price
let e-food expected-food-sell-price
ask farm [
ifelse land-sustainability < 2.1 or water-level = 1
[ ask myself [set profit-from-food food-sell-price * (((sum [food-yeld] of farm ) ^ (1 - alfa)) * (((water-level) ^ (1 - gamma)) * ((land-sustainability) ^ (gamma)) ^ alfa))
]set food 1
]
[
if land-sustainability >= 2.1 or water-level = 0
[
let utility-from-food (( food-yeld * e-food * land-sustainability) ^ r ) / r
let utility-from-fuel (( fuel-yeld * e-f * land-sustainability) ^ (1 - r) ) / ( 1 - r)
ifelse utility-from-food < utility-from-fuel
[
ask myself [set profit-from-fuel fuel-sell-price * (((fuel-yeld ) ^ (1 - alfa)) * (((water-level) ^ (1 - gamma)) * ((land-sustainability) ^ (gamma)) ^ alfa)) ]
set fuel 1
]
[ ask myself [set profit-from-food food-sell-price * (((food-yeld ) ^ (1 - alfa)) * (((water-level) ^ (1 - gamma)) * ((land-sustainability) ^ (gamma)) ^ alfa)) ]
set food 1
]
]
]
]
end
to recolor-farm
if food = 1 [set pcolor green ]
if fuel = 1 [set pcolor red]
end
and this is after first tick:
This is final view:
I'm new to this language and I'm suppose to create a graph, so far I've done very basic structure (nodes). I'd like to assign a different value to each node, this value should be taken from a list (like [1 2 3 4]) and this list should be made automaticly.
I've read this command somewhere else [n-values <number> [self]] But i don't really understand what [self] stands for. What I'd like my program to do is to create n nodes (n is taken from the slider value) and then for each node assign values (1 2 3 4 5...n) respectively.
My code so far:
breed [nodes node] ;;Hacemos 'especies'(Clases) de tortugas, el objeto nodes será de una especie node.
nodes-own [info]
to setup
ca ;clear all shortage
ask patches [set pcolor white] ;;hacemos todas las parcelas blancas
create-nodes num-nodes [ ;creamos tantos nodos como el slider diga
set shape "circle" ;con forma de circulo
setxy random-pxcor random-pycor ;;en cualquier lugar.
]
ask nodes [set info 9] ;;<<<ALL nodes have value 9 I'd like to change this!!!
reset-ticks
end
to layout
layout-spring nodes links .5 .5 .5
end
Thanks in advice!
Also: is there a better way to make a graph? (I'm going to work with flow networks!)
I am not sure why you need n-value <number> self
what N-value does is to repeat the reporter in brackets n times , for example if you :
ask nodes [print n-values info [self]]
each node will print its own name for example (node 1) info times.
best place to start is NetLogo Models Library examples there are plenty examples which use nodes and links for graphs such as Small Worlds, Team Assembly, virus network and ...
http://ccl.northwestern.edu/netlogo/models/
or just from netlogo choose file / Models library
This is your code with a few changes, by adding a list to choose the value of info from, however , if you think info should be assigned to the link not to the node you can add it to link-own
breed [nodes node] ;;Hacemos 'especies'(Clases) de tortugas, el objeto nodes será de una especie node.
nodes-own [info]
globals
[My-Num-List]
links-own [msg]
to setup
ca ;clear all shortage
ask patches [set pcolor white] ;;hacemos todas las parcelas blancas
set My-Num-List [ 1 2 3 4 5 6 7 8 9 10] ; or any other list you need
create-nodes num-of-nodes [ ;creamos tantos nodos como el slider diga
set shape "circle" ;con forma de circulo
setxy random-pxcor random-pycor ;;en cualquier lugar
set label-color black
set info one-of My-Num-List
set label info
]
;;<<<ALL nodes have value 9 I'd like to change this!!!
reset-ticks
end
to layout
crtlinks
layout-spring nodes links .5 .5 .5
end
to crtlinks
ask turtles
[
create-links-with n-of 2 other turtles
[
set msg one-of [ "C" "A" "B"]
set label msg
set label-color black
set thickness 0.2
]
]