Game Theory & Strategic Decision Making
Game theory analyzes strategic interactions between rational decision-makers, providing frameworks for optimizing outcomes in competitive and cooperative scenarios across business, economics, and operations research.
Mathematical Foundations
Game Representation
A strategic game consists of:
- Players: Set [mathematical expression] of decision makers
- Strategies: Set [mathematical expression] of available actions for each player [mathematical expression]
- Payoffs: Function [mathematical expression]
Nash Equilibrium
A strategy profile [mathematical expression] is a Nash equilibrium if:
Where [mathematical expression] represents the strategies of all players except player [mathematical expression].
Mixed Strategies
A mixed strategy is a probability distribution over pure strategies:
Expected payoff under mixed strategies:
Evolutionarily Stable Strategy (ESS)
Strategy [mathematical expression] is evolutionarily stable if for all [mathematical expression]:
Rust Implementation
use nalgebra::{DMatrix, DVector};
use std::collections::HashMap;
use itertools::Itertools;
/// Represents a strategic game with multiple players.
#[derive(Debug, Clone)]
pub struct StrategicGame {
/// Number of players
num_players: usize,
/// Strategy sets for each player
strategy_sets: Vec<Vec<String>>,
/// Payoff matrices for each player
payoff_matrices: Vec<DMatrix<f64>>,
}
impl StrategicGame {
/// Create a new strategic game.
///
/// # Arguments
/// * `strategy_sets` - Vector of strategy names for each player
/// * `payoff_matrices` - Payoff matrices for each player
pub fn new(
strategy_sets: Vec<Vec<String>>,
payoff_matrices: Vec<DMatrix<f64>>
) -> Self {
let num_players = strategy_sets.len();
assert_eq!(num_players, payoff_matrices.len());
Self {
num_players,
strategy_sets,
payoff_matrices,
}
}
/// Find pure strategy Nash equilibria.
pub fn find_pure_nash_equilibria(&self) -> Vec<Vec<usize>> {
let mut equilibria = Vec::new();
// Generate all strategy profiles
let strategy_counts: Vec<usize> = self.strategy_sets.iter()
.map(|strategies| strategies.len())
.collect();
let total_profiles = strategy_counts.iter().product::<usize>();
for profile_index in 0..total_profiles {
let profile = self.index_to_profile(profile_index, &strategy_counts);
if self.is_nash_equilibrium(&profile) {
equilibria.push(profile);
}
}
equilibria
}
/// Check if a strategy profile is a Nash equilibrium.
fn is_nash_equilibrium(&self, profile: &[usize]) -> bool {
for player in 0..self.num_players {
let current_payoff = self.get_payoff(player, profile);
// Check if player can improve by unilateral deviation
for alternative_strategy in 0..self.strategy_sets[player].len() {
if alternative_strategy == profile[player] {
continue;
}
let mut alternative_profile = profile.to_vec();
alternative_profile[player] = alternative_strategy;
let alternative_payoff = self.get_payoff(player, &alternative_profile);
if alternative_payoff > current_payoff {
return false; // Player can improve
}
}
}
true
}
/// Get payoff for a player given a strategy profile.
fn get_payoff(&self, player: usize, profile: &[usize]) -> f64 {
// For simplicity, assume 2-player games with matrix representation
if self.num_players == 2 {
self.payoff_matrices[player][(profile[0], profile[1])]
} else {
// For n-player games, would need tensor representation
0.0 // Placeholder
}
}
/// Convert linear index to strategy profile.
fn index_to_profile(&self, mut index: usize, strategy_counts: &[usize]) -> Vec<usize> {
let mut profile = vec![0; self.num_players];
for (i, &count) in strategy_counts.iter().enumerate().rev() {
profile[i] = index % count;
index /= count;
}
profile
}
/// Calculate mixed strategy Nash equilibrium for 2-player games.
pub fn mixed_nash_equilibrium_2p(&self) -> Option<(DVector<f64>, DVector<f64>)> {
if self.num_players != 2 {
return None;
}
let p1_payoffs = &self.payoff_matrices[0];
let p2_payoffs = &self.payoff_matrices[1];
// For 2x2 games, solve analytically
if p1_payoffs.nrows() == 2 && p1_payoffs.ncols() == 2 {
self.solve_2x2_mixed_nash(p1_payoffs, p2_payoffs)
} else {
// For larger games, would use linear programming
None
}
}
/// Solve 2x2 mixed strategy Nash equilibrium.
fn solve_2x2_mixed_nash(
&self,
p1_payoffs: &DMatrix<f64>,
p2_payoffs: &DMatrix<f64>
) -> Option<(DVector<f64>, DVector<f64>)> {
// Player 1's mixed strategy makes Player 2 indifferent
let p2_expected_0 = p2_payoffs[(0, 0)] - p2_payoffs[(1, 0)];
let p2_expected_1 = p2_payoffs[(0, 1)] - p2_payoffs[(1, 1)];
if (p2_expected_0 - p2_expected_1).abs() < 1e-10 {
return None; // No mixed strategy equilibrium
}
let p1_prob_0 = p2_expected_1 / (p2_expected_1 - p2_expected_0);
// Player 2's mixed strategy makes Player 1 indifferent
let p1_expected_0 = p1_payoffs[(0, 0)] - p1_payoffs[(0, 1)];
let p1_expected_1 = p1_payoffs[(1, 0)] - p1_payoffs[(1, 1)];
if (p1_expected_0 - p1_expected_1).abs() < 1e-10 {
return None;
}
let p2_prob_0 = p1_expected_1 / (p1_expected_1 - p1_expected_0);
// Check if probabilities are valid
if p1_prob_0 < 0.0 || p1_prob_0 > 1.0 || p2_prob_0 < 0.0 || p2_prob_0 > 1.0 {
return None;
}
let p1_strategy = DVector::from_vec(vec![p1_prob_0, 1.0 - p1_prob_0]);
let p2_strategy = DVector::from_vec(vec![p2_prob_0, 1.0 - p2_prob_0]);
Some((p1_strategy, p2_strategy))
}
}
/// Evolutionary game dynamics simulation.
pub struct EvolutionaryGameSimulator {
/// Population size
population_size: usize,
/// Strategy proportions
strategy_proportions: DVector<f64>,
/// Payoff matrix
payoff_matrix: DMatrix<f64>,
/// Mutation rate
mutation_rate: f64,
}
impl EvolutionaryGameSimulator {
/// Create new evolutionary game simulator.
pub fn new(
strategy_proportions: DVector<f64>,
payoff_matrix: DMatrix<f64>,
population_size: usize,
mutation_rate: f64,
) -> Self {
Self {
population_size,
strategy_proportions,
payoff_matrix,
mutation_rate,
}
}
/// Run replicator dynamics for specified iterations.
pub fn run_replicator_dynamics(&mut self, iterations: usize, dt: f64) -> Vec<DVector<f64>> {
let mut history = Vec::with_capacity(iterations);
for _ in 0..iterations {
history.push(self.strategy_proportions.clone());
let fitness = &self.payoff_matrix * &self.strategy_proportions;
let average_fitness = self.strategy_proportions.dot(&fitness);
// Replicator equation: dx/dt = x(f(x) - φ(x))
for i in 0..self.strategy_proportions.len() {
let growth_rate = self.strategy_proportions[i] *
(fitness[i] - average_fitness);
self.strategy_proportions[i] += dt * growth_rate;
}
// Normalize to maintain probability distribution
let sum: f64 = self.strategy_proportions.sum();
self.strategy_proportions /= sum;
// Apply mutation
self.apply_mutation();
}
history
}
/// Apply random mutations to strategy proportions.
fn apply_mutation(&mut self) {
for i in 0..self.strategy_proportions.len() {
if rand::random::<f64>() < self.mutation_rate {
let mutation = (rand::random::<f64>() - 0.5) * 0.01;
self.strategy_proportions[i] =
(self.strategy_proportions[i] + mutation).max(0.0);
}
}
// Renormalize
let sum: f64 = self.strategy_proportions.sum();
if sum > 0.0 {
self.strategy_proportions /= sum;
}
}
/// Find evolutionarily stable strategies.
pub fn find_ess(&self) -> Vec<usize> {
let mut ess_strategies = Vec::new();
for i in 0..self.payoff_matrix.nrows() {
if self.is_evolutionarily_stable(i) {
ess_strategies.push(i);
}
}
ess_strategies
}
/// Check if a pure strategy is evolutionarily stable.
fn is_evolutionarily_stable(&self, strategy: usize) -> bool {
let mut test_strategy = DVector::zeros(self.payoff_matrix.nrows());
test_strategy[strategy] = 1.0;
let own_fitness = (&self.payoff_matrix * &test_strategy)[strategy];
for j in 0..self.payoff_matrix.nrows() {
if j == strategy {
continue;
}
let mut mutant_strategy = DVector::zeros(self.payoff_matrix.nrows());
mutant_strategy[j] = 1.0;
let mutant_fitness = (&self.payoff_matrix * &test_strategy)[j];
if mutant_fitness >= own_fitness {
return false;
}
}
true
}
}
/// Auction theory implementation.
pub struct AuctionAnalyzer {
/// Number of bidders
num_bidders: usize,
/// Valuation distributions (simplified as uniform)
valuation_bounds: Vec<(f64, f64)>,
}
impl AuctionAnalyzer {
pub fn new(num_bidders: usize, valuation_bounds: Vec<(f64, f64)>) -> Self {
Self {
num_bidders,
valuation_bounds,
}
}
/// Calculate optimal bid in first-price sealed-bid auction.
pub fn first_price_optimal_bid(&self, bidder: usize, valuation: f64) -> f64 {
let (low, high) = self.valuation_bounds[bidder];
// For uniform distribution and symmetric equilibrium
let n = self.num_bidders as f64;
valuation * (n - 1.0) / n
}
/// Calculate expected revenue for different auction formats.
pub fn compare_auction_revenues(&self) -> AuctionComparison {
let n = self.num_bidders as f64;
// Assuming uniform valuations [0, 1] for simplicity
let first_price_revenue = (n - 1.0) / (n + 1.0);
let second_price_revenue = (n - 1.0) / (n + 1.0); // Revenue equivalence
let english_auction_revenue = (n - 1.0) / (n + 1.0);
let dutch_auction_revenue = (n - 1.0) / (n + 1.0);
AuctionComparison {
first_price: first_price_revenue,
second_price: second_price_revenue,
english: english_auction_revenue,
dutch: dutch_auction_revenue,
}
}
}
/// Cooperative game theory: Shapley value calculation.
pub struct CooperativeGameAnalyzer {
/// Number of players
num_players: usize,
/// Characteristic function mapping coalitions to values
characteristic_function: HashMap<Vec<bool>, f64>,
}
impl CooperativeGameAnalyzer {
pub fn new(num_players: usize) -> Self {
Self {
num_players,
characteristic_function: HashMap::new(),
}
}
/// Set coalition value.
pub fn set_coalition_value(&mut self, coalition: Vec<bool>, value: f64) {
assert_eq!(coalition.len(), self.num_players);
self.characteristic_function.insert(coalition, value);
}
/// Calculate Shapley values for all players.
pub fn calculate_shapley_values(&self) -> DVector<f64> {
let mut shapley_values = DVector::zeros(self.num_players);
for player in 0..self.num_players {
shapley_values[player] = self.shapley_value(player);
}
shapley_values
}
/// Calculate Shapley value for specific player.
fn shapley_value(&self, player: usize) -> f64 {
let mut total_contribution = 0.0;
// Iterate over all possible coalitions not containing the player
for coalition_size in 0..self.num_players {
let coalitions_without_player = self.generate_coalitions_of_size(
coalition_size,
player
);
for mut coalition in coalitions_without_player {
let coalition_value = self.get_coalition_value(&coalition);
// Add player to coalition
coalition[player] = true;
let coalition_with_player_value = self.get_coalition_value(&coalition);
let marginal_contribution = coalition_with_player_value - coalition_value;
// Weight by coalition size probability
let weight = self.factorial(coalition_size) *
self.factorial(self.num_players - coalition_size - 1) /
self.factorial(self.num_players);
total_contribution += weight * marginal_contribution;
}
}
total_contribution
}
/// Generate all coalitions of specific size excluding a player.
fn generate_coalitions_of_size(&self, size: usize, excluded_player: usize) -> Vec<Vec<bool>> {
let mut coalitions = Vec::new();
let available_players: Vec<usize> = (0..self.num_players)
.filter(|&i| i != excluded_player)
.collect();
if size <= available_players.len() {
for combination in available_players.iter().combinations(size) {
let mut coalition = vec![false; self.num_players];
for &player in combination {
coalition[*player] = true;
}
coalitions.push(coalition);
}
}
coalitions
}
/// Get coalition value from characteristic function.
fn get_coalition_value(&self, coalition: &[bool]) -> f64 {
*self.characteristic_function.get(coalition).unwrap_or(&0.0)
}
/// Calculate factorial.
fn factorial(&self, n: usize) -> f64 {
(1..=n).map(|i| i as f64).product()
}
}
/// Supporting data structures.
#[derive(Debug, Clone)]
pub struct AuctionComparison {
pub first_price: f64,
pub second_price: f64,
pub english: f64,
pub dutch: f64,
}
Practical Applications
Market Competition Analysis
use crate::analytics::prescriptive::game_theory::{StrategicGame};
/// Analyze pricing competition between firms.
pub fn analyze_pricing_competition() {
// Duopoly pricing game: High Price vs Low Price strategies
let strategies = vec![
vec!["High".to_string(), "Low".to_string()], // Firm 1
vec!["High".to_string(), "Low".to_string()], // Firm 2
];
// Payoff matrices: (Firm1 profits, Firm2 profits)
// Firm 1's payoffs when both choose: (High,High), (High,Low), (Low,High), (Low,Low)
let firm1_payoffs = DMatrix::from_row_slice(2, 2, &[
10.0, 2.0, // If Firm 1 chooses High: vs (High, Low)
15.0, 5.0, // If Firm 1 chooses Low: vs (High, Low)
]);
let firm2_payoffs = DMatrix::from_row_slice(2, 2, &[
10.0, 15.0, // If Firm 2 chooses High: vs (High, Low)
2.0, 5.0, // If Firm 2 chooses Low: vs (High, Low)
]);
let game = StrategicGame::new(
strategies,
vec![firm1_payoffs, firm2_payoffs],
);
println!("Pricing Competition Analysis:");
println!("Pure Strategy Nash Equilibria:");
let equilibria = game.find_pure_nash_equilibria();
for (i, equilibrium) in equilibria.iter().enumerate() {
println!(" Equilibrium {}: Firm 1: {}, Firm 2: {}",
i + 1,
if equilibrium[0] == 0 { "High" } else { "Low" },
if equilibrium[1] == 0 { "High" } else { "Low" });
}
// Check for mixed strategy equilibrium
if let Some((p1_mixed, p2_mixed)) = game.mixed_nash_equilibrium_2p() {
println!("\nMixed Strategy Nash Equilibrium:");
println!(" Firm 1: High={:.3}, Low={:.3}", p1_mixed[0], p1_mixed[1]);
println!(" Firm 2: High={:.3}, Low={:.3}", p2_mixed[0], p2_mixed[1]);
}
}
Evolutionary Dynamics in Technology Adoption
/// Model technology adoption using evolutionary game theory.
pub fn technology_adoption_dynamics() {
// Two technologies competing for market share
let initial_proportions = DVector::from_vec(vec![0.3, 0.7]); // Tech A: 30%, Tech B: 70%
// Network effects payoff matrix
let payoff_matrix = DMatrix::from_row_slice(2, 2, &[
5.0, 1.0, // Tech A payoffs: vs (A, B) adoption
2.0, 4.0, // Tech B payoffs: vs (A, B) adoption
]);
let mut simulator = EvolutionaryGameSimulator::new(
initial_proportions,
payoff_matrix,
1000, // Population size
0.01, // Mutation rate
);
println!("Technology Adoption Dynamics:");
println!("Initial state: Tech A: {:.1}%, Tech B: {:.1}%",
simulator.strategy_proportions[0] * 100.0,
simulator.strategy_proportions[1] * 100.0);
// Run evolutionary dynamics
let history = simulator.run_replicator_dynamics(100, 0.1);
println!("Final state: Tech A: {:.1}%, Tech B: {:.1}%",
simulator.strategy_proportions[0] * 100.0,
simulator.strategy_proportions[1] * 100.0);
// Analyze convergence
let last_state = history.last().unwrap();
let final_state = &simulator.strategy_proportions;
let convergence = (final_state - last_state).norm();
println!("Convergence metric: {:.6}", convergence);
// Check for evolutionarily stable strategies
let ess = simulator.find_ess();
println!("Evolutionarily Stable Strategies: {:?}", ess);
}
Supply Chain Coordination
/// Analyze supply chain coordination using cooperative game theory.
pub fn supply_chain_coordination() {
let mut analyzer = CooperativeGameAnalyzer::new(3); // Supplier, Manufacturer, Retailer
// Define coalition values (total profit)
analyzer.set_coalition_value(vec![false, false, false], 0.0); // Empty coalition
analyzer.set_coalition_value(vec![true, false, false], 10.0); // Supplier alone
analyzer.set_coalition_value(vec![false, true, false], 15.0); // Manufacturer alone
analyzer.set_coalition_value(vec![false, false, true], 20.0); // Retailer alone
analyzer.set_coalition_value(vec![true, true, false], 40.0); // Supplier + Manufacturer
analyzer.set_coalition_value(vec![true, false, true], 45.0); // Supplier + Retailer
analyzer.set_coalition_value(vec![false, true, true], 50.0); // Manufacturer + Retailer
analyzer.set_coalition_value(vec![true, true, true], 80.0); // Grand coalition
let shapley_values = analyzer.calculate_shapley_values();
println!("Supply Chain Profit Allocation (Shapley Values):");
println!(" Supplier: {:.2}", shapley_values[0]);
println!(" Manufacturer: {:.2}", shapley_values[1]);
println!(" Retailer: {:.2}", shapley_values[2]);
println!(" Total: {:.2}", shapley_values.sum());
// Verify efficiency and individual rationality
let grand_coalition_value = 80.0;
let individual_values = vec![10.0, 15.0, 20.0];
println!("\nCoalition Properties:");
println!(" Efficiency: {} (Shapley sum = Grand coalition value)",
(shapley_values.sum() - grand_coalition_value).abs() < 1e-6);
for (i, &individual_value) in individual_values.iter().enumerate() {
println!(" Individual Rationality {}: {} (Shapley ≥ Individual)",
i + 1, shapley_values[i] >= individual_value);
}
}
Auction Strategy Optimization
/// Optimize bidding strategies in different auction formats.
pub fn auction_strategy_optimization() {
let analyzer = AuctionAnalyzer::new(
5, // 5 bidders
vec![(0.0, 100.0); 5], // Uniform valuations [0, 100] for all bidders
);
println!("Auction Strategy Analysis:");
// Analyze optimal bidding for different valuations
let test_valuations = vec![20.0, 40.0, 60.0, 80.0, 100.0];
println!("\nOptimal First-Price Sealed-Bid Auction Bids:");
println!("{:<10} {:<15} {:<15}", "Valuation", "Optimal Bid", "Bid/Value Ratio");
println!("{}", "-".repeat(40));
for valuation in test_valuations {
let optimal_bid = analyzer.first_price_optimal_bid(0, valuation);
let ratio = optimal_bid / valuation;
println!("{:<10.0} {:<15.2} {:<15.3}", valuation, optimal_bid, ratio);
}
// Compare auction format revenues
let revenue_comparison = analyzer.compare_auction_revenues();
println!("\nExpected Revenue Comparison:");
println!(" First-Price: {:.3}", revenue_comparison.first_price);
println!(" Second-Price: {:.3}", revenue_comparison.second_price);
println!(" English: {:.3}", revenue_comparison.english);
println!(" Dutch: {:.3}", revenue_comparison.dutch);
println!("\nRevenue Equivalence: All formats yield same expected revenue");
}
Strategic Applications
Network Security Games
/// Model cybersecurity investment decisions.
pub fn cybersecurity_investment_game() {
// Two firms deciding on security investment levels
let strategies = vec![
vec!["Low".to_string(), "High".to_string()], // Firm 1 security investment
vec!["Low".to_string(), "High".to_string()], // Firm 2 security investment
];
// Payoffs considering security benefits and investment costs
// Higher security reduces breach probability but increases costs
let firm1_payoffs = DMatrix::from_row_slice(2, 2, &[
5.0, 8.0, // Low investment: benefits from other's security
2.0, 6.0, // High investment: costly but more secure
]);
let firm2_payoffs = DMatrix::from_row_slice(2, 2, &[
5.0, 2.0, // Symmetric payoffs
8.0, 6.0,
]);
let game = StrategicGame::new(
strategies,
vec![firm1_payoffs, firm2_payoffs],
);
let equilibria = game.find_pure_nash_equilibria();
println!("Cybersecurity Investment Game:");
for equilibrium in equilibria {
let firm1_strategy = if equilibrium[0] == 0 { "Low" } else { "High" };
let firm2_strategy = if equilibrium[1] == 0 { "Low" } else { "High" };
println!(" Equilibrium: ({}, {})", firm1_strategy, firm2_strategy);
}
println!("\nAnalysis: Free-riding problem in cybersecurity investment");
}
Resource Allocation Games
/// Model resource competition using congestion games.
pub fn resource_allocation_analysis() {
// Simplified congestion game: users choosing between two resources
let initial_distribution = DVector::from_vec(vec![0.6, 0.4]); // 60% on Resource 1
// Cost increases with congestion
let cost_matrix = DMatrix::from_row_slice(2, 2, &[
1.0, 2.0, // Resource 1 costs: vs (low, high) usage
2.0, 1.0, // Resource 2 costs: vs (low, high) usage
]);
// Convert costs to payoffs (negative costs)
let payoff_matrix = -cost_matrix;
let mut simulator = EvolutionaryGameSimulator::new(
initial_distribution,
payoff_matrix,
1000,
0.005, // Low mutation rate
);
println!("Resource Allocation Dynamics:");
println!("Initial: Resource 1: {:.1}%, Resource 2: {:.1}%",
simulator.strategy_proportions[0] * 100.0,
simulator.strategy_proportions[1] * 100.0);
let _history = simulator.run_replicator_dynamics(200, 0.05);
println!("Equilibrium: Resource 1: {:.1}%, Resource 2: {:.1}%",
simulator.strategy_proportions[0] * 100.0,
simulator.strategy_proportions[1] * 100.0);
// Analyze efficiency loss (Price of Anarchy)
let social_optimum_usage = 0.5; // Balanced usage minimizes total cost
let actual_usage = simulator.strategy_proportions[0];
let efficiency_loss = (actual_usage - social_optimum_usage).abs();
println!("Efficiency loss from Nash equilibrium: {:.3}", efficiency_loss);
}
Advanced Concepts
Mechanism Design
/// Vickrey-Clarke-Groves (VCG) auction implementation.
pub struct VCGAuction {
num_items: usize,
bidder_valuations: Vec<DVector<f64>>,
}
impl VCGAuction {
pub fn new(bidder_valuations: Vec<DVector<f64>>) -> Self {
let num_items = if !bidder_valuations.is_empty() {
bidder_valuations[0].len()
} else {
0
};
Self {
num_items,
bidder_valuations,
}
}
/// Determine optimal allocation and VCG payments.
pub fn run_auction(&self) -> (Vec<Vec<bool>>, Vec<f64>) {
let num_bidders = self.bidder_valuations.len();
// Find welfare-maximizing allocation
let allocation = self.find_optimal_allocation();
// Calculate VCG payments
let mut payments = vec![0.0; num_bidders];
for bidder in 0..num_bidders {
// Social welfare without this bidder
let welfare_without = self.max_welfare_excluding_bidder(bidder);
// Other bidders' welfare in the chosen allocation
let others_welfare = self.calculate_others_welfare(&allocation, bidder);
payments[bidder] = welfare_without - others_welfare;
}
(allocation, payments)
}
/// Find allocation that maximizes social welfare.
fn find_optimal_allocation(&self) -> Vec<Vec<bool>> {
// Simplified: assume single-item auction
let num_bidders = self.bidder_valuations.len();
let mut allocation = vec![vec![false; self.num_items]; num_bidders];
for item in 0..self.num_items {
let mut best_bidder = 0;
let mut best_value = self.bidder_valuations[0][item];
for bidder in 1..num_bidders {
if self.bidder_valuations[bidder][item] > best_value {
best_value = self.bidder_valuations[bidder][item];
best_bidder = bidder;
}
}
allocation[best_bidder][item] = true;
}
allocation
}
/// Calculate maximum welfare excluding specific bidder.
fn max_welfare_excluding_bidder(&self, excluded_bidder: usize) -> f64 {
let mut total_welfare = 0.0;
for item in 0..self.num_items {
let mut best_value = 0.0;
for bidder in 0..self.bidder_valuations.len() {
if bidder != excluded_bidder {
best_value = best_value.max(self.bidder_valuations[bidder][item]);
}
}
total_welfare += best_value;
}
total_welfare
}
/// Calculate welfare of other bidders given allocation.
fn calculate_others_welfare(&self, allocation: &[Vec<bool>], excluded_bidder: usize) -> f64 {
let mut others_welfare = 0.0;
for bidder in 0..self.bidder_valuations.len() {
if bidder != excluded_bidder {
for item in 0..self.num_items {
if allocation[bidder][item] {
others_welfare += self.bidder_valuations[bidder][item];
}
}
}
}
others_welfare
}
}
Game theory provides essential frameworks for analyzing strategic interactions in competitive business environments, enabling optimal decision-making in scenarios ranging from pricing competition to resource allocation and cooperative partnerships.