Thank you so much for your response! It is very helpful. I like Simulate.jl very much, which would be have performance benefit.I have write an example of using the bike-share described as follows based on your example.
In a bike-share system, there is one bike and two users. The user use the bike as follows.
step1: The user start the trip at time start_t
from the bike station;
step2: If there is bike, rent the bike and use the bike for trip_t
and return the bike;
If no bike, wait there
I write a struct Resource
in resource.jl
to describe the resource similar to SimPy
and SimJulia.jl
as follows.
using Simulate
import Base.isempty
import Base.length
abstract type ResType end
abstract type AbstractResource end
struct DiscreteSource <: ResType end
struct ResourceBase{T<:ResType} <: AbstractResource
container::Channel{T}
res_type::DataType
end
function ResourceBase{T}(n::Int=0) where T<:ResType
res = Channel{T}(n)
for i in 1:n
put!(res, T())
end
return ResourceBase{T}( res, T)
end
request!(res::AbstractResource) = take!(res.container)
release!(res::AbstractResource, source::ResType) = put!(res.container, source)
release!(res::AbstractResource) = put!(res.container, res.res_type())
isempty(res::AbstractResource) = !isready(res.container)
length(res::AbstractResource) = length( res.container.data )
capacity( res::AbstractResource ) = res.container.sz_max
capacity!(res::AbstractResource, n::Int) = (res.container.sz_max = n)
slots(res::AbstractResource) = ( res.container.sz_max - length(res) )
const Resource = ResourceBase{DiscreteSource}
The simulation is as follows,
include("resource.jl")
function ride_bike(sim::Simulator, name::String, bikes::Resource, start_time::Int, trip_duration::Int, user_id::Int)
delay!(sim.env, start_time)
println( @sprintf("%s starting at %d", name, tau(sim.env)) ) # this line will result in logic error
push!(sim.log, @sprintf("%s starting at %d", name, tau(sim.env)) )
request!(bikes)
println( @sprintf("%s rent a bikeat %d", name, tau(sim.env))) # this line will result in logic error
push!(sim.log, @sprintf("%s rent a bike at %d", name, tau(sim.env)) )
delay!(sim.env, trip_duration)
release!(bikes)
println( @sprintf("%s return the bike at %d", name, tau(sim.env)))
push!(sim.log, @sprintf("%s return the bike at %d", name, tau(sim.env)) )
@show user_id, driving_time, tau(sim.env)
end
function sim()
bikes = Resource(1)
sim = Simulator()
id = 0
start_t = [0, 2]
rent_t = [5, 1]
for i in 1:2
id +=1
t = start_t[i]
d = rent_t[i]
process!(sim.env, SP(id, ride_bike, sim, "Car $id", bikes, t, d, id), 1 ) # process started emediately
end
@show "start simulate"
run!(sim.env, 20)
@show sim.traffic_inf
for r in sim.log
println(r)
end
end
sim()
The result is not correct as follows,
"start simulate" = "start simulate"
Car 1 starting at 0
Car 1 rent a bikeat 0
Car 2 starting at 2
Car 2 rent a bikeat 7
Car 1 return the bike at 7
(user_id, driving_time, tau(sim.env)) = (1, 0, 20.0)
sim.traffic_inf = Dict{Int64,Tuple{Int64,Int64}}()
Car 1 starting at 0
Car 1 rent a bike at 2
Car 2 starting at 7
Car 2 rent a bike at 20
Car 1 return the bike at 20
If I remove the println()
in function ride_bike()
, the result is correct.
function ride_bike(sim::Simulator, name::String, bikes::Resource, start_time::Int, trip_duration::Int, user_id::Int)
delay!(sim.env, start_time)
#println( @sprintf("%s starting at %d", name, tau(sim.env)) )
push!(sim.log, @sprintf("%s starting at %d", name, tau(sim.env)) )
request!(bikes)
#println( @sprintf("%s rent a bikeat %d", name, tau(sim.env)))
push!(sim.log, @sprintf("%s rent a bike at %d", name, tau(sim.env)) )
delay!(sim.env, trip_duration)
release!(bikes)
#println( @sprintf("%s return the bike at %d", name, tau(sim.env)))
push!(sim.log, @sprintf("%s return the bike at %d", name, tau(sim.env)) )
@show user_id, driving_time, tau(sim.env)
end
The correct result as follows
"start simulate" = "start simulate"
(user_id, driving_time, tau(sim.env)) = (1, 0, 5.0)
(user_id, driving_time, tau(sim.env)) = (2, 2, 6.0)
sim.traffic_inf = Dict{Int64,Tuple{Int64,Int64}}()
Car 1 starting at 0
Car 1 rent a bike at 0
Car 2 starting at 2
Car 1 return the bike at 5
Car 2 rent a bike at 5
Car 2 return the bike at 6
Two questions:
(1) Why the result is different when I use ‘println()’ in ride_bike()
?
(2) How to model “If there is no bike available, the user wait for t
, after that the user leave (cancel the request of a bike).”
Thank you so much!