muse2/
agent.rs

1//! Agents drive the economy of the MUSE 2.0 simulation, through relative investment in different
2//! assets.
3use crate::commodity::{Commodity, CommodityID};
4use crate::id::{define_id_getter, define_id_type};
5use crate::process::ProcessID;
6use crate::region::RegionID;
7use indexmap::IndexMap;
8use serde::Deserialize;
9use serde_string_enum::DeserializeLabeledStringEnum;
10use std::collections::HashMap;
11use std::collections::HashSet;
12use std::rc::Rc;
13
14define_id_type! {AgentID}
15
16/// A map of [`Agent`]s, keyed by agent ID
17pub type AgentMap = IndexMap<AgentID, Agent>;
18
19/// A map of cost limits for an agent, keyed by year
20pub type AgentCostLimitsMap = HashMap<u32, AgentCostLimits>;
21
22/// A map of commodity portions for an agent, keyed by commodity and year
23pub type AgentCommodityPortionsMap = HashMap<(CommodityID, u32), f64>;
24
25/// An agent in the simulation
26#[derive(Debug, Clone, PartialEq)]
27pub struct Agent {
28    /// A unique identifier for the agent.
29    pub id: AgentID,
30    /// A text description of the agent.
31    pub description: String,
32    /// The proportion of the commodity production that the agent is responsible for.
33    pub commodity_portions: AgentCommodityPortionsMap,
34    /// The processes that the agent will consider investing in.
35    pub search_space: Vec<AgentSearchSpace>,
36    /// The decision rule that the agent uses to decide investment.
37    pub decision_rule: DecisionRule,
38    /// Cost limits (e.g. capital cost, annual operating cost)
39    pub cost_limits: AgentCostLimitsMap,
40    /// The regions in which this agent operates.
41    pub regions: HashSet<RegionID>,
42    /// The agent's objectives.
43    pub objectives: Vec<AgentObjective>,
44}
45define_id_getter! {Agent, AgentID}
46
47/// The cost limits for an agent in a particular year
48#[derive(Debug, Clone, PartialEq)]
49pub struct AgentCostLimits {
50    /// The maximum capital cost the agent will pay.
51    pub capex_limit: Option<f64>,
52    /// The maximum annual operating cost (fuel plus var_opex etc) that the agent will pay.
53    pub annual_cost_limit: Option<f64>,
54}
55
56/// Search space for an agent
57#[derive(Debug, Clone, PartialEq)]
58pub struct AgentSearchSpace {
59    /// The year the objective is relevant for
60    pub year: u32,
61    /// The commodity to apply the search space to
62    pub commodity: Rc<Commodity>,
63    /// The agent's search space
64    pub search_space: Vec<ProcessID>,
65}
66
67/// The decision rule for a particular objective
68#[derive(Debug, Clone, PartialEq)]
69pub enum DecisionRule {
70    /// Used when there is only a single objective
71    Single,
72    /// A simple weighting of objectives
73    Weighted,
74    /// Objectives are considered in a specific order
75    Lexicographical {
76        /// The tolerance around the main objective to consider secondary objectives. This is an absolute value of maximum deviation in the units of the main objective.
77        tolerance: f64,
78    },
79}
80
81/// An objective for an agent with associated parameters
82#[derive(Debug, Clone, Deserialize, PartialEq)]
83pub struct AgentObjective {
84    /// Unique agent id identifying the agent this objective belongs to
85    pub agent_id: AgentID,
86    /// The year the objective is relevant for
87    pub year: u32,
88    /// Acronym identifying the objective (e.g. LCOX)
89    pub objective_type: ObjectiveType,
90    /// For the weighted sum decision rule, the set of weights to apply to each objective.
91    pub decision_weight: Option<f64>,
92    /// For the lexico decision rule, the order in which to consider objectives.
93    pub decision_lexico_order: Option<u32>,
94}
95
96/// The type of objective for the agent
97#[derive(Debug, Clone, PartialEq, DeserializeLabeledStringEnum)]
98pub enum ObjectiveType {
99    /// Average cost of one unit of output commodity over its lifetime
100    #[string = "lcox"]
101    LevelisedCostOfX,
102}