Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Understanding the r parameter in nearby_ids #565

Closed
marcelovmaciel opened this issue Oct 27, 2021 · 6 comments
Closed

Understanding the r parameter in nearby_ids #565

marcelovmaciel opened this issue Oct 27, 2021 · 6 comments
Assignees
Labels
bug Something isn't working continuous Continuous space related question Further information is requested

Comments

@marcelovmaciel
Copy link
Contributor

I am trying to understand what the r parameter does in the nearby_ids procedure, specifically in the continuous case. In the docs the following is said: " Standard distance according to the space metric." Could someone elaborate to someone whose mathematical training is limited to calculus and linear algebra (I completely understand if y'all are busy!!) ? What is the change in behavior that changing r will have in the procedure?

I am writing a simulation in which I set some "central" points and want to get nearby points. So, I wrote some code to explore it. However, when I set r to 1, and exact to true, and test the euclidean distance (from the central points) I get a distance of ~1.2, which is not the behavior I was expecting. However, when I set r to 2 I still get a distance of 1.2! Doubling r does not change the euclidean distance of the points sampled using the nearby_ids procedure.

using Agents, Distances, Distributions

mutable struct  DummyAgent{n} <: AbstractAgent
    id::Int
    pos::NTuple{n,Float64}
end

function sample_Centerpoints_to_nearbydummies(npoints, model)
    ids = collect(allids(model))

    centerids= sample(ids,npoints,replace = false)

    centerpoints_nearbydummies = Dict(Pair(k,  -1) for k in centerids)

    return(centerpoints_nearbydummies)

end

function set_nearbies!(model)
    pointsdict = model.properties[:pointsdict]
    r = model.properties[:r]
    get_nearbypointid(pointid)= sample(collect(
        nearby_ids(model[pointid],
                       model, r,
                       exact = true)))

    centerpoint_nearbypoint_pairs = Dict(Pair(pid,
                                              get_nearbypointid(pid))
                                         for pid in keys(pointsdict))

    for (cid, nid) in centerpoint_nearbypoint_pairs
        pointsdict[cid] = nid
    end
end


function model_initialize(nagents,n, ncs,  r = 1)
    space = ContinuousSpace(ntuple(x -> float(1),n))

    model = ABM(DummyAgent{n}, space, properties = Dict(:n=> n,
                                                        :r => r,
                                                        :pointsdict => Dict{}()))

        for i in 1:nagents
        pos = Tuple(rand(Uniform(0,1), n))
                add_agent_pos!(DummyAgent{n}(i, pos), model)
                end


    model.properties[:pointsdict] = sample_Centerpoints_to_nearbydummies(ncs, model)
    set_nearbies!(model)
    return model
end


r=1
for i in 1:10
    m = model_initialize(1000,2, 100, r)
    maximum([Distances.euclidean(m[cid].pos,m[nid].pos)
             for (cid,nid) in m.properties[:pointsdict]]) |> println
end

#=
1.0600469817653908
1.1146469931411775
1.1382090904186484
1.043741312973825
0.975082751450818
1.0846058257611162
1.228164192811571
1.1257033374510226
1.180173316553839
1.142794281626783
=#



r=2
for i in 1:10
    m = model_initialize(1000,2, 100, r)
    maximum([Distances.euclidean(m[cid].pos,m[nid].pos)
             for (cid,nid) in m.properties[:pointsdict]]) |> println
end


#=
1.230712318455345
1.1299289372658443
1.2296617406308241
1.1649147171916512
1.171758995244182
1.0287872874615116
1.0844658585268767
1.0700902907578802
1.0112842966992845
1.041351684524605
=#

So, the code above shows what I'm saying. I admit I don't really understand what the r parameter does here and changing it doesn't seem to change the radius of what is being sampled in that code.

@Datseris Datseris self-assigned this Oct 29, 2021
@Datseris Datseris added bug Something isn't working continuous Continuous space related question Further information is requested labels Oct 29, 2021
@Datseris
Copy link
Member

Your post is long and it will take me some time to read and reply. Quick answer on the first question:

"Standard distance according to the space metric." means that when you create ContinuousSpace you decide its metric, which is Chebyshev or Euclidean. Google these two names and you'll immediatelly understand what they mean. Now, given this metric, one calculate the distance between two points in the space (the agent locations). If this distance is less than r, then they are neighbors.

@Datseris
Copy link
Member

when I set r to 1, and exact to true, and test the euclidean distance (from the central points) I get a distance of ~1.2,

This might be a bug, I'll return here once I have more time to read the full code you paste.

@Libbum
Copy link
Member

Libbum commented Oct 29, 2021

Not the complete picture, but

(ntuple(x -> float(1),n))

Your space has been set to a maximum of one in any direction.

Since r is the search range, it doesn't matter if you're searching 1 or 2 units away when your maximum possible area is 1^2. Try the same examples with (ntuple(x -> float(10),n)).

@marcelovmaciel
Copy link
Contributor Author

marcelovmaciel commented Oct 29, 2021

@Libbum thank you and it makes sense, but I've tested here with say an r of 0.2 or 0.3 and got the same result as above. Then I changed the bound to 10 (and accordingly sampled agents' positions from 0 to 10) to test doubling r and the result still does not change (from r =1 to r = 2):

julia> r = 1;
julia> for i in 1:10
           m = model_initialize(1000,2, 100, r )
           maximum([Distances.euclidean(m[cid].pos,m[nid].pos)
                    for (cid,nid) in m.properties[:pointsdict]]) |> println
       end
#= 9.695498878763921
13.674575357835351
13.252550529785903
9.974019672427724
9.875425090648458
9.887215555446176
9.754798725473133
9.807639365571072
9.728916662458216
13.321711803841492
=#
julia> r = 2
2

julia> for i in 1:10
           m = model_initialize(1000,2, 100, r )
           maximum([Distances.euclidean(m[cid].pos,m[nid].pos)
                    for (cid,nid) in m.properties[:pointsdict]]) |> println
       end
#=
9.568065496062083
9.87265005574368
9.46048586970795
12.681313962716818
12.487125144176273
12.875428923136857
9.494411136950713
9.59346749363167
10.00765614970002
9.955890829815404
=#

@marcelovmaciel
Copy link
Contributor Author

I think the problem was that periodic was true! Now it all makes sense. If I'm going around the space doubling the r won't change a thing, since we already wrapped the space. The exact keyword still does not give the exact bound, but that may be due to floating-point errors, and for my application, it is not a problem.

@Datseris
Copy link
Member

Datseris commented Jan 7, 2022

c.f. also #566

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working continuous Continuous space related question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants