4 #ifndef UAT_SIMULATION_HPP
5 #define UAT_SIMULATION_HPP
14 #include <cool/compose.hpp>
34 constexpr
auto no_owner = std::numeric_limits<uint_t>::max();
36 namespace permit_private_status
64 std::variant<permit_private_status::on_sale, permit_private_status::in_use, permit_private_status::out_of_limits>
current;
70 namespace agent_private_status
100 void update_active(std::vector<
id_t>);
106 std::vector<
id_t> active_;
118 namespace stop_criterion
133 using stop_criterion_t = std::variant<stop_criterion::no_agents_t, stop_criterion::time_threshold_t>;
153 std::mt19937 rnd(opts.seed ? *opts.seed : std::random_device{}());
155 agents_private_status_t agents;
156 std::vector<id_t> keep_active;
160 std::deque<std::unordered_map<permit<R>, permit_private_status_t>> data;
162 permit_private_status_t ool = {permit_private_status::out_of_limits{}, {}};
163 auto book = [&t0, &data, &ool, &opts](region_view loc,
uint_t t)
mutable -> permit_private_status_t& {
166 if (opts.time_window && t > t0 + 1 + *opts.time_window)
168 while (t - t0 >= data.size())
170 return data[t - t0][{loc.downcast<R>(), t}];
173 auto safe_book = [&book](region_view loc,
uint_t t) -> permit_private_status_t {
return book(loc, t); };
175 auto public_access = [&book](
auto id) {
176 return [
id = id, &book](region_view s,
uint_t t) -> permit_public_status_t {
177 using namespace permit_private_status;
178 using namespace permit_public_status;
179 const auto& pstatus = book(s, t);
182 [](out_of_limits) -> permit_public_status_t {
return unavailable{}; },
183 [&](in_use
status) -> permit_public_status_t {
186 [&](on_sale
status) -> permit_public_status_t {
193 const auto stop = [&] {
194 using namespace stop_criterion;
195 return std::visit(cool::compose{
196 [&](no_agents_t) {
return agents.active_count() == 0; },
197 [&](time_threshold_t th) {
return t0 > th.t; },
199 opts.stop_criterion);
203 if (opts.simulation_callback)
208 auto new_agents = opts.factory(t0, rnd());
209 for (
auto& agent : new_agents)
210 agents.insert(std::move(agent));
215 std::vector<permit<R>> bids;
216 for (
const auto id : agents.active()) {
220 using namespace permit_private_status;
221 const auto visitor = cool::compose{[](out_of_limits) {
return false; }, [](in_use) {
return false; },
224 if (
status.highest_bidder == no_owner)
225 bids.emplace_back(s.downcast<R>(), t);
226 status.highest_bidder = id;
231 return std::visit(visitor, book(s, t).current);
234 auto access = public_access(
id);
239 if (bids.size() > 0) {
240 const auto first_active = agents.active().front();
241 for (
const auto& [s, t] : bids) {
242 const auto status = std::get<permit_private_status::on_sale>(book(s, t).current);
243 if (opts.trade_callback)
244 opts.trade_callback({t0,
status.owner,
status.highest_bidder, s, t,
status.highest_bid});
246 agents.at(
status.highest_bidder).on_bought(s, t,
status.highest_bid);
247 if (
status.owner != no_owner &&
status.owner >= first_active)
248 agents.at(
status.owner).on_sold(s, t,
status.highest_bid);
250 auto& pstatus = book(s, t);
251 pstatus.current = permit_private_status::in_use{
status.highest_bidder};
252 pstatus.history.push_back({
status.min_value,
status.highest_bid});
259 std::vector<std::tuple<R, uint_t, uint_t, value_t>> asks;
260 for (
const auto id : agents.active()) {
264 using namespace permit_private_status;
265 const auto visitor = cool::compose{[](out_of_limits) {
return false; },
269 asks.emplace_back(s.downcast<R>(), t, id, v);
275 asks.emplace_back(s.downcast<R>(), t, id, v);
278 return std::visit(visitor, book(s, t).current);
281 auto access = public_access(
id);
285 for (
const auto& [s, t,
id, v] : asks)
286 book(s, t).current = permit_private_status::on_sale{.owner = id, .min_value = v};
291 keep_active.reserve(agents.active_count());
292 for (
const auto id : agents.active())
293 if (!agents.at(
id).stop(t0, rnd()))
294 keep_active.push_back(
id);
295 agents.update_active(std::move(keep_active));
Defines the agent class and related types.
type_safe::function_ref< bool(region_view, uint_t, value_t)> bid_fn
Function reference that allows the agent to bid for a permit.
Definition: agent.hpp:52
type_safe::function_ref< bool(region_view, uint_t, value_t)> ask_fn
Function reference that allows the agent to ask for a permit.
Definition: agent.hpp:55
type_safe::function_ref< permit_public_status_t(region_view, uint_t)> permit_public_status_fn
Function reference that returns the public status of a permit.
Definition: agent.hpp:58
std::variant< permit_public_status::unavailable, permit_public_status::available, permit_public_status::owned > permit_public_status_t
Variant that represents the possible public status of a permit.
Definition: agent.hpp:49
Private status of the collection of agents in the simulation.
Definition: simulation.hpp:93
auto status(id_t) const -> agent_private_status_t
Get the private status of an agent with the given id.
auto active_count() const -> uint_t
Get the number of active agents.
auto active() const -> std::span< const id_t >
Get the ids of the active agents.
A type-erased class that represents an agent in the simulation.
Definition: agent.hpp:149
A non-owning wrapper to an atomic region in the airspace.
Definition: permit.hpp:21
std::variant< stop_criterion::no_agents_t, stop_criterion::time_threshold_t > stop_criterion_t
Variant that represents the possible stop criteria for the simulation.
Definition: simulation.hpp:133
auto simulate(const simulation_opts_t< R > &opts={}) -> void
Definition: simulation.hpp:151
std::function< void(trade_info_t< R >)> trade_callback_t
Callback type that receives information about a trade transaction.
Definition: simulation.hpp:113
constexpr auto no_owner
Unique value to represent the absence of an owner.
Definition: simulation.hpp:34
std::function< std::vector< any_agent >(uint_t, int)> factory_t
A function type that generates agents for each iteration.
Definition: simulation.hpp:20
std::function< void(uint_t, const agents_private_status_t &, permit_private_status_fn)> simulation_callback_t
Callback type that receives information about the status of the simulation.
Definition: simulation.hpp:116
type_safe::function_ref< permit_private_status_t(region_view, uint_t)> permit_private_status_fn
Function reference that allows the simulation to access the private status of an agent.
Definition: simulation.hpp:110
std::variant< agent_private_status::inactive, agent_private_status::active > agent_private_status_t
Variant that represents the private status of an agent.
Definition: simulation.hpp:89
Represents the private status of an agent that is active in the simulation.
Definition: simulation.hpp:81
Represents the private status of an agent that is inactive in the simulation.
Definition: simulation.hpp:75
Represents the private status of a permit that is not available for trading.
Definition: simulation.hpp:50
Represents the private status of a permit that is available for trading.
Definition: simulation.hpp:41
uint_t highest_bidder
The current highest bidder.
Definition: simulation.hpp:44
value_t min_value
The minimum value (exclusive) that the owner is willing to sell the permit.
Definition: simulation.hpp:43
uint_t owner
The owner of the permit.
Definition: simulation.hpp:42
value_t highest_bid
The current highest bid.
Definition: simulation.hpp:45
Represents the private status of a permit that is out of limits (past and future).
Definition: simulation.hpp:56
Represents the private status of a permit.
Definition: simulation.hpp:62
std::variant< permit_private_status::on_sale, permit_private_status::in_use, permit_private_status::out_of_limits > current
The current status of the permit.
Definition: simulation.hpp:64
std::vector< trade_value_t > history
The history of trades involving the permit.
Definition: simulation.hpp:67
Options to configure the simulation.
Definition: simulation.hpp:137
simulation_callback_t simulation_callback
Callback to receive information about the status of the simulation.
Definition: simulation.hpp:142
stop_criterion_t stop_criterion
The criterion to stop the simulation.
Definition: simulation.hpp:140
std::optional< uint_t > time_window
Maximum time ahead a permit can be traded.
Definition: simulation.hpp:139
std::optional< uint_t > seed
Random seed.
Definition: simulation.hpp:143
trade_callback_t< R > trade_callback
Callback to receive information about a trade transaction.
Definition: simulation.hpp:141
factory_t factory
Generator of agents for each iteration.
Definition: simulation.hpp:138
Stop criterion that stops the simulation when there are no agents.
Definition: simulation.hpp:123
Stop criterion that stops the simulation when a time threshold is reached.
Definition: simulation.hpp:127
Type to represent the information in a trade transaction.
Definition: simulation.hpp:24
std::size_t uint_t
Default unsigned integer type.
Definition: type.hpp:29
std::size_t id_t
Default type for identifier.
Definition: type.hpp:32
double value_t
Default type for price.
Definition: type.hpp:35