Home

Welcome to bnelearn’s documentation! bnelearn is a framework for equilibrium learning in sealed-bid auctions and other markets that can be modeled as Bayesian Games.

This is a work in progress, so the documentation is still incomplete, and may even be outdated or specific to our local deployments in some places. We’ll be working to bring the documentation up to paar in the near future. If you need additional help in the meantime, please get in touch with one of the maintainers.

The public version of the bnelearn repository is hosted at https://github.com/heidekrueger/bnelearn. Development is ongoing via a private GitLab repository on our university server. If you have questions, find an error, or want to contribute, please get in touch via the Issues on the GitHub repository above, or email one of the maintainers.

Installation and Reproduction Instructions

These are minimal instructions to install dependencies and run the scripts to reproduce the results presented in our paper.

Prerequesites

Current parameter settings assume that you are running on a Unix system with a cuda-enabled Nvidia GPU with at least 11GB GPU-RAM, and that the root directory (containing this readme file) is located at ~/bnelearn. On a system without a GPU (but at least 11GB of available RAM), everything should work, but you will experience significantly longer runtimes. On systems with less GPU-RAM, standard configurations may fail, in that case try adjusting the batch_size and eval_batch_size parameters in the run-scripts (and possibly the tests). Everything should likewise run on Windows, but you may need to change the output directories manually.

Installation

bnelearn mainly runs on top of pytorch and python. The repository was extensively tested with python 3.9 and pytorch 1.10 on a Ubuntu system. The package should be cross-platform compatible, but we can make no guarantees. (A limited feature set has been tested on Windows 11.)

Installation instructions for Ubuntu using conda:

  1. Install Python (tested on 3.9) and pip, we recommend using a separate environment using conda or virtualenv. Assuming you have a running installation of conda, make a new environment: `conda create -n bnelearn-test python=3.9 pip` Then activate your environment via `conda activate bnelearn`

  2. Optional – you can skip directly to step 3, but this will install the package with a reduced feature set (e.g. no GPU support, no commercial solvers, no development extras.) Make sure you are using the correct version of pip ()`which pip` should point to your new conda environment!) and install the remaining requirements via pip install -r requirements.txt. This will install all requirements, including GPU-enabled pytorch, external solvers required for some combinatorial auctions and development tools. Note that requirements.txt will pull the latest stable torch version with cuda that is available at the time of writing (July 2021). You may want to manually install the latest version available for your system, see https://pytorch.org/get-started/locally/ for details.

  3. Install the bnelearn package via pip install -e ..

  4. Test your installation via pytest. If all tests pass, everything was successfull. You may also see ``SKIP``s or ``XFAIL``s: In this case, the, installation seems to work, but the tests have determined that you are missing some optional requirements for advanced features, or that your system does not support cuda. In this case, not all features may be available to you.

The framework conceptually consists of the following

  • A python package bnelearn in the ./bnelearn subdirectory.

  • Some User-code scripts in ./scripts.

  • Jupyter notebooks in the ./notebooks directory that trigger experiments and log results to subdirectories (or other places) in tensorboard format.

  • The R subdirectory contains scripts for parsing tensorboard logs into R dataframes, in order to create pretty figures. Some of this functionality uses r-tensorflow, see source code for installation instructions.

Running the software

  • Navigate to your local bnelearn folder (in the following: .).

  • Activate the bnelearn conda-env: conda activate bnelearn.

  • Execute one of the scripts in the scripts directory, or run a jupyter lab instance to run of the notebooks in the notebooks directory.

Experiment logging

On the fly logging: Results of script and notebook experiments are written to a subdirectory as specified in each script or notebook. To view the results or monitor training process, start a tensorboard instance:

  • Navigate to your experiment output directory.

  • In another terminal window, activate the bnelearn conda env as well: activate bnelearn.

  • Start a tensorboard instance, pointing at the relevant subdirectory for your experiment (tensorboard can simultaneously display multiple runs of the same experiment.) I.e. if you’re interested in fpsb experiments and your directory structure is

    ./
    |
    *---* notebooks/
        |
        *---* fpsb/
            |
            *--- run1/
            *--- run2/
    

This folder structure should be used for work in progress. Then start tensorboard using

tensorboard --logdir fpsb [--port 6006]

The standard port is 6006, but each user should use their own port to enable different sessions. The tensorboard server is then accessible at http://localhost:6006.

Quickstart

Let us take a look at how to learn in one of the predefined auction games with one of the predefined algorithms.

The commands below can be used to reproduce the results published in (Bichler et al., 2021). All references refer to the numbering in that paper.

(Note: as of December 2022, another paper based on bnelearn is forthcoming in the INFORMS Journal of computing. Reproduction instruction for that paper will be hosted in a separate repository published by INFORMS.)

Reproduction Instructions for Bichler et al. (2021)

You can then run the experiments underlying the tables and figures in the main paper via python run_experiments_npga.py (see run_experiments_npga.py). The standard configuration of the file reruns the experiments behind Figure 3, i.e., one run each for all combinations of the correlation strength and the risk parameter. To run the other experiments reported in the paper, make the following changes in lines 17 to 34:

  • For the experiments underlying Figure 2, set n_runs = 10, gammas = [0.5], payment_rules = ['nearest_vcg'].

  • For the experiments underlying Table 1, set n_runs = 10, risks = [1.0], gammas = [0.5], payment_rules = ['vcg', 'nearest_bid', 'nearest_zero', 'nearest_vcg', 'first_price'].

To run the other experiments reported in the Supplementary Information, make the following changes:

  • For the experiments underlying Table S.1, set n_runs = 10, risks = [1.0] or [0.5], gammas = [0.0], payment_rules = ['first_price'], corr_models = ['independent'], experiment_type = 'single_item_uniform_symmetric' or 'single_item_gaussian_symmetric' and additionally supply the corresponding number of bidders via the n_players parameter to the set_setting() call.

  • For the experiments underlying Figure S.1, set n_runs = 10, risks = [1.0], gammas = [0.0], payment_rules = ['first_price'], corr_models = ['independent'], experiment_type = 'single_item_gaussian_symmetric and additionally supply the number of bidders via n_players = 10 within the set_setting() call.

  • For the experiments underlying Table S.2, set n_runs = 10, risks = [1.0], gammas = [None] (fallback to default), payment_rules = ['first_price'] for the Affiliated values setting and 'second_price' for the Common value settings, corr_models = [None] (fallback to default), experiment_type = 'affiliated_observations' or 'mineral_rights' and additionally supply the corresponding number of bidders via the n_players parameter to the set_setting() call.

  • For the experiments underlying Table S.3, set n_runs = 10, risks = [1.0], gammas = [0.0], payment_rules = ['first_price', 'uniform', 'vcg'], corr_models = ['independent'], experiment_type = 'multiunit' and additionally supply the corresponding number of bidders via the n_players parameter and the number of units via the n_units parameter to the set_setting() call.

  • For the experiments underlying Figure S.2, make the corresponding changes to the previous experiments.

  • For the experiments underlying Figure S.3, make the corresponding changes to the previous experiments and set corr_models = ['additive'].

  • For the experiments underlying Figure S.2, make the corresponding changes to the previous experiments.

Logs will be written into the experiments subdirectory. While the experiments are running, you can examine the training progress via tensorboard --logdir experiments.

Running Experiments for Learning with PSO

You can then run the experiments for particle swarm optimization (from Kohring et al., 2022) via python run_experiments_pso.py (see run_experiments_pso.py).

Running Experiments for Learning in Contests

You can then run the experiments for particle swarm optimization via python run_experiments_contests.py (see run_experiments_contests.py).

Auction Theory and Equilibrium Computation

1. Background

The computation and analysis of equilibrium states in strategic settings is of utmost importance in the economic sciences. However, equilibria in many markets remain poorly understood. The computational complexity of finding Nash equilibria is known to be PPAD complete even for finite normal form games (NFG), a class that is considered to be hard unless P = NP (Daskalakis et al. 2009). Despite these hardness results for the worst case, equilibrium computation has become tenable for NFGs of moderate sizes in recent years. Auction markets are of a particular interest to economists and policymakers, as a precise understanding of strategic behavior in proposed auction markets would be invaluable in the design and implementation market mechanisms with certain desiderata. However, the game theoretic properties of auctions are even less amiable to equilibrium computation: Auctions are commonly modeled as Bayesian games with continuous type and action spaces (Harsanyi 1968), resulting in an infinite-dimensional, functional space of possible strategies. Such games are no longer finite, so even Nash’s famous theorem about the existence of equilibria (Nash 1950) no longer holds, and the complexity of finding Bayesian Nash equilibria in auctions may be NP-hard or worse depending on the specifics of the game. In fact, Cai and Papadimitriou (2014) show that in certain combinatorial auctions, the computation of Bayesian Nash (BNE) is at least PP-hard (a complexity class above the polynomial hierarchy), and even certifying or approximating a BNE at a constant approximation bound remains NP-hard. The current understanding of strategic behavior in the field of auction theory therefore relies mainly on equilibria that have been analytically derived. Unfortunately, such results are scarce and elusive for all but a few simple settings.

Most recently, however, there have been a range of first empirical successes in approximating Bayesian Nash equilibria in sealed-bid auctions using computational black-box methods that do not rely on manual mathematical analysis of specific settings (Heymann and Mertikopoulos 2021, Bichler et al. 2021, Bosshard et al. 2020, Li and Wellman 2020) This suggests that the established hardness results may not apply to a wide range of auctions that are of practical interest and that it may be possible to characterize subclasses of continuous Bayesian games for which equilibrium computation may be feasible.

However, the literature on auctions is vast, with many variants of markets that are of interest. This has been a limiting factor for research in equilibrium computation, as each individual study has only been able to investigate new methods in a small number of relevant auction settings due to implementation complexity. Existing equilibrium learning methods rely on simulating very large numbers of auctions, which has required computational optimizations that have often been hand tailored to specific classes of auctions or even the specific setting at hand.

To facilitate future research in equilibrium computation in auctions, we propose consolidating a wide set of auction settings into a single benchmark suite with a common, modular, extensible and performant programming interface. To this end, we present our open-source package bnelearn, which provides a GPU-accelerated framework for equilibrium computation in sealed-bid auctions and related (Bayesian and complete-information) games. Using bnelearn, researchers working on novel equilibrium learning rules will have access to a wide selection of implemented auction settings with or without existing equilibria as well as to an ecosystem of metrics and tools that facilitate analysis. To the authors’ knowledge, bnelearn comprises the largest and most complete suite of implementations of sealed-bid auctions and their known equilibria, collecting

In addition to researchers in equilibrium computation, we expect that such a framework will also be useful to practitioners of auction theory in the economic sciences: Given the fact that existing approaches have been empirically demonstrated to converge to approximate equilibria in a wide range of auction settings, and (approximate) error bounds can be calculated for candidate solutions, bnelearn enables analyses of strategic behavior in markets that elude analytical equilibrium analysis. As an example, in (Bichler et al. 2021), we were empirically able to quantify the effects of correlation between bidders on revenue and economic efficiency in equilibrium of small combinatorial auctions with core-selecting payment rules.

2. Problem Statement

2.1 Model of an Auction Game

We consider sealed-bid auctions as special cases of Bayesian games. In such games, an auctioneer aims to sell \(m\) goods to \(n\) competing buyers. These buyers each submit bids based on their private information. Based on these bids, the auctioneer then uses an auction mechanism to allocate the goods to the buyers and determine what prices to charge the winners. The most general case of such an auction game can be formalized as the tuple \(G = (n, m, \mathcal{V}, \mathcal{O}, F, \mathcal{A}, x, p, u)\), where

  • \(n\) is the number of participating bidders or agents. We denote the set of bidders by \(\mathcal{I} = \lbrace 1, \dots, n\rbrace\) and use the letter \(i\) to index it.

  • \(m\) is the number of goods to be sold. When goods are heterogenous, we further denote by \(\mathcal{K} = 2^{[m]}\) the set of bundles of goods, and index it by \(k\). When goods are homogenous, we instead use \(\mathcal{K} = {[m]} \cup \{0\}\) to describe the possible cardinalities of subsets of the goods.

  • \(\mathcal{V} = \mathcal{V}_1 \times \dots \times \mathcal{V}_n\) describes the set of possible valuations of the bidders: Each bidder \(i\) may be potentially interested in a subset \(\mathcal{K}_i \subseteq \mathcal{K}\) of the possible bundles. Writing \(K_i = \left\lvert \mathcal{K}_i \right\rvert\) for it’s cardinality, \(\mathcal{V}_i \subseteq \mathbb{R}^{K_i}_{+}\) then is the set of possible valuation vectors for agent \(i\). For example, in an auction of two heterogenous items \(\{a, b\}\), we might have \(\mathcal{V}_i = \mathbb{R}^4_+\) and a vector \(v_i = (0, 1, 2, 5)\) would indicate agent \(i\)’s valuations for winning the empty bundle, only item \(a\), only item \(b\), or both items, respectively. Note that in some cases, bidders may not directly observe their true valuations \(v_i\), but may only have access to partial information about them:

  • \(\mathcal{O} = \mathcal{O}_1 \times \dots \times \mathcal{O}_n\) describes the set of possible signals or observations of private information that the bidders have access to. In the private values model, where bidders have full information about their valuations, we have \(o_i = v_i\).

  • \(F\) is the cumulative density function of the joint prior distribution over bidders’ types, given by tuples \((o_i, v_i)\) of observations and valuations: \(F: \mathcal V \times \mathcal O \rightarrow [0, 1]\). It’s probability density function will be denoted by \(f\) and we state no further assumptions on the prior, thus, allowing for arbitrary correlations. Its marginals are denoted by \(f_v\), \(f_{o_i}\), etc. and its conditionals by \(f_{v_i\vert o_i}\).

  • \(\mathcal{A} = \mathcal{A}_1 \times \dots \times \mathcal{A}_n = \mathbb{R}^n_{\geq 0}\) are the available actions or bids to the bidders. These must be decided on based on the strategy \(\beta_i: \mathcal{O}_i \rightarrow \mathcal{A}_i\) with the information they have available, namely their observations \(o_i\).

  • \(x = (x_1, \dots, x_n) \in \{0, 1\}^{|\mathcal K|}\) and \(p = (p_1, \dots, p_n) \in \mathbb{R}^n\) describe the allocations and the payments that are determined by the mechanism after bids \(b \in \mathcal{A}\) have been reported. An allocation constitutes a partition of the \(m\) items, where bidder \(i\) is allocated the bundle \(x_i\). In the simplest case, the allocations would be chosen such that the seller revenue (the sum of all bidders’ payments) is maximized when bidders pay what they report. This is known as the first-price sealed bid auction.

  • \(u = (u_1, \dots, u_n)\) then is the utility vector of the bidders, where bidder \(i\)’s utility \(u_i(v_i, b)\) depends on their own valuation but all bidders’ actions. Assuming the other bidders follow \(\beta\), bidder \(i\)’s interim utility is then defined as the expected utility of choosing a bid \(b_i\) conditioned on their observation \(o_i\):

    \[\overline{u}_i(o,b_i,\beta_{-i}) = \mathbb{E}_{v_i,o_{-i}|o_i}\left[u_i(v_i, b_i,\beta_{-i}(o_{-i}))\right].\]

    Accordingly, the interim utility loss \(\overline \ell\) that is incurred by not playing a best response is:

    \[\overline \ell (o; b_i, \beta_{-i}) = \sup_{b'_i \in \mathcal A_i} \overline u_i(o_i, b'_i, \beta_{-i}) -\overline u_i(o_i, b_i, \beta_{-i}).\]

Furthermore, the ex-ante utility is defined as \(\tilde{u}_i(\beta_i,\beta_{-i})=\mathbb{E}_{o_i \sim f_{o_i}} [\overline{u}_i(o_i, \beta_{i}(o_i), \beta_{-i})]\), and the ex-ante loss \(\tilde \ell_i(\beta_i, \beta_{-i})\).

The question to be answered now is: “What is the optimal strategy profile for the bidders?” The most common the solution concept for this question is the so-called Bayes-Nash equilibrium: An (interim) \(\epsilon\)-Bayes-Nash equilibrium (\(\epsilon\)-BNE) is a strategy profile \(\beta^* = (\beta^*_1, \dots, \beta^*_n)\) such that no agent can improve their own utility by more than \(\epsilon \geq 0\) by unilaterally deviating from \(\beta^*\):

\[\forall\ i\in\mathcal I, o_i \in \mathcal O_i: \quad \overline{\ell}_i\left(o_i; \beta^*_i(o_i), \beta^*_{-i}\right) \leq \epsilon.\]

For \(\epsilon = 0\), the BNE is called exact, or the \(\epsilon\)-prefix is simply dropped. The ex-ante \(\epsilon\)-BNE is defined analogously.

bnelearn

bnelearn package

Subpackages

bnelearn.experiment package
Submodules
bnelearn.experiment.combinatorial_experiment module

This module implements combinatorial experiments. Currently, this is only Local Global experiments as considered by Bosshard et al. (2018).

Limitations and comments:
  • Currently implemented for only uniform valuations

  • Strictly speaking Split Award might belong here (however, implementation closer to multi-unit)

class bnelearn.experiment.combinatorial_experiment.LLGExperiment(config: ExperimentConfig)[source]

Bases: LocalGlobalExperiment

A combinatorial experiment with 2 local and 1 global bidder and 2 items; but each bidders bids on 1 bundle only. Local bidder 1 bids only on the first item, the second only on the second and global only on both. Ausubel and Baranov (2018) provide closed form solutions for the 3 core selecting rules.

Supports arbitrary number of local bidders, not just two.

action_size: int
bne_env: AuctionEnvironment
bne_utilities: Tensor
epoch: int
input_length: int
mechanism: Mechanism
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
valuation_size: int
class bnelearn.experiment.combinatorial_experiment.LLGFullExperiment(config: ExperimentConfig)[source]

Bases: LocalGlobalExperiment

A combinatorial experiment with 2 local and 1 global bidder and 2 items.

Essentially, this is a general CA with 3 bidders and 2 items.

Each bidder bids on all bundles. Local bidder 1 has only a value for the first item, the second only for the second and global only on both. This experiment is therefore more general than the LLGExperiment and includes the specific payment rule from Beck & Ott, where the 2nd local bidder is favored (pays VCG prices).

action_size: int
bne_env: AuctionEnvironment
bne_utilities: Tensor
epoch: int
input_length: int
mechanism: Mechanism
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
pretrain_transform(player_position: int) callable[source]

Transformation during pretraining: Bidders are single-minded in this setting.

valuation_size: int
class bnelearn.experiment.combinatorial_experiment.LLLLGGExperiment(config: ExperimentConfig)[source]

Bases: LocalGlobalExperiment

A combinatorial experiment with 4 local and 2 global bidder and 6 items; but each bidders bids on 2 bundles only.

Local bidder 1 bids on the bundles {(item_1,item_2),(item_2,item_3)} Local bidder 2 bids on the bundles {(item_3,item_4),(item_4,item_5)} … Gloabl bidder 1 bids on the bundles {(item_1,item_2,item_3,item_4), (item_5,item_6,item_7,item_8)} Gloabl bidder 1 bids on the bundles {(item_3,item_4,item_5,item_6), (item_1,item_2,item_7,item_8)}

No BNE are known (but VCG). Bosshard et al. (2018) consider this setting with nearest-vcg and first-price payments.

TODO:
  • Implement eval_env for VCG

action_size: int
bne_env: AuctionEnvironment
bne_utilities: Tensor
epoch: int
input_length: int
mechanism: Mechanism
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
valuation_size: int
class bnelearn.experiment.combinatorial_experiment.LLLLRRGExperiment(config: ExperimentConfig)[source]

Bases: Experiment

Experiment in an extension of the Local-Global Model with three groups of bidders.

action_size: int
bne_env: AuctionEnvironment
bne_utilities: Tensor
epoch: int
input_length: int
mechanism: Mechanism
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
valuation_size: int
class bnelearn.experiment.combinatorial_experiment.LocalGlobalExperiment(config: ExperimentConfig, n_players, n_local, valuation_size, observation_size, action_size)[source]

Bases: Experiment, ABC

This class represents Local Global experiments in general as considered by Bosshard et al. (2018). It serves only to provide common logic and parameters for LLG and LLLLGG.

action_size: int
bne_env: AuctionEnvironment
bne_utilities: Tensor
epoch: int
input_length: int
mechanism: Mechanism
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
valuation_size: int
bnelearn.experiment.configuration_manager module
class bnelearn.experiment.configuration_manager.ConfigurationManager(experiment_type: str, n_runs: int, n_epochs: int, seeds: Optional[Iterable[int]] = None)[source]

Bases: object

The class provides a ‘front-end’ for the whole package. It allows for creation of a full and consistent ExperimentConfiguration, as defined by the ExperimentConfig dataclass. It manages all the defaults, including those specific for each experiment type, auto-inits the parameters that are not supposed to be initialized manually, and allows to selectively change any part of the configuration, while also performing a parameter and consistency check before creating the final configuration object.

The workflow with the class API is as follows:

  1. Init class object with the experiment type string, n_runs and n_epochs. For possible experiment types see ConfigurationManager.experiment_types

    1. __init__ calls get_default_config_members method to get default configuration members.

    2. Based on the experiment type, __init__ calls the appropriate ancillary _init_experiment_type. It sets the default parameters specific for the given experiment type.

  2. (Optional step) Call set_config_member methods (e.g. set_setting) in a chain style, each methods allows to selectively set any parameter of a corresponding config member to a new arbitrary value, while leaving all the parameters not specified by the user intact - with their default values.

  3. Call the get_config method to get a ready configuration object and an experiment class corresponding to the experiment type (the latter needed for an easy instantiation of the Experiment)

    1. get_config calls _post_init, which inits the parameters which shouldn’t be set manually, checks for consistency between the related parameters and validates whether each parameter is in an appropriate value range. Then, it calls the type specific _post_init_experiment_type method which performs all the same things, but specific for the experiment type.

    2. get_config creates and returns the final and valid configuration object alongside the experiment class.

Example of class usage:

experiment_config, experiment_class = \
    ConfigurationManager(
        experiment_type='multiunit', n_runs=1, n_epochs=20
    ) \
    .set_logging(log_root_dir=log_root_dir) \
    .set_setting(payment_rule='discriminatory') \
    .set_learning(model_sharing=False) \
    .set_hardware() \
    .get_config()

experiment_class(experiment_config).run()
static compare_two_experiment_configs(conf1: ExperimentConfig, conf2: ExperimentConfig) bool[source]

Checks whether two given configurations are identical (deep comparison)

static experiment_config_could_be_saved_properly(exp_config: ExperimentConfig) bool[source]

Tests whether the given config could be serialized and deserialized properly.

experiment_types = {'affiliated_observations': (<class 'bnelearn.experiment.single_item_experiment.AffiliatedObservationsExperiment'>, <function ConfigurationManager._init_affiliated_observations>, <function ConfigurationManager._post_init_affiliated_observations>), 'all_pay_uniform_symmetric': (<class 'bnelearn.experiment.single_item_experiment.UniformSymmetricPriorSingleItemExperiment'>, <function ConfigurationManager._init_single_item_uniform_symmetric>, <function ConfigurationManager._post_init_single_item_uniform_symmetric>), 'crowdsourcing': (<class 'bnelearn.experiment.single_item_experiment.ContestExperiment'>, <function ConfigurationManager._init_crowdsourcing>, <function ConfigurationManager._post_init_crowdsourcing>), 'llg': (<class 'bnelearn.experiment.combinatorial_experiment.LLGExperiment'>, <function ConfigurationManager._init_llg>, <function ConfigurationManager._post_init_llg>), 'llg_full': (<class 'bnelearn.experiment.combinatorial_experiment.LLGFullExperiment'>, <function ConfigurationManager._init_llg_full>, <function ConfigurationManager._post_init_llg_full>), 'llllgg': (<class 'bnelearn.experiment.combinatorial_experiment.LLLLGGExperiment'>, <function ConfigurationManager._init_llllgg>, <function ConfigurationManager._post_init_llllgg>), 'llllrrg': (<class 'bnelearn.experiment.combinatorial_experiment.LLLLRRGExperiment'>, <function ConfigurationManager._init_llllrrg>, <function ConfigurationManager._post_init_llllrrg>), 'mineral_rights': (<class 'bnelearn.experiment.single_item_experiment.MineralRightsExperiment'>, <function ConfigurationManager._init_mineral_rights>, <function ConfigurationManager._post_init_mineral_rights>), 'multiunit': (<class 'bnelearn.experiment.multi_unit_experiment.MultiUnitExperiment'>, <function ConfigurationManager._init_multiunit>, <function ConfigurationManager._post_init_multiunit>), 'single_item_asymmetric_beta': (<class 'bnelearn.experiment.single_item_experiment.TwoPlayerAsymmetricBetaPriorSingleItemExperiment'>, <function ConfigurationManager._init_single_item_asymmetric_beta>, <function ConfigurationManager._post_init_single_item_asymmetric_beta>), 'single_item_asymmetric_uniform_disjunct': (<class 'bnelearn.experiment.single_item_experiment.TwoPlayerAsymmetricUniformPriorSingleItemExperiment'>, <function ConfigurationManager._init_single_item_asymmetric_uniform_disjunct>, <function ConfigurationManager._post_init_single_item_asymmetric_uniform_disjunct>), 'single_item_asymmetric_uniform_overlapping': (<class 'bnelearn.experiment.single_item_experiment.TwoPlayerAsymmetricUniformPriorSingleItemExperiment'>, <function ConfigurationManager._init_single_item_asymmetric_uniform_overlapping>, <function ConfigurationManager._post_init_single_item_asymmetric_uniform_overlapping>), 'single_item_gaussian_symmetric': (<class 'bnelearn.experiment.single_item_experiment.GaussianSymmetricPriorSingleItemExperiment'>, <function ConfigurationManager._init_single_item_gaussian_symmetric>, <function ConfigurationManager._post_init_single_item_gaussian_symmetric>), 'single_item_uniform_symmetric': (<class 'bnelearn.experiment.single_item_experiment.UniformSymmetricPriorSingleItemExperiment'>, <function ConfigurationManager._init_single_item_uniform_symmetric>, <function ConfigurationManager._post_init_single_item_uniform_symmetric>), 'splitaward': (<class 'bnelearn.experiment.multi_unit_experiment.SplitAwardExperiment'>, <function ConfigurationManager._init_splitaward>, <function ConfigurationManager._post_init_splitaward>), 'tullock_contest': (<class 'bnelearn.experiment.single_item_experiment.ContestExperiment'>, <function ConfigurationManager._init_tullock>, <function ConfigurationManager._post_init_tullock>)}
static get_class_by_experiment_type(experiment_type: str)[source]

Given an experiment type, returns the corresponding experiment class which could be initialized

get_config()[source]

Performs the _post_init, creates and returns the final ExperimentConfig object alongside with the appropriate experiment class

static get_default_config_members() Tuple[RunningConfig, SettingConfig, LearningConfig, LoggingConfig, HardwareConfig][source]

Creates with default (or most common) parameters and returns members of the ExperimentConfig

static load_experiment_config(experiment_log_dir=None)[source]

Retrieves stored configurations from JSON and turns them into ExperimentConfiguration object By default creates configuration from the file stored alongside the running script

Parameters:

experiment_log_dir – full path except for the file name, current working directory by default

Returns:

ExperimentConfiguration object

set_hardware(cuda: bool = 'None', specific_gpu: int = 'None', fallback: bool = 'None', max_cpu_threads: int = 'None')[source]

Sets only the parameters of hardware which were passed, returns self

set_learning(model_sharing: bool = 'None', learner_type: str = 'None', learner_hyperparams: dict = 'None', optimizer_type: str = 'None', optimizer_hyperparams: dict = 'None', scheduler_type: str = 'None', scheduler_hyperparams: dict = 'None', hidden_nodes: List[int] = 'None', pretrain_iters: int = 'None', smoothing_temperature: bool = 'None', batch_size: int = 'None', hidden_activations: List[Module] = 'None', redraw_every_iteration: bool = 'None', mixed_strategy: str = 'None', pretrain_to_bne: int = 'None', value_contest: bool = True)[source]

Sets only the parameters of learning which were passed, returns self

set_logging(enable_logging: bool = 'None', log_root_dir: str = 'None', util_loss_batch_size: int = 'None', util_loss_opponent_batch_size: int = 'None', util_loss_grid_size: int = 'None', eval_frequency: int = 'None', eval_batch_size: int = 'None', plot_frequency: int = 'None', plot_points: int = 'None', plot_show_inline: bool = 'None', log_metrics: dict = 'None', best_response: bool = 'None', save_tb_events_to_csv_aggregate: bool = 'None', save_tb_events_to_csv_detailed: bool = 'None', save_tb_events_to_binary_detailed: bool = 'None', save_models: bool = 'None', save_figure_to_disk_png: bool = 'None', save_figure_to_disk_svg: bool = 'None', save_figure_data_to_disk: bool = 'None', cache_eval_actions: bool = 'None', export_step_wise_linear_bid_function_size: bool = 'None', experiment_dir: str = 'None', experiment_name: str = 'None')[source]

Sets only the parameters of logging which were passed, returns self

set_setting(n_players: int = 'None', payment_rule: str = 'None', risk: float = 'None', n_items: int = 'None', common_prior: Distribution = 'None', valuation_mean: float = 'None', valuation_std: float = 'None', u_lo: list = 'None', u_hi: list = 'None', gamma: float = 'None', correlation_types: str = 'None', correlation_groups: List[List[int]] = 'None', correlation_coefficients: List[float] = 'None', pretrain_transform: callable = 'None', constant_marginal_values: bool = 'None', item_interest_limit: int = 'None', efficiency_parameter: float = 'None', core_solver: str = 'None', tullock_impact_factor: float = 'None', impact_function: str = 'None', crowdsourcing_values: Optional[List] = None)[source]

Sets only the parameters of setting which were passed, returns self. Using None here and below Args:

n_players: The number of players in the game. payment_rule: The payment rule to be used. risk: A strictly positive risk-parameter. A value of 1 corresponds to risk-neutral agents,

values <1 indicate risk-aversion.

common_prior: The common type distribution shared by all players, explicitly given as a

torch.distributions.Distribution object. Gaussian distribution.

valuation_mean: The expectation of the valuation distribution, when implicitly setting up a

Gaussian distribution.

valuation_std: The standard deviation of the valuation distribution, when implicitly setting up a

Gaussian distribution.

u_lo: Lower bound of valuation distribution, when implicitly setting up a Uniform distribution. u_hi: Upper bound of valuation distribution, when implicitly setting up a Uniform distribution. gamma: Correlation parameter for correlated value distributions of bidders. (Relevant Settings: LLG) correlation_types: Specifies the type of correlation model. (Most relevant settings: LLG) correlation_groups: A list of lists that ‘groups’ players into correlated subsets. All players

should be part of exactly one sublist. (Relevant settings: LLG)

correlation_coefficients: List of correlation coefficients for each

group specified with correlation_groups.

n_items: Number of items to sell. pretrain_transform: A function used to explicitly give the desired behavior in pretraining for

given neural net inputs. Defaults to identity, i.e. truthful bidding.

constant_marginal_values: Whether or not the bidders have constant marginal values in

multi-unit auctions.

item_interest_limit: Whether or not the bidders have a lower demand in units than available in

multi-unit auctions.

efficiency_parameters: Efficiency parameter in split-award auction. core_solver: Specifies which solver should be used to calculate core prices.

Should be one of ‘NoCore’, ‘mpc’, ‘gurobi’, ‘cvxpy’ (Relevant settings: LLLLGG)

Returns:

self with updated parameters.

bnelearn.experiment.configurations module

This module provides dataclasses that are used to hold configs. The values which are set to None are either not necessary, specific only for certain kinds of experiments or are set later depending on other values

class bnelearn.experiment.configurations.EnhancedJSONEncoder(*, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)[source]

Bases: JSONEncoder

default(o)[source]

Implement this method in a subclass such that it returns a serializable object for o, or calls the base implementation (to raise a TypeError).

For example, to support arbitrary iterators, you could implement default like this:

def default(self, o):
    try:
        iterable = iter(o)
    except TypeError:
        pass
    else:
        return list(iterable)
    # Let the base class default method raise the TypeError
    return JSONEncoder.default(self, o)
class bnelearn.experiment.configurations.ExperimentConfig(experiment_class: str, running: bnelearn.experiment.configurations.RunningConfig, setting: bnelearn.experiment.configurations.SettingConfig, learning: bnelearn.experiment.configurations.LearningConfig, logging: bnelearn.experiment.configurations.LoggingConfig, hardware: bnelearn.experiment.configurations.HardwareConfig)[source]

Bases: object

experiment_class: str
hardware: HardwareConfig
learning: LearningConfig
logging: LoggingConfig
running: RunningConfig
setting: SettingConfig
class bnelearn.experiment.configurations.HardwareConfig(cuda: bool, specific_gpu: int, fallback: bool, max_cpu_threads: int, device: str = None)[source]

Bases: object

cuda: bool
device: str = None
fallback: bool
max_cpu_threads: int
specific_gpu: int
class bnelearn.experiment.configurations.LearningConfig(model_sharing: bool, learner_type: str, learner_hyperparams: dict, optimizer_type: str, optimizer_hyperparams: dict, scheduler_type: str, scheduler_hyperparams: dict, hidden_nodes: List[int], pretrain_iters: int, pretrain_to_bne: int, batch_size: int, smoothing_temperature: float, redraw_every_iteration: bool, mixed_strategy: str, bias: bool, hidden_activations: List[torch.nn.modules.module.Module] = None, value_contest: bool = True)[source]

Bases: object

batch_size: int
bias: bool
hidden_activations: List[Module] = None
hidden_nodes: List[int]
learner_hyperparams: dict
learner_type: str
mixed_strategy: str
model_sharing: bool
optimizer_hyperparams: dict
optimizer_type: str
pretrain_iters: int
pretrain_to_bne: int
redraw_every_iteration: bool
scheduler_hyperparams: dict
scheduler_type: str
smoothing_temperature: float
value_contest: bool = True
class bnelearn.experiment.configurations.LoggingConfig(enable_logging: bool, log_root_dir: str, util_loss_batch_size: int, util_loss_opponent_batch_size: int, util_loss_grid_size: int, eval_frequency: int, eval_batch_size: int, cache_eval_actions: bool, plot_frequency: int, plot_points: int, plot_show_inline: bool, log_metrics: dict, best_response: bool, save_tb_events_to_csv_aggregate: bool, save_tb_events_to_csv_detailed: bool, save_tb_events_to_binary_detailed: bool, save_models: bool, log_componentwise_norm: bool, save_figure_to_disk_png: bool, save_figure_to_disk_svg: bool, save_figure_data_to_disk: bool, experiment_dir: Optional[str] = None, experiment_name: Optional[str] = None)[source]

Bases: object

Controls logging and evaluation aspects of an experiment suite.

If logging is enabled, the experiment runs will be logged to the following directories:

log_root_dir /
    [setting-specific dir hierarchy determined by Experiment subclasses] /
        experiment_timestamp + experiment_name /
            run_timestamp + run_seed
best_response: bool
cache_eval_actions: bool
enable_logging: bool
eval_batch_size: int
eval_frequency: int
experiment_dir: str = None
experiment_name: str = None
export_step_wise_linear_bid_function_size = None
log_componentwise_norm: bool
log_metrics: dict
log_root_dir: str
plot_frequency: int
plot_points: int
plot_show_inline: bool
save_figure_data_to_disk: bool
save_figure_to_disk_png: bool
save_figure_to_disk_svg: bool
save_models: bool
save_tb_events_to_binary_detailed: bool
save_tb_events_to_csv_aggregate: bool
save_tb_events_to_csv_detailed: bool
util_loss_batch_size: int
util_loss_grid_size: int
util_loss_opponent_batch_size: int
class bnelearn.experiment.configurations.RunningConfig(n_runs: int, n_epochs: int, seeds: Iterable[int] = None)[source]

Bases: object

n_epochs: int
n_runs: int
seeds: Iterable[int] = None
class bnelearn.experiment.configurations.SettingConfig(n_players: int, n_items: int, payment_rule: str, risk: float, common_prior: torch.distributions.distribution.Distribution = None, valuation_mean: float = None, valuation_std: float = None, u_lo: list = None, u_hi: list = None, gamma: float = None, correlation_types: str = None, correlation_groups: List[List[int]] = None, correlation_coefficients: List[float] = None, pretrain_transform: <built-in function callable> = None, constant_marginal_values: bool = False, item_interest_limit: int = None, efficiency_parameter: float = None, core_solver: str = None, tullock_impact_factor: float = None, impact_function: str = None, crowdsourcing_values: List = None)[source]

Bases: object

common_prior: Distribution = None
constant_marginal_values: bool = False
core_solver: str = None
correlation_coefficients: List[float] = None
correlation_groups: List[List[int]] = None
correlation_types: str = None
crowdsourcing_values: List = None
efficiency_parameter: float = None
gamma: float = None
impact_function: str = None
item_interest_limit: int = None
n_items: int
n_players: int
payment_rule: str
pretrain_transform: callable = None
risk: float
tullock_impact_factor: float = None
u_hi: list = None
u_lo: list = None
valuation_mean: float = None
valuation_std: float = None
bnelearn.experiment.equilibria module

This module contains implementations of known Bayes-Nash equilibrium bid functions in several specific settings. Whenever possible, the bid functions are fully vectorized.

NOTE: This module contains a mix of direct implementations of bid functions, and factory methods that create and return the bid function as a callable object.

bnelearn.experiment.equilibria.bne1_kaplan_zhamir(u_lo: List, u_hi: List)[source]

BNE in asymmetric 2-player IPV first-price auctions, when both players have quasilinear-utilities and uniform priors, that do NOT share the same lower bound and are non overlapping.

This setting was analyzed by Kaplan and Zhamir (2014) and was found to have multiple pure BNE. (At least 3).

Reference: Equilibrium 1 of https://link.springer.com/article/10.1007/s40505-014-0049-1

NOTE: this implementation is hard-coded for the bounds used in the paper above, i.e. [0,5] and [6,7], but we do not perform any checks at runtime for performance reasons!

bnelearn.experiment.equilibria.bne2_kaplan_zhamir(valuation: Tensor, player_position: int, u_lo: List, u_hi: List)[source]

BNE in asymmetric 2-player IPV first-price auctions, when both players have quasilinear-utilities and uniform priors, that do NOT share the same lower bound and are nonoverlapping.

This setting was analyzed by Kaplan and Zhamir (2014) and was found to have multiple pure BNE. (At least 3).

Reference: Equilibrium 2 of https://link.springer.com/article/10.1007/s40505-014-0049-1

NOTE: this implementation is hard-coded for the bounds used in the paper above, i.e. [0,5] and [6,7], but we do not perform any checks at runtime for performance reasons!

bnelearn.experiment.equilibria.bne3_kaplan_zhamir(valuation: Tensor, player_position: int, u_lo: List, u_hi: List)[source]

BNE in asymmetric 2-player IPV first-price auctions, when both players have quasilinear-utilities and uniform priors, that do NOT share the same lower bound and are nonoverlapping.

This setting was analyzed by Kaplan and Zhamir (2014) and was found to have multiple pure BNE. (At least 3).

Reference: Equilibrium 3 of https://link.springer.com/article/10.1007/s40505-014-0049-1

NOTE: this implementation is hard-coded for the bounds used in the paper above, i.e. [0,5] and [6,7], but we do not perform any checks at runtime for performance reasons!

bnelearn.experiment.equilibria.bne_2p_affiliated_values(valuation: Tensor, player_position: int = 0) Tensor[source]

Symmetric BNE in the 2p affiliated values model.

Reference: Krishna (2009), Example 6.2

bnelearn.experiment.equilibria.bne_3p_mineral_rights(valuation: Tensor, player_position: int = 0) Tensor[source]

BNE in the 3-player ‘Mineral Rights’ setting.

Reference: Krishna (2009), Example 6.1

bnelearn.experiment.equilibria.bne_crowdsourcing_symmetric_uniform_cost(valuation: Tensor, v1: float = 0.5, **kwargs)[source]
bnelearn.experiment.equilibria.bne_crowdsourcing_symmetric_uniform_value(valuation: Tensor, v1: float = 1, v2=0, N: int = 0, player_position=0, **kwargs)[source]
bnelearn.experiment.equilibria.bne_fpsb_ipv_asymmetric_uniform_overlapping_priors_risk_neutral(valuation: Tensor, player_position: int, u_lo: List, u_hi: List) Tensor[source]

BNE in asymmetric 2-player IPV first-price auctions, when both players have quasilinear-utilities and uniform valuation priors that share the same lower lower bound, but may differ in the upper bound.

Reference: https://link.springer.com/article/10.1007/BF01271133

bnelearn.experiment.equilibria.bne_fpsb_ipv_symmetric_generic_prior_risk_neutral(valuation: Union[Tensor, ndarray, float], n_players: int, prior_cdf: Callable, **kwargs) Tensor[source]
BNE in symmetric IPV first-price sealed bid auctions with

generic prior value distributions and quasi-linear utilities.

Reference: Krishna (2009), Chapter 2, Proof of Proposition 2.2.

bnelearn.experiment.equilibria.bne_fpsb_ipv_symmetric_uniform_prior(valuation: Tensor, n: int, r: float, u_lo, u_hi, **kwargs) Tensor[source]

BNE in the special case of symmetric FPSB IPV auctions where priors are symmetric uniform.

Compared to the generic case above, we also know this BNE for risk-averse agents.

Reference:

In terms of implementation, note that this equlibrium is fully vectorized.

bnelearn.experiment.equilibria.bne_splitaward_2x2_1_factory(experiment_config, payoff_dominant: bool = True)[source]

Factory method returning the BNE pooling equilibrium in the split-award auction with 2 players and 2 lots (as in Anton and Yao, 1992).

Actually, this is a continuum of BNEs of which this function returns the upper bound (payoff dominant BNE) and the one at the lower bound.

Returns:

optimal_bid (callable): The equilibrium bid function.

bnelearn.experiment.equilibria.bne_splitaward_2x2_2_factory(experiment_config)[source]

Factory method returning the BNE WTA equilibrium in the split-award auction with 2 players and 2 lots (as in Anton and Yao Proposition 4, 1992).

Returns:

optimal_bid (callable): The equilibrium bid function.

bnelearn.experiment.equilibria.bne_symmetric_all_pay_uniform_prior(valuation: Tensor, n_player: int, **kwargs) Tensor[source]
bnelearn.experiment.equilibria.multiunit_bne_factory(setting, payment_rule) Callable[source]

Factory method that returns the known BNE strategy function for the standard multi-unit auctions (split-award is NOT one of the) as callable if available and None otherwise.

bnelearn.experiment.equilibria.truthful_bid(valuation: Tensor, **kwargs) Tensor[source]

Truthful bidding function: A BNE in any VCG auction.

bnelearn.experiment.experiment module

This module defines an experiment. It includes logging and plotting since they can often be shared by specific experiments.

class bnelearn.experiment.experiment.Experiment(config: ExperimentConfig)[source]

Bases: ABC

Abstract Class representing an experiment

action_size: int
bne_env: AuctionEnvironment
bne_utilities: Tensor
epoch: int
input_length: int
mechanism: Mechanism
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
pretrain_transform(player_position: int) callable[source]

Some experiments need specific pretraining transformations. In most cases, pretraining to the truthful bid (i.e. the identity function) is sufficient.

Args:
player_position (:int:) the player for which the transformation is

requested.

Returns

(:callable:) pretraining transformation

run() bool[source]

Runs the experiment implemented by this class, i.e. all defined runs.

If a run fails for whatever reason, a warning will be raised and the next run will be triggered until all runs have completed/failed.

Returns:

success (bool): True if all runs ran successfully, false otherwise.

valuation_size: int
bnelearn.experiment.multi_unit_experiment module

In this file multi-unit experiments MultiUnitExperiment are defined and their analytical BNEs (if known) are assigned. Also, the SplitAwardExperiment is implemented as well, as it shares most its properties.

class bnelearn.experiment.multi_unit_experiment.MultiUnitExperiment(config: ExperimentConfig)[source]

Bases: _MultiUnitSetupEvalMixin, Experiment

Experiment class for the standard multi-unit auctions.

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
class bnelearn.experiment.multi_unit_experiment.SplitAwardExperiment(config: ExperimentConfig)[source]

Bases: _MultiUnitSetupEvalMixin, Experiment

Experiment class of the first-price sealed bid split-award auction.

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
pretrain_transform(player_position)[source]

Some experiments need specific pretraining transformations. In most cases, pretraining to the truthful bid (i.e. the identity function) is sufficient.

Args:
player_position (:int:) the player for which the transformation is

requested.

Returns

(:callable:) pretraining transformation

sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
bnelearn.experiment.single_item_experiment module

This module implements Experiments on single items

class bnelearn.experiment.single_item_experiment.AffiliatedObservationsExperiment(config: ExperimentConfig)[source]

Bases: SingleItemExperiment

A Single Item Experiment that has the same valuation prior for all participating bidders. For risk-neutral agents, a unique BNE is known.

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
class bnelearn.experiment.single_item_experiment.ContestExperiment(config: ExperimentConfig)[source]

Bases: SymmetricPriorSingleItemExperiment

This class implements a symmetric Contest Experiment

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
pretrain_transform(player_pos: Optional[int] = None) callable[source]

Some experiments need specific pretraining transformations. In most cases, pretraining to the truthful bid (i.e. the identity function) is sufficient.

Args:
player_position (:int:) the player for which the transformation is

requested.

Returns

(:callable:) pretraining transformation

sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
class bnelearn.experiment.single_item_experiment.GaussianSymmetricPriorSingleItemExperiment(config: ExperimentConfig)[source]

Bases: SymmetricPriorSingleItemExperiment

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
class bnelearn.experiment.single_item_experiment.MineralRightsExperiment(config: ExperimentConfig)[source]

Bases: SingleItemExperiment

A Single Item Experiment that has the same valuation prior for all participating bidders. For risk-neutral agents, a unique BNE is known.

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
class bnelearn.experiment.single_item_experiment.SingleItemExperiment(config: ExperimentConfig)[source]

Bases: Experiment, ABC

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
static get_risk_profile(risk) str[source]

Used for logging and checking existence of bne

input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
class bnelearn.experiment.single_item_experiment.SymmetricPriorSingleItemExperiment(config: ExperimentConfig)[source]

Bases: SingleItemExperiment

A Single Item Experiment that has the same valuation prior for all participating bidders. For risk-neutral agents, a unique BNE is known.

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
class bnelearn.experiment.single_item_experiment.TwoPlayerAsymmetricBetaPriorSingleItemExperiment(config: ExperimentConfig)[source]

Bases: SingleItemExperiment

A single item experiment where two bidders have different beta priors.

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
class bnelearn.experiment.single_item_experiment.TwoPlayerAsymmetricUniformPriorSingleItemExperiment(config: ExperimentConfig)[source]

Bases: SingleItemExperiment

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
class bnelearn.experiment.single_item_experiment.UniformSymmetricPriorSingleItemExperiment(config: ExperimentConfig)[source]

Bases: SymmetricPriorSingleItemExperiment

action_size: int
b_opt: torch.Tensor
bidders: Iterable[Bidder]
bne_env: AuctionEnvironment
bne_utilities: Tensor
env: Environment
epoch: int
input_length: int
learners: Iterable[learners.Learner]
mechanism: Mechanism
models: Iterable[torch.nn.Module]
n_models: int
observation_size: int
plot_xmax: float
plot_xmin: float
plot_ymax: float
plot_ymin: float
positive_output_point: Tensor
sampler: ValuationObservationSampler
v_opt: torch.Tensor
valuation_size: int
Module contents

Main module that handles everything needed for learning.

bnelearn.mechanism package
Submodules
bnelearn.mechanism.auctions_combinatorial module

Auction mechanism for combinatorial auctions (where bidders are interested in bundles of items).

class bnelearn.mechanism.auctions_combinatorial.CombinatorialAuction(rule='first_price', cuda: bool = True, bundles=None, parallel: int = 1)[source]

Bases: Mechanism

A combinatorial auction, implemented via (possibly parallel) calls to the gurobi solver.

Args:

rule: pricing rule

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Performs a general Combinatorial auction

Args:
bids: torch.Tensor

of bids with dimensions (batch_size, n_players, 2) [0,Inf]

bundles: torch.Tensor

of bundles with dimensions (batch_size, 2, n_items), {0,1}

Returns:

allocation: torch.Tensor, dim (batch_size, n_bidders, 2) payments: torch.Tensor, dim (batch_size, n_bidders)

class bnelearn.mechanism.auctions_combinatorial.LLGAuction(rule='first_price', cuda: bool = True)[source]

Bases: Mechanism

Implements simple auctions in the LLG setting with 3 bidders and 2 goods. Notably, this is not an implementation of a general Combinatorial auction and bidders do not submit full bundle (XOR) bids: Rather, it’s assumed a priori that each bidder bids on a specific bundle: The first bidder will only bid on the bundle {1}, the second on {2}, the third on {1,2}, thus actions are scalar for each bidder.

For the LLG Domain see e.g. Ausubel & Milgrom 2006 or Bosshard et al 2017

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Runs a (batch of) LLG Combinatorial auction(s).

We assume n_players == 3 with 0,1 being local bidders and 3 being the global bidder.

Parameters
bids: torch.Tensor

of bids with dimensions (batch_size, n_players, 1)

Returns
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (n_batches x n_players x 1),

1 indicating the desired bundle is allocated to corresponding player in that batch, 0 otherwise. (i.e. 1 for player0 means {1} allocated, for player2 means {2} allocated, for player3 means {1,2} allocated.)

payments: tensor of dimension (n_batches x n_players)

Total payment from player to auctioneer for her allocation in that batch.

class bnelearn.mechanism.auctions_combinatorial.LLGFullAuction(rule='first_price', cuda: bool = True)[source]

Bases: Mechanism

Implements auctions in the LLG setting with 3 bidders and 2 goods.

Here, bidders do submit full bundle (XOR) bids. For this specific LLG domain see (Beck and Ott 2013).

Item dim 0 corresponds to item A, dim 1 to item B and dim 2 to the bundle of both.

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Runs a batch of LLG Combinatorial auctions.

We assume n_players == 3 with 0, 1 being local bidders and 3 being the global bidder.

Args:
bids (torch.Tensor): of bids with dimensions (*batch_sizes,

n_players, 3).

Returns:
(allocation, payments) (tuple of torch.Tensor):

allocation: tensor of dimension (*batche_sizes x n_players x 3) payments: tensor of dimension (*batch_sizes x n_players)

class bnelearn.mechanism.auctions_combinatorial.LLLLGGAuction(rule='first_price', core_solver='NoCore', parallel: int = 1, cuda: bool = True)[source]

Bases: Mechanism

Inspired by implementation of Seuken Paper (Bosshard et al. (2019), https://arxiv.org/abs/1812.01955). Hard coded possible solutions for faster batch computations.

Args:

rule: pricing rule core_solver: which solver to use, only relevant if pricing rule is a core rule parallel: number of processors for parallelization in gurobi (only)

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Performs a specific LLLLGG auction as in Seuken Paper (Bosshard et al. (2019))

Args:
bids: torch.Tensor

of bids with dimensions (*batch_sizes, n_players, 2) [0,Inf]

bundles: torch.Tensor

of bundles with dimensions (*batch_sizes, 2, n_items), {0,1}

Returns:

allocation: torch.Tensor, dim (batch_size, n_bidders, 2) payments: torch.Tensor, dim (batch_size, n_bidders)

class bnelearn.mechanism.auctions_combinatorial.LLLLRRGAuction(rule='first_price', core_solver='NoCore', parallel: int = 1, cuda: bool = True)[source]

Bases: LLLLGGAuction

Extended LLLLGG Auction with an additional ‘superglobal’ bider. Implementation is identical to LLLLGG except we overwrite some settings in the constructor.

bnelearn.mechanism.auctions_multiunit module

Auction mechanism for multi-unit auctions (where objects are homogeneous).

class bnelearn.mechanism.auctions_multiunit.FPSBSplitAwardAuction(cuda: bool = True, smoothing_temperature: Optional[float] = None)[source]

Bases: MultiUnitAuction

First-price sealed-bid split-award auction: Multiple agents bidding for either 100% of the share or 50%.

We define a bids as torch.Tensor with dimensions (*batch_sizes, n_players, n_bids=2), where the first bid is for the 50% share and the second for the 100% share.

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Performs a batch of split-award auction rounds.

Args:
bids: torch.Tensor

of bids with dimensions (*batch_sizes, n_players, n_items=2); first entry of n_items dim corresponds to bid for 50% lot, second entry to bid for 100% lot, etc.

Returns:
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (*n_batches x n_players x 2),

1 indicating item is allocated to corresponding player in that batch, 0 otherwise.

payments: tensor of dimension (*n_batches x n_players);

total payment from player to auctioneer for her allocation in that batch.

class bnelearn.mechanism.auctions_multiunit.MultiUnitAuction(cuda: bool = True, smoothing_temperature: Optional[float] = None)[source]

Bases: Mechanism

Class for multi-unit auctions where multiple identical items (so called units) are for sale. Agents thus don’t care about winning item no. x or no. y, as they’re homogeneous.

class bnelearn.mechanism.auctions_multiunit.MultiUnitDiscriminatoryAuction(cuda: bool = True, smoothing_temperature: Optional[float] = None)[source]

Bases: MultiUnitAuction

Multi item discriminatory auction. Units are allocated to the highest n_item bids, winners pay as bid.

Bids of each bidder must be in decreasing order, otherwise the mechanism does not accept these bids and allocates no units to this bidder.

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Runs a (batch of) multi item discriminatory auction(s). Invalid bids (i.e. in increasing order) will be ignored (-> no allocation to that bidder), s.t. the bidder might be able to “learn” the right behavior.

Args:
bids: torch.Tensor

of bids with dimensions (*batch_sizes, n_players, n_items); first entry of n_items dim corresponds to bid of first unit, second entry to bid of second unit, etc.

Returns:
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (n_batches x n_players x

n_items), 1 indicating item is allocated to corresponding player in that batch, 0 otherwise.

payments: tensor of dimension (n_batches x n_players);

total payment from player to auctioneer for her allocation in that batch.

class bnelearn.mechanism.auctions_multiunit.MultiUnitUniformPriceAuction(cuda: bool = True, smoothing_temperature: Optional[float] = None)[source]

Bases: MultiUnitAuction

In a uniform-price auction, all units are sold at a “market-clearing” price such that the total amount demanded is equal to the total amount supplied. We adopt the rule that the market-clearing price is the same as the highest losing bid.

Bids of each bidder must be in decreasing order, otherwise the mechanism does not accept these bids and allocates no units to this bidder.

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Runs a (batch of) Multi Unit Uniform-Price Auction(s). Invalid bids (i.e. in increasing order) will be ignored (-> no allocation to that bidder), s.t. the bidder might be able to “learn” the right behavior.

Args:
bids: torch.Tensor

of bids with dimensions (*batch_sizes, n_players, n_items); first entry of n_items dim corresponds to bid of first unit, second entry to bid of second unit, etc.

Returns:
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (n_batches x n_players x

n_items), 1 indicating item is allocated to corresponding player in that batch, 0 otherwise.

payments: tensor of dimension (n_batches x n_players);

total payment from player to auctioneer for her allocation in that batch.

class bnelearn.mechanism.auctions_multiunit.MultiUnitVickreyAuction(cuda: bool = True, smoothing_temperature: Optional[float] = None)[source]

Bases: MultiUnitAuction

In a Vickrey auction, a bidder who wins k units pays the k highest losing bids of the other bidders.

Bids of each bidder must be in decreasing order, otherwise the mechanism does not accept these bids and allocates no units to this bidder.

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Runs a (batch of) Multi Unit Vickrey Auction(s). Invalid bids (i.e. in increasing order) will be ignored (-> no allocation to that bidder), s.t. the bidder might be able to “learn” the right behavior.

Args:
bids: torch.Tensor

of bids with dimensions (*batch_sizes, n_players, n_items); first entry of n_items dim corresponds to bid of first unit, second entry to bid of second unit, etc.

Returns:
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (n_batches x n_players x

n_items), 1 indicating item is allocated to corresponding player in that batch, 0 otherwise.

payments: tensor of dimension (n_batches x n_players);

total payment from player to auctioneer for her allocation in that batch.

bnelearn.mechanism.auctions_single_item module
class bnelearn.mechanism.auctions_single_item.AllPayAuction(cuda: bool)[source]

Bases: Mechanism

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Runs a (batch of) All-Pay Auctions.

This function is meant for single-item auctions. If a bid tensor for multiple items is submitted, each item is auctioned independently of one another.

Parameters
bids: torch.Tensor

of bids with dimensions (*batch_sizes, n_players, n_items)

Returns
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (*batch_sizes x n_players x n_items),

1 indicating item is allocated to corresponding player in that batch, 0 otherwise

payments: tensor of dimension (*batch_sizes x n_players)

Total payment from player to auctioneer for her allocation in that batch.

class bnelearn.mechanism.auctions_single_item.FirstPriceSealedBidAuction(**kwargs)[source]

Bases: Mechanism

First Price Sealed Bid auction

run(bids: Tensor, smooth_market: bool = False) Tuple[Tensor, Tensor][source]

Runs a (batch of) First Price Sealed Bid Auction.

This function is meant for single-item auctions. If a bid tensor for multiple items is submitted, each item is auctioned independently of one another.

Parameters
bids: torch.Tensor

of bids with dimensions (*batch_sizes, n_players, n_items)

Returns
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (*batch_sizes x n_players x n_items),

1 indicating item is allocated to corresponding player in that batch, 0 otherwise

payments: tensor of dimension (*batch_sizes x n_players)

Total payment from player to auctioneer for her allocation in that batch.

class bnelearn.mechanism.auctions_single_item.ThirdPriceSealedBidAuction(cuda: bool = True, smoothing_temperature: Optional[float] = None)[source]

Bases: Mechanism

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Runs a (batch of) Third Price Sealed Bid Auctions.

This function is meant for single-item auctions. If a bid tensor for multiple items is submitted, each item is auctioned independently of one another.

Parameters
bids: torch.Tensor

of bids with dimensions (batch_size, n_players, n_items)

Returns
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (n_batches x n_players x n_items),

1 indicating item is allocated to corresponding player in that batch, 0 otherwise

payments: tensor of dimension (n_batches x n_players)

Total payment from player to auctioneer for her allocation in that batch.

class bnelearn.mechanism.auctions_single_item.VickreyAuction(random_tie_break: bool = False, **kwargs)[source]

Bases: Mechanism

Vickrey / Second Price Sealed Bid Auctions

run(bids: Tensor, smooth_market: bool = False) Tuple[Tensor, Tensor][source]

Runs a (batch of) Vickrey/Second Price Sealed Bid Auctions.

This function is meant for single-item auctions. If a bid tensor for multiple items is submitted, each item is auctioned independently of one another.

Parameters
bids: torch.Tensor

of bids with dimensions (batch_size, n_players, n_items)

smooth_market: Smoothens allocations and payments s.t. the ex-post

utility is continuous again. This introduces a bias though. PG then is applicable.

Returns
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (n_batches x n_players x n_items),

1 indicating item is allocated to corresponding player in that batch, 0 otherwise

payments: tensor of dimension (n_batches x n_players)

Total payment from player to auctioneer for her allocation in that batch.

bnelearn.mechanism.auctions_single_player module
class bnelearn.mechanism.auctions_single_player.StaticFunctionMechanism(cuda: bool = True, smoothing_temperature: Optional[float] = None)[source]

Bases: Mechanism

A static mechanism that can be used for testing purposes, in order to test functionality/efficiency of optimizers without introducing additional stochasticity from multi-player learning dynamics. This function more straightforward than the Static Mechanism above, which has stochasticity similar to an auction.

Instead, this class returns a straight up function, designed such that vanilla PG will also work on it.

Here, the player gets the item with probability 0.5 and pays (5-b)², i.e. it’s optimal to always bid 5. The expected utility in optimal strategy is thus 2.5.

run(bids)[source]

Alias for play for auction mechanisms

class bnelearn.mechanism.auctions_single_player.StaticMechanism(cuda: bool = True, smoothing_temperature: Optional[float] = None)[source]

Bases: Mechanism

A static mechanism that can be used for testing purposes, in order to test functionality/efficiency of optimizers without introducing additional stochasticity from multi-player learning dynamics.

In this ‘single-player single-item’ setting, items are allocated with probability bid/10, payments are always given by b²/20, even when the item is not allocated. The expected payoff from this mechanism is thus b/10 * v - 0.05b², The optimal strategy fo an agent with quasilinear utility is given by bidding truthfully.

run(bids: Tensor)[source]

Alias for play for auction mechanisms

bnelearn.mechanism.contests_single_item module
class bnelearn.mechanism.contests_single_item.CrowdsourcingContest(cuda: bool = True)[source]

Bases: Mechanism

Crowdsourcing Contest

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Runs a (batch of) Crowdsourcing Contests.

If a effort tensor for multiple items is submitted, each item is auctioned independently of one another.

Parameters
efforts: torch.Tensor

of efforts with dimensions (*batch_sizes, n_players, n_items)

Returns
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (*batch_sizes x n_players x n_items),

Entry indicates which prize the corresponding contestant would have won

payments: tensor of dimension (*batch_sizes x n_players)

Total payment from player to auctioneer for her allocation in that batch.

class bnelearn.mechanism.contests_single_item.TullockContest(impact_function, cuda: bool = True)[source]

Bases: Mechanism

Tullock Contest

run(bids: Tensor) Tuple[Tensor, Tensor][source]

Runs a (batch of) Tullock Contests.

This function is meant for single-item contests. If a effort tensor for multiple items is submitted, each item is auctioned independently of one another.

Note that if multiple contestants submit the highest effort, we choose the first one.

Parameters
bids: torch.Tensor

of efforts with dimensions (*batch_sizes, n_players, n_items)

Returns
(winning_probs, payments): Tuple[torch.Tensor, torch.Tensor]
winning_probs: tensor of dimension (*batch_sizes x n_players x n_items),

Winning probabilities defined by the impact function and the contest success function

payments: tensor of dimension (*batch_sizes x n_players)

Total payment from player to auctioneer for her allocation in that batch.

bnelearn.mechanism.data module

This module contains static data about all possible solutions in the LLG and LLLLGG combinatorial auctions, which may constitute efficient allocations.

class bnelearn.mechanism.data.CombinatorialAuctionData[source]

Bases: ABC

Wraper class to represent static data of a large combinatorial auction.

classmethod efficient_allocations_dense(device='cpu') Tensor[source]

Returns the possible efficient allocations as a dense tensor

classmethod legal_allocations_dense(device='cpu') Tensor[source]

returns a dense torch tensor of all possible legal allocations on the desired device. Output shape: n_legal_allocations x n_bundles

classmethod legal_allocations_sparse(device='cpu') Tensor[source]

returns the sparse index representation of legal allocations as a torch.Tensor.

abstract class property n_bundles: int
classmethod player_bundles(device='cpu') Tensor[source]

returns the player bundle matching as a torch.Tensor

class bnelearn.mechanism.data.LLGData[source]

Bases: object

Contains static data about legal allocations in the LLG setting.

bundles = [[0], [1], [0, 1]]
legal_allocations_dense = [[0, 0, 1, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 1, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0, 1, 0], [0, 1, 0, 1, 0, 0, 0, 0, 0], [0, 0, 0, 1, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0, 0, 1, 0], [0, 1, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 1, 1, 0]]
legal_allocations_sparse = [[0, 0], [1, 1], [2, 2], [3, 3], [4, 4], [5, 5], [6, 6], [7, 7], [8, 8], [9, 0], [9, 4], [10, 1], [10, 3], [11, 0], [11, 1], [12, 0], [12, 7], [13, 1], [13, 6], [14, 3], [14, 4], [15, 3], [15, 7], [16, 4], [16, 6], [17, 6], [17, 7]]
class bnelearn.mechanism.data.LLLLGGData[source]

Bases: CombinatorialAuctionData

Static data about legal and possibly efficient allocations in the LLLLGG setting. For details about the representation, see Bosshard et al. (2019), https://arxiv.org/abs/1812.01955.

efficient_allocations_semisparse: List[List[int]] = [[0, 2, 4, 6], [1, 3, 5, 7], [4, 6, 8], [0, 2, 9], [0, 6, 10], [2, 4, 11], [5, 8], [1, 9], [7, 10], [3, 11], [0, 2, 5], [2, 4, 7], [1, 4, 6], [0, 3, 6], [0, 3, 5], [2, 5, 7], [1, 3, 6], [1, 4, 7]]
n_bundles = 12
class bnelearn.mechanism.data.LLLLRRGData[source]

Bases: CombinatorialAuctionData

Static data about legal and possibly efficient allocations in the LLLLRRG setting. This extends the LLLLGG setting by adding a 7th, “superglobal” player, who is interested in the bundle of all 8 items.

In this setting, we’ll call the new player ‘global’, and the players interested in 4-item-bundles (R in LLLLRRG, G in LLLLGG) ‘regional’.

efficient_allocations_semisparse = [[0, 2, 4, 6], [1, 3, 5, 7], [4, 6, 8], [0, 2, 9], [0, 6, 10], [2, 4, 11], [5, 8], [1, 9], [7, 10], [3, 11], [0, 2, 5], [2, 4, 7], [1, 4, 6], [0, 3, 6], [0, 3, 5], [2, 5, 7], [1, 3, 6], [1, 4, 7], 12]
n_bundles = 14
bnelearn.mechanism.matrix_games module

Matrix Games

class bnelearn.mechanism.matrix_games.BattleOfTheSexes(**kwargs)[source]

Bases: MatrixGame

Two player, two action Battle of the Sexes game

class bnelearn.mechanism.matrix_games.BattleOfTheSexesMod(**kwargs)[source]

Bases: MatrixGame

Modified Battle of the Sexes game

class bnelearn.mechanism.matrix_games.JordanGame(**kwargs)[source]

Bases: MatrixGame

Jordan Anticoordination game (1993), FP does not converge. 3P version of Shapley fashion game: Player Actions: (Left, Right) P1 wants to be different from P2 P2 wants to be different from P3 P3 wants to be different from P1

class bnelearn.mechanism.matrix_games.MatchingPennies(**kwargs)[source]

Bases: MatrixGame

Two Player, two action Matching Pennies / anticoordination game

class bnelearn.mechanism.matrix_games.MatrixGame(n_players: int, outcomes: Tensor, cuda: bool = True, names: Optional[dict] = None, validate_inputs: bool = True)[source]

Bases: Game

A complete information Matrix game.

TODO: missing documentation

calculate_expected_action_payoffs(strategy_profile, player_position)[source]

Calculates the expected utility for a player under a mixed opponent strategy

Args:
strategy_profile: List of action-probability-vectors for each player.

Player i’s strategy must be supplied but is ignored.

player_position: player of interest

Returns:

expected payoff per action of player i (tensor of dimension (1 x n_actions[i])

get_action_name(action_id: int)[source]

Currently only works if all players have same action set!

get_player_name(player_id: int)[source]

Returns readable name of player if provided.

play(action_profile)[source]

Plays the game for a given action_profile.

Parameters
action_profile: torch.Tensor

Shape: (batch_size, n_players, n_items) n_items should be 1 for now. (This might change in the future to represent information sets!) Actions should be integer indices. #TODO: Ipmlement that they can also be action names!

Mixed strategies are NOT allowed as input, sampling should happen in the player class.

Returns
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]
allocation: tensor of dimension (n_batches x n_players x n_items),

In this setting, there’s nothing to be allocated, so it will be all zeroes.

payments: tensor of dimension (n_batches x n_players)

Negative outcome/utility for each player.

play_mixed(strategy_profile: List[Tensor], validate: Optional[bool] = None)[source]

Plays the game with mixed strategies, returning expectation of outcomes.

This version does NOT support batches or multiple items, as (1) batches do not make sense in this setting since we are already returning expectations.

Parameters
strategy_profile: List[torch.Tensor]. A list of strategies for each player.

Each element i should be a 1-dimensional torch tensor of length n_actions_pi with entries j = P(player i plays action j)

validate: bool. Whether to validate inputs. Defaults to setting in game class.

(Validation overhead is ~100%, so you might want to turn this off in settings with many many iterations)

Returns
(allocation, payments): Tuple[torch.Tensor, torch.Tensor]

allocation: empty tensor of dimension (0) –> not used in this game payments: tensor of dimension (n_players)

Negative expected outcome/utility for each player.

class bnelearn.mechanism.matrix_games.PaulTestGame(**kwargs)[source]

Bases: MatrixGame

A 3-p game without many symmetries used for testing n-player tensor implementations. Payoff: [M,R,C]

class bnelearn.mechanism.matrix_games.PrisonersDilemma(**kwargs)[source]

Bases: MatrixGame

Two player, two action Prisoner’s Dilemma game. Has a unique pure Nash equilibrium in ap [1,1]

class bnelearn.mechanism.matrix_games.RockPaperScissors(**kwargs)[source]

Bases: MatrixGame

2 player, 3 action game rock paper scissors

bnelearn.mechanism.mechanism module

This module implements games such as matrix games and auctions.

class bnelearn.mechanism.mechanism.Game(cuda: bool = True)[source]

Bases: ABC

Base class for any kind of games

abstract play(action_profile)[source]

Play the game!

class bnelearn.mechanism.mechanism.Mechanism(cuda: bool = True, smoothing_temperature: Optional[float] = None)[source]

Bases: Game, ABC

Auction Mechanism - Interpreted as a Bayesian game. A Mechanism collects bids from all players, then allocates available items as well as payments for each of the players.

play(action_profile, smooth_market: bool = False) Tuple[Tensor, Tensor][source]

Play the game!

abstract run(bids) Tuple[Tensor, Tensor][source]

Alias for play for auction mechanisms

Module contents
bnelearn.sampler package
Submodules
bnelearn.sampler.base module

This class provides primitives to implement samplers that support drawing of valuation and observation profiles for a set of players.

class bnelearn.sampler.base.CompositeValuationObservationSampler(n_players: int, valuation_size: int, observation_size: int, subgroup_samplers: List[ValuationObservationSampler], default_batch_size=1, default_device=None)[source]

Bases: ValuationObservationSampler

A class representing composite prior distributions that are made up of several groups of bidders, each of which can be represented by an atomic ValuationObservationSampler, and which are independent between-group (but not necessarily within-group).

Limitation: The current implementation requires that all players nevertheless have the same valuation_size.

draw_conditional_profiles(conditioned_player: int, conditioned_observation: Tensor, inner_batch_size: int, device: Optional[Union[device, str, int]] = None) Tuple[Tensor, Tensor][source]

Draws and returns batches conditional valuation and corresponding observation profile. For each entry of conditioned_observation, inner_batch_size samples will be drawn!

Note that here, we are returning full profiles instead (including conditioned_player’s observation and others’ valuations.)

Args:
conditioned_player: int

Index of the player whose observation we are conditioning on.

conditioned_observation: torch.Tensor (*outer_batch_sizes (implicit), observation_size)

A batch of/batches of observations of player conditioned_player.

Kwargs:

batch_size (optional): int, the “inner”batch_size to draw - i.e. how many conditional samples to draw for each provided conditional_observation. If none provided, will use self.default_batch_size of the class.

Returns:
valuations: torch.Tensor (batch_size x n_players x valuation_size):

a conditional valuation profile

observations: torch.Tensor (*outer_batch_sizes, inner_batch_size, n_players, observation_size):

a corresponding conditional observation profile. observations[…,conditioned_observation,:] will be equal to conditioned_observation repeated batch_size times

draw_profiles(batch_sizes: Optional[int] = None, device=None) Tuple[Tensor, Tensor][source]

Draws and returns a batch of valuation and observation profiles.

Kwargs:

batch_sizes (optional): List[int], the batch_size to draw. If none provided, self.default_batch_size will be used. device (optional): torch.cuda.Device, the device to draw profiles on

Returns:

valuations: torch.Tensor (*batch_sizes x n_players x valuation_size): a valuation profile observations: torch.Tensor (*batch_sizes x n_players x observation_size): an observation profile

generate_action_grid(**kwargs) Tensor[source]

Possibly need to call specific sampling

generate_cell_partition(**kwargs) Tensor[source]

Possibly need to call specific sampling

generate_reduced_grid(**kwargs) Tensor[source]

Possibly need to call specific sampling

generate_valuation_grid(**kwargs) Tensor[source]

Possibly need to call specific sampling

class bnelearn.sampler.base.FlushedWrappedSampler(base_sampler: ValuationObservationSampler, flush_val_dims: int = 1, flush_obs_dims: int = 1)[source]

Bases: ValuationObservationSampler

A sampler that relies on a base sampler but flushes the last valuation and observations dimensions with zeros.

This is useful when some players have lower observation / valuation size than others.

Note on implementation: an alternative would be using a lower-dimensional base sampler and then adding extra zeroes. We instead go this route of overwriting unnecessary values because the incurred cost of sampling too many values will be cheaper in most cases compared to ‘growing’ tensors after the fact.

draw_conditional_profiles(conditioned_player: int, conditioned_observation: Tensor, inner_batch_size: int, device: Optional[Union[device, str, int]] = None) Tuple[Tensor, Tensor][source]

Draws and returns batches conditional valuation and corresponding observation profile. For each entry of conditioned_observation, batch_size samples will be drawn!

Note that here, we are returning full profiles instead (including conditioned_player’s observation and others’ valuations.)

Args:
conditioned_player: int

Index of the player whose observation we are conditioning on.

conditioned_observation: torch.Tensor (*outer_batch_sizes (implicit), observation_size)

A (batch of) observations of player conditioned_player.

Kwargs:

batch_size (optional): int, the “inner”batch_size to draw - i.e. how many conditional samples to draw for each provided conditional_observation. If none provided, will use self.default_batch_size of the class.

Returns:
valuations: torch.Tensor (outer_batch_size, inner_batch_size, n_players, valuation_size):

a conditional valuation profile

observations: torch.Tensor (*`outer_batch_size`s, inner_batch_size, n_players, observation_size):

a corresponding conditional observation profile. observations[:,conditioned_observation,:] will be equal to conditioned_observation repeated batch_size times

draw_profiles(batch_sizes: Optional[Union[int, List[int]]] = None, device=None) Tuple[Tensor, Tensor][source]

Draws and returns a batch of valuation and observation profiles.

Kwargs:

batch_sizes (optional): List[int], the batch_sizes to draw. If none provided, [self.default_batch_size] will be used. device (optional): torch.cuda.Device, the device to draw profiles on

Returns:

valuations: torch.Tensor (*batch_sizes x n_players x valuation_size): a valuation profile observations: torch.Tensor (*batch_sizes x n_players x observation_size): an observation profile

class bnelearn.sampler.base.IPVSampler(n_players: int, valuation_size: int, support_bounds, default_batch_size: int = 1, default_device: Optional[Union[device, str, int]] = None)[source]

Bases: PVSampler, ABC

A sampler in Independent Private Value Settings.

NOTE: We will only use this class as an interface to perform quick checks for IPV (e.g. in FlushedWrappedSampler below). Implementation is left to subclasses.

See the module .samplers_ipv for examples.

class bnelearn.sampler.base.PVSampler(n_players: int, valuation_size: int, support_bounds, default_batch_size: int = 1, default_device: Optional[Union[device, str, int]] = None)[source]

Bases: ValuationObservationSampler, ABC

A sampler for Private Value settings, i.e. when observations and valuations are identical.

draw_profiles(batch_sizes: Optional[int] = None, device: Optional[Union[device, str, int]] = None) Tuple[Tensor, Tensor][source]

Draws and returns a batch of valuation and observation profiles.

Kwargs:

batch_sizes (optional): List[int], the batch_sizes to draw. If none provided, [self.default_batch_size] will be used. device (optional): torch.cuda.Device, the device to draw profiles on

Returns:

valuations: torch.Tensor (*batch_sizes x n_players x valuation_size): a valuation profile observations: torch.Tensor (*batch_sizes x n_players x observation_size): an observation profile

class bnelearn.sampler.base.ValuationObservationSampler(n_players, valuation_size, observation_size, support_bounds, default_batch_size=1, default_device=None)[source]

Bases: ABC

Provides functionality to draw valuation and observation profiles.

abstract draw_conditional_profiles(conditioned_player: int, conditioned_observation: Tensor, inner_batch_size: int, device: Optional[Union[device, str, int]] = None) Tuple[Tensor, Tensor][source]

Draws and returns batches conditional valuation and corresponding observation profile. For each entry of conditioned_observation, batch_size samples will be drawn!

Note that here, we are returning full profiles instead (including conditioned_player’s observation and others’ valuations.)

Args:
conditioned_player: int

Index of the player whose observation we are conditioning on.

conditioned_observation: torch.Tensor (*outer_batch_sizes (implicit), observation_size)

A (batch of) observations of player conditioned_player.

Kwargs:

batch_size (optional): int, the “inner”batch_size to draw - i.e. how many conditional samples to draw for each provided conditional_observation. If none provided, will use self.default_batch_size of the class.

Returns:
valuations: torch.Tensor (outer_batch_size, inner_batch_size, n_players, valuation_size):

a conditional valuation profile

observations: torch.Tensor (*`outer_batch_size`s, inner_batch_size, n_players, observation_size):

a corresponding conditional observation profile. observations[:,conditioned_observation,:] will be equal to conditioned_observation repeated batch_size times

abstract draw_profiles(batch_sizes: Optional[Union[int, List[int]]] = None, device=None) Tuple[Tensor, Tensor][source]

Draws and returns a batch of valuation and observation profiles.

Kwargs:

batch_sizes (optional): List[int], the batch_sizes to draw. If none provided, [self.default_batch_size] will be used. device (optional): torch.cuda.Device, the device to draw profiles on

Returns:

valuations: torch.Tensor (*batch_sizes x n_players x valuation_size): a valuation profile observations: torch.Tensor (*batch_sizes x n_players x observation_size): an observation profile

generate_action_grid(player_position: int, minimum_number_of_points: int, dtype=torch.float32, device=None) Tensor[source]

As the grid is also used for finding best responses, some samplers need extensive grids that sample a broader area. (E.g. when a bidder with high valuations massively shads her bids.)

generate_cell_partition(player_position: int, grid_size: int, dtype=torch.float32, device=None)[source]

Generate a rectangular grid partition of the valuation/observation prior and return cells with their vertices.

generate_reduced_grid(player_position: int, minimum_number_of_points: int, dtype=torch.float32, device=None) Tensor[source]

For some samplers, the action dimension is smaller and the grid can be reduced to that lower dimension.

generate_valuation_grid(player_position: int, minimum_number_of_points: int, dtype=torch.float32, device=None, support_bounds: Optional[Tensor] = None, return_mesh: bool = False) Tensor[source]

Generates an evenly spaced grid of (approximately and at least) minimum_number_of_points valuations covering the support of the valuation space for the given player. These are meant as rational actions for the player to evaluate, e.g. in the util_loss estimator.

The default reference implementation returns a rectangular grid on [0, upper_bound] x valuation_size.

bnelearn.sampler.samplers_correlated_pv module

This module implements samplers for correlated private values settings.

class bnelearn.sampler.samplers_correlated_pv.BernoulliWeightsCorrelatedSymmetricUniformPVSampler(n_players: int, valuation_size: int, correlation: float, u_lo: float = 0.0, u_hi: float = 1.0, default_batch_size=1, default_device: Optional[Union[device, str, int]] = None)[source]

Bases: CorrelatedSymmetricUniformPVSampler

draw_conditional_profiles(conditioned_player: int, conditioned_observation: Tensor, inner_batch_size: int, device: Optional[Union[device, str, int]] = None) Tuple[Tensor, Tensor][source]

Draws and returns batches conditional valuation and corresponding observation profile. For each entry of conditioned_observation, batch_size samples will be drawn!

Note that here, we are returning full profiles instead (including conditioned_player’s observation and others’ valuations.)

Args:
conditioned_player: int

Index of the player whose observation we are conditioning on.

conditioned_observation: torch.Tensor (*outer_batch_sizes (implicit), observation_size)

A (batch of) observations of player conditioned_player.

Kwargs:

batch_size (optional): int, the “inner”batch_size to draw - i.e. how many conditional samples to draw for each provided conditional_observation. If none provided, will use self.default_batch_size of the class.

Returns:
valuations: torch.Tensor (outer_batch_size, inner_batch_size, n_players, valuation_size):

a conditional valuation profile

observations: torch.Tensor (*`outer_batch_size`s, inner_batch_size, n_players, observation_size):

a corresponding conditional observation profile. observations[:,conditioned_observation,:] will be equal to conditioned_observation repeated batch_size times

class bnelearn.sampler.samplers_correlated_pv.ConstantWeightCorrelatedSymmetricUniformPVSampler(n_players: int, valuation_size: int, correlation: float, u_lo: float = 0.0, u_hi: float = 1.0, default_batch_size=1, default_device: Optional[Union[device, str, int]] = None)[source]

Bases: CorrelatedSymmetricUniformPVSampler

draw_conditional_profiles(conditioned_player: int, conditioned_observation: Tensor, inner_batch_size: int, device: Optional[Union[device, str, int]] = None) Tuple[Tensor, Tensor][source]

Draws and returns batches conditional valuation and corresponding observation profile. For each entry of conditioned_observation, batch_size samples will be drawn!

Note that here, we are returning full profiles instead (including conditioned_player’s observation and others’ valuations.)

Args:
conditioned_player: int

Index of the player whose observation we are conditioning on.

conditioned_observation: torch.Tensor (*outer_batch_sizes (implicit), observation_size)

A (batch of) observations of player conditioned_player.

Kwargs:

batch_size (optional): int, the “inner”batch_size to draw - i.e. how many conditional samples to draw for each provided conditional_observation. If none provided, will use self.default_batch_size of the class.

Returns:
valuations: torch.Tensor (outer_batch_size, inner_batch_size, n_players, valuation_size):

a conditional valuation profile

observations: torch.Tensor (*`outer_batch_size`s, inner_batch_size, n_players, observation_size):

a corresponding conditional observation profile. observations[:,conditioned_observation,:] will be equal to conditioned_observation repeated batch_size times

class bnelearn.sampler.samplers_correlated_pv.CorrelatedSymmetricUniformPVSampler(u_lo: float, u_hi: float, n_players: int, valuation_size: int, correlation: float, weight_method, default_batch_size=1, default_device: Optional[Union[device, str, int]] = None)[source]

Bases: PVSampler, ABC

Draws (non-independent) symmetric uniform valuation profiles that are pairwise correlated between the bidders according to the models from Ausubel & Baranov (2019) (https://doi.org/10.1007/s00182-019-00691-3).

Use subclasses BernoulliWeightsCorrelatedSymmetricUniformPVSampler or ConstantWeightsCorrelatedSymmetricUniformPVSampler to initialize.

Individual valuations v_i are composed additively of an individual component \(z_i\) and a common component \(s\), where \(z_i, s\) are each uniform.

\[v_i = (1-w) z_i + w s\]

weights are set according to either the ‘Bernoulli Weights Model’ or ‘Constant Weights Model’.

In this scheme, a Bernoulli (0 or 1) weight determines that either \(v_i = z_i\) or \(v_i = s\), with weights/probabilities being set such that correlation \(\gamma\) is achieved between bidders.

class bnelearn.sampler.samplers_correlated_pv.LLGFullSampler(correlation=0.0, correlation_method=None, default_batch_size=1, default_device=None)[source]

Bases: LLGSampler

A sampler for the LLG full setting.

generate_action_grid(player_position: int, minimum_number_of_points: int, dtype=torch.float32, device=None, support_bounds=None) Tensor[source]

Here, the grid needs to be three dimensional and the support bounds need to be wider.

generate_reduced_grid(player_position: int, minimum_number_of_points: int, dtype=torch.float32, device=None, support_bounds=None) Tensor[source]

Here, the grid can be one dimensional, as bidders are single-minded.

generate_valuation_grid(player_position: int, minimum_number_of_points: int, dtype=torch.float32, device=None, support_bounds=None) Tensor[source]

Here, the grid can be one dimensional, as bidders are single-minded. Also has mesh funtionallity for creation of grid cells.

class bnelearn.sampler.samplers_correlated_pv.LLGSampler(correlation=0.0, correlation_method=None, default_batch_size=1, default_device=None)[source]

Bases: LocalGlobalCompositePVSampler

A sampler for the LLG settings in Ausubel & Baranov.

Args:
correlation (float), correlation coefficient between local bidders,

takes values in [0.0, 1.0]

correlation_method (str or None, default: None): The type of correlation

model. For correlation > 0.0, must be one of ‘Bernoulli’ or ‘constant’

class bnelearn.sampler.samplers_correlated_pv.LLLLGGSampler(correlation_locals=0.0, correlation_method_locals=None, default_batch_size=1, default_device=None)[source]

Bases: LocalGlobalCompositePVSampler

A sampler for the LLLLGG settings in Bosshard et al (2020).

Note: while the auction is for 6 players and 8 items, our auction implementation uses symmetries and

encodes each player’s valuations with a valuation_size of 2.

Args:
correlation_locals (float), correlation coefficient between local bidders,

takes values in [0.0, 1.0]

correlation_method_locals (str or None, default: None): The type of correlation

model. For correlation > 0.0, must be one of ‘Bernoulli’ or ‘constant’

class bnelearn.sampler.samplers_correlated_pv.LLLLRRGSampler(correlation_locals=0.0, correlation_method_locals=None, correlation_regionals=0.0, correlation_method_regionals=None, default_batch_size=1, default_device=None)[source]

Bases: CompositeValuationObservationSampler

Setting with three groups of players: The local players (L’s) have symmetric (possibly correlated) uniform valuations on [0,1]. The regional (R) bidders have symmetric (possibly correlated) uniform valuations on [0,2]. The global (G) bidder has a valuation

class bnelearn.sampler.samplers_correlated_pv.LocalGlobalCompositePVSampler(n_locals: int, n_globals: int, valuation_size: int, correlation_locals=0.0, correlation_method_locals=None, correlation_globals=0.0, correlation_method_globals=None, default_batch_size=1, default_device=None)[source]

Bases: CompositeValuationObservationSampler

Settings with two groups of players: The local players have symmetric (possibly correlated) uniform valuations on [0,1]. The global bidders have symmetric (possibly correlated) uniform valuations on [0,2].

bnelearn.sampler.samplers_ipv module

This module implements samplers for independent-private value auction settings.

Note that all samplers in this class should implement the IPVSampler interface from .base. Elsewhere in the implementation, we use instancechecks against IPVSampler in order to use functionality that is only available in independent settings, e.g. when drawing samples from conditional distributions.

class bnelearn.sampler.samplers_ipv.BetaSymmetricIPVSampler(alpha: float, beta: float, n_players: int, valuation_size: int, default_batch_size: int, default_device: Optional[Union[device, str, int]] = None)[source]

Bases: SymmetricIPVSampler

An IPV sampler with symmetric Beta priors.

class bnelearn.sampler.samplers_ipv.FixedManualIPVSampler(valuation_tensor: Tensor)[source]

Bases: IPVSampler

For testing purposes: A sampler that returns a fixed tensor as valuations/observations.

class bnelearn.sampler.samplers_ipv.GaussianSymmetricIPVSampler(mean, stddev, n_players, valuation_size, default_batch_size, default_device: Optional[Union[device, str, int]] = None)[source]

Bases: SymmetricIPVSampler

An IPV sampler with symmetric Gaussian priors.

class bnelearn.sampler.samplers_ipv.MultiUnitValuationObservationSampler(n_players: int, n_items: int = 1, max_demand: Optional[int] = None, constant_marginal_values: bool = False, u_lo: float = 0.0, u_hi: float = 1.0, default_batch_size: int = 1, default_device=None)[source]

Bases: UniformSymmetricIPVSampler

Sampler for Multi-Unit, private value settings. Sampler for valuations and signals in Multi-Unit Auctions, following Krishna, Chapter 13.

These are symmetric private value settings, where

  • valuations are descending along the valuation_size dimension and represent the marginal utility of winning an additional item.

  • bidders may be limited to be interested in at most a certain number of items.

generate_cell_partition(player_position: int, grid_size: int, dtype=torch.float32, device=None)[source]

Generate a rectangular grid partition of the valuation/observation prior and return cells with their vertices.

generate_valuation_grid(player_position: int, minimum_number_of_points: int, dtype=torch.float32, device=None, support_bounds: Optional[Tensor] = None, return_mesh: bool = False) Tensor[source]

Generates an evenly spaced grid of (approximately and at least) minimum_number_of_points valuations covering the support of the valuation space for the given player. These are meant as rational actions for the player to evaluate, e.g. in the util_loss estimator.

The default reference implementation returns a rectangular grid on [0, upper_bound] x valuation_size.

class bnelearn.sampler.samplers_ipv.SplitAwardValuationObservationSampler(efficiency_parameter: float, **kwargs)[source]

Bases: UniformSymmetricIPVSampler

Sampler for Split-Award, private value settings. Here bidders have two valuations of which one is a linear combination of the other.

generate_action_grid(player_position: int, minimum_number_of_points: int, dtype=torch.float32, device=None) Tensor[source]

From zero to some maximal value. Here, unlike in the other methods, the two outputs must not be linearly dependent.

generate_valuation_grid(player_position: int, minimum_number_of_points: int, dtype=torch.float32, device=None, support_bounds: Optional[Tensor] = None, return_mesh: bool = False) Tensor[source]

Generates an evenly spaced grid of (approximately and at least) minimum_number_of_points valuations covering the support of the valuation space for the given player. These are meant as rational actions for the player to evaluate, e.g. in the util_loss estimator.

The default reference implementation returns a rectangular grid on [0, upper_bound] x valuation_size.

class bnelearn.sampler.samplers_ipv.SymmetricIPVSampler(distribution: Distribution, n_players: int, valuation_size: int = 1, default_batch_size: int = 1, default_device: Optional[Union[device, str, int]] = None)[source]

Bases: IPVSampler

A Valuation Oracle that draws valuations independently and symmetrically for all players and each entry of their valuation vector according to a specified distribution.

This base class works with all torch.distributions but requires sampling on cpu then moving to the device. When using cuda, use the faster, distribution-specific subclasses instead where provided.

UPPER_BOUND_QUARTILE_IF_UNBOUNDED = 0.999
draw_conditional_profiles(conditioned_player: int, conditioned_observation: Tensor, inner_batch_size: int, device: Optional[Union[device, str, int]] = None) Tuple[Tensor, Tensor][source]

Draws and returns batches conditional valuation and corresponding observation profile. For each entry of conditioned_observation, batch_size samples will be drawn!

Note that here, we are returning full profiles instead (including conditioned_player’s observation and others’ valuations.)

Args:
conditioned_player: int

Index of the player whose observation we are conditioning on.

conditioned_observation: torch.Tensor (*outer_batch_sizes (implicit), observation_size)

A (batch of) observations of player conditioned_player.

Kwargs:

batch_size (optional): int, the “inner”batch_size to draw - i.e. how many conditional samples to draw for each provided conditional_observation. If none provided, will use self.default_batch_size of the class.

Returns:
valuations: torch.Tensor (outer_batch_size, inner_batch_size, n_players, valuation_size):

a conditional valuation profile

observations: torch.Tensor (*`outer_batch_size`s, inner_batch_size, n_players, observation_size):

a corresponding conditional observation profile. observations[:,conditioned_observation,:] will be equal to conditioned_observation repeated batch_size times

class bnelearn.sampler.samplers_ipv.UniformSymmetricIPVSampler(lo, hi, n_players, valuation_size, default_batch_size, default_device: Optional[Union[device, str, int]] = None)[source]

Bases: SymmetricIPVSampler

An IPV sampler with symmetric Uniform priors.

default_batch_size: int
default_device: Optional[Union[device, str, int]]
n_players: int
observation_size: int
support_bounds: FloatTensor
valuation_size: int
bnelearn.sampler.samplers_non_pv module

This module implements samplers that do not adhere to the private values setting.

class bnelearn.sampler.samplers_non_pv.AffiliatedValuationObservationSampler(n_players: int, valuation_size: int = 1, u_lo: float = 0.0, u_hi: float = 1.0, default_batch_size: int = 1, default_device=None)[source]

Bases: ValuationObservationSampler

The ‘Affiliated Values Model’ model. (Krishna 2009, Example 6.2). This is a private values model.

Two bidders have signals

\[\]

o_i = z_i + s

and valuations .. math:: v_i = s + (z_1+z_2)/2 = mean_i(o_i)

where z_i and s are i.i.d. standard uniform.

draw_conditional_profiles(conditioned_player: int, conditioned_observation: Tensor, inner_batch_size: int, device: Optional[Union[device, str, int]] = None) Tuple[Tensor, Tensor][source]

Draws and returns batches conditional valuation and corresponding observation profile. For each entry of conditioned_observation, batch_size samples will be drawn!

Note that here, we are returning full profiles instead (including conditioned_player’s observation and others’ valuations.)

Args:
conditioned_player: int

Index of the player whose observation we are conditioning on.

conditioned_observation: torch.Tensor (*outer_batch_sizes (implicit), observation_size)

A (batch of) observations of player conditioned_player.

Kwargs:

batch_size (optional): int, the “inner”batch_size to draw - i.e. how many conditional samples to draw for each provided conditional_observation. If none provided, will use self.default_batch_size of the class.

Returns:
valuations: torch.Tensor (outer_batch_size, inner_batch_size, n_players, valuation_size):

a conditional valuation profile

observations: torch.Tensor (*`outer_batch_size`s, inner_batch_size, n_players, observation_size):

a corresponding conditional observation profile. observations[:,conditioned_observation,:] will be equal to conditioned_observation repeated batch_size times

draw_profiles(batch_sizes: Optional[List[int]] = None, device=None) Tuple[Tensor, Tensor][source]

Draws and returns a batch of valuation and observation profiles.

Kwargs:

batch_sizes (optional): List[int], the batch_sizes to draw. If none provided, [self.default_batch_size] will be used. device (optional): torch.cuda.Device, the device to draw profiles on

Returns:

valuations: torch.Tensor (*batch_sizes x n_players x valuation_size): a valuation profile observations: torch.Tensor (*batch_sizes x n_players x observation_size): an observation profile

class bnelearn.sampler.samplers_non_pv.MineralRightsValuationObservationSampler(n_players: int, valuation_size: int = 1, common_value_lo: float = 0.0, common_value_hi: float = 1.0, default_batch_size: int = 1, default_device=None)[source]

Bases: ValuationObservationSampler

The ‘Mineral Rights’ model is a common value model: There is a uniformly distributed common value of the item(s), each agent’s observation is then uniformly drawn from U[0,2v]. See Kishna (2009), Example 6.1

draw_conditional_profiles(conditioned_player: int, conditioned_observation: Tensor, inner_batch_size: int, device: Optional[Union[device, str, int]] = None) Tuple[Tensor, Tensor][source]

Draws and returns batches conditional valuation and corresponding observation profile. For each entry of conditioned_observation, batch_size samples will be drawn!

Note that here, we are returning full profiles instead (including conditioned_player’s observation and others’ valuations.)

Args:
conditioned_player: int

Index of the player whose observation we are conditioning on.

conditioned_observation: torch.Tensor (*outer_batch_sizes (implicit), observation_size)

A (batch of) observations of player conditioned_player.

Kwargs:

batch_size (optional): int, the “inner”batch_size to draw - i.e. how many conditional samples to draw for each provided conditional_observation. If none provided, will use self.default_batch_size of the class.

Returns:
valuations: torch.Tensor (outer_batch_size, inner_batch_size, n_players, valuation_size):

a conditional valuation profile

observations: torch.Tensor (*`outer_batch_size`s, inner_batch_size, n_players, observation_size):

a corresponding conditional observation profile. observations[:,conditioned_observation,:] will be equal to conditioned_observation repeated batch_size times

draw_profiles(batch_sizes: Optional[List[int]] = None, device=None) Tuple[Tensor, Tensor][source]

Draws and returns a batch of valuation and observation profiles.

Kwargs:

batch_sizes (optional): List[int], the batch_sizes to draw. If none provided, [self.default_batch_size] will be used. device (optional): torch.cuda.Device, the device to draw profiles on

Returns:

valuations: torch.Tensor (*batch_sizes x n_players x valuation_size): a valuation profile observations: torch.Tensor (*batch_sizes x n_players x observation_size): an observation profile

generate_valuation_grid(player_position: int, minimum_number_of_points: int, dtype=torch.float32, device=None, support_bounds: Optional[Tensor] = None) Tensor[source]

This setting needs larger bounds for the grid.

Module contents
bnelearn.tests package
Subpackages
bnelearn.tests.test_samplers package
Submodules
bnelearn.tests.test_samplers.test_affiliated_value module

This pytest test file checks whether valuation and observation samplers have the expected behaviour

bnelearn.tests.test_samplers.test_affiliated_value.test_affiliated_values(n_players, valuation_size, u_lo, u_hi)[source]

Test the Affiliated Values Sampler.

bnelearn.tests.test_samplers.test_composite_samplers module

This pytest test file checks whether valuation and observation samplers have the expected behaviour

bnelearn.tests.test_samplers.test_composite_samplers.test_local_global_samplers(setting, method, gamma)[source]

Test whether the LLG sampler works as expected.

bnelearn.tests.test_samplers.test_correlated_pv module

This pytest test file checks whether valuation and observation samplers have the expected behavior.

bnelearn.tests.test_samplers.test_correlated_pv.check_validity(valuation_profile, expected_shape, expected_mean, expected_std, expected_correlation=None)[source]

Checks whether a given batch of profiles has expected shape, mean, std and correlation matrix.

bnelearn.tests.test_samplers.test_correlated_pv.check_validity_of_conditional_sampler(sampler: CorrelatedSymmetricUniformPVSampler, n_players, valuation_size, u_lo, u_hi)[source]

Check runtime at minimum, maximum, midpoint inputs, as well as shapes, devices and known entries.

bnelearn.tests.test_samplers.test_correlated_pv.correlation(valuation_profile)[source]

Pearson correlation between valuations of bidders.

valuation_profile should be (batch x n_players x 1)

bnelearn.tests.test_samplers.test_correlated_pv.test_correlated_Bernoulli_weight_pv(n_players, valuation_size, gamma, u_lo, u_hi)[source]

Functionality and correctness test of the Bernoulli Weights sampler. We test

  • correctness of sample on standard device with standard batch_size

    • dimensions and output devices

    • ipv, i.e. valuations == observations

    • correctness of mean, std (where known) of marginals

    • correlation matrix

  • conditioned sampling on one player’s observation

    • has correct shapes and devices

    • has correct entries for the given player

    • otherwise looks like a valid sample

  • additionally, we test dimensions and output devices for manually specified devises or batch_sizes.

bnelearn.tests.test_samplers.test_correlated_pv.test_correlated_constant_weight_pv(n_players, valuation_size, gamma, u_lo, u_hi)[source]

Functionality and correctness test of the Constant Weights sampler. We test

  • correctness of sample on standard device with standard batch_size * dimensions and output devices * ipv, i.e. valuations == observations * correctness of mean, std (where known) of marginals * correlation matrix

  • conditioned sampling on one player’s observation * has correct shapes and devices * has correct entries for the given player * otherwise looks like a valid sample

  • additionally, we test dimensions and output devices for manually specified devises or batch_sizes.

bnelearn.tests.test_samplers.test_ipv module

This pytest test file checks whether valuation and observation samplers have the expected behaviour

bnelearn.tests.test_samplers.test_ipv.check_validity(valuation_profile, expected_shape, expected_mean, expected_std, expected_correlation=None)[source]

Checks whether a given batch of profiles has expected shape, mean, std and correlation matrix.

bnelearn.tests.test_samplers.test_ipv.correlation(valuation_profile)[source]

Pearson correlation between valuations of bidders.

valuation_profile should be (batch x n_players x 1)

bnelearn.tests.test_samplers.test_ipv.test_gaussian_symmetric_ipv()[source]

Test the GaussianSymmetricIPVSampler.

bnelearn.tests.test_samplers.test_ipv.test_uniform_symmetric_ipv()[source]

Test the UniformSymmetricIPVSampler.

bnelearn.tests.test_samplers.test_mineral_rights module

This pytest test file checks whether valuation and observation samplers have the expected behaviour

bnelearn.tests.test_samplers.test_mineral_rights.test_mineral_rights(n_players, valuation_size, u_lo, u_hi)[source]

Test the Mineral Rights Sampler.

bnelearn.tests.test_samplers.test_multi_unit module

This pytest test file checks whether valuation and observation samplers have the expected behaviour

bnelearn.tests.test_samplers.test_multi_unit.test_uniform_symmetric_ipv(n_players, n_items, max_demand, u_lo, u_hi)[source]

Test the UniformSymmetricIPVSampler.

Module contents
Submodules
bnelearn.tests.conftest module

This module defines pytest fixtures and sets constants to be used in test files.

bnelearn.tests.conftest.check_gurobi()[source]
bnelearn.tests.test_auction_environment module

This module tests whether rewards can be calculated correctly in an environment.

bnelearn.tests.test_auction_environment.strat_to_bidder(strategy, batch_size, player_position=0)[source]

creates a bidder from a strategy

bnelearn.tests.test_auction_environment.test_auction_environment()[source]
bnelearn.tests.test_auction_learning module

Test auction learning in symmetric and asymmetric implementations, using a 2p-FPSB setup.

This script tests

  • whether the loop runs without runtime exceptions for a small number of iterations

  • whether the model learnt the appropriate bid for the top-range of valuations (this value is expected to be learned _very_ fast as it’s most significant and as such should always be found (up to a certain range) even in a short amount of time)

  • Further, the script tests whether the utility after 200 iterations is in the expected range, if it isn’t it won’t fail but issue a warning (because this might just be due to stochasticity as it would take a significantly longer test time / more iterations to make sure.)

bnelearn.tests.test_auction_learning.strat_to_bidder(strategy, batch_size, player_position=None)[source]
bnelearn.tests.test_auction_learning.test_learning_in_fpsb_environment()[source]

Tests the same setting as above (2p FPSB symmetric uniform), but with a fixed-environment implementation. (2 named agents with a shared model.)

bnelearn.tests.test_bne_database module

Testing correctness of the BNE utilities database.

bnelearn.tests.test_bne_database.test_bne_utility_database()[source]

Testing correctness of the BNE utilities database.

bnelearn.tests.test_combinatorial_auctions module

Testing correctness of LLLLGG combinatorial auction implementations.

bnelearn.tests.test_combinatorial_auctions.run_combinatorial_test(rule, device, bids, bundle, expected_allocation, expected_VCG_payments)[source]

Run correctness test for a given LLLLGG rule

bnelearn.tests.test_combinatorial_auctions.test_combinatorial(rule, bids, bundles, expected_allocation, expected_payments, check_gurobi)[source]

Tests allocation and payments in combinatorial auctions

bnelearn.tests.test_experiment_serialization module
bnelearn.tests.test_experiment_serialization.test_all_experiments_serialization()[source]

Checks all types of experiments are serialized and deserialized properly with default parameters

bnelearn.tests.test_learners module

This module tests implemented learner in a ‘static’ environment.

bnelearn.tests.test_learners.set_up_environment(mechanism, batch_size: int = 262144)[source]
bnelearn.tests.test_learners.strat_to_bidder(strategy, batch_size, player_position=0)[source]

creates a bidder from a strategy

bnelearn.tests.test_learners.test_AESPG_learner_SGD()[source]

Tests the standard policy gradient learner in static env. This does not test complete convergence but ‘running in the right direction’.

bnelearn.tests.test_learners.test_ES_learner_SGD()[source]

Tests ES PG learner with SGD optimizer in static environment. This does not test complete convergence but ‘running in the right direction’.

bnelearn.tests.test_learners.test_PG_learner_SGD()[source]

Tests the standard policy gradient learner in static env. This does not test complete convergence but ‘running in the right direction’.

bnelearn.tests.test_learners.test_PSO_learner_SGD()[source]

Tests ES PG learner with SGD optimizer in static environment. This does not test complete convergence but ‘running in the right direction’.

bnelearn.tests.test_learners.test_static_mechanism()[source]

Test whether the mechanism for testing the optimizers returns expected results

bnelearn.tests.test_llg_auctions module

Testing correctness of LLG combinatorial auction implementations.

bnelearn.tests.test_llg_auctions.run_llg_test(rule, device, expected_payments)[source]

Run correctness test for a given llg rule on given device

bnelearn.tests.test_llg_auctions.test_LLG_first_price()[source]

FP should run on CPU and GPU and return expected results.

bnelearn.tests.test_llg_auctions.test_LLG_full()[source]

LLG setting with complete combinatrial (3d) bids.

bnelearn.tests.test_llg_auctions.test_LLG_nearest_bid()[source]

LLG with nearest-bid rule should run on CPU and GPU and return expected results.

bnelearn.tests.test_llg_auctions.test_LLG_nearest_vcg()[source]

LLG with nearest-VCG rule should run on CPU and GPU and return expected results.

bnelearn.tests.test_llg_auctions.test_LLG_proxy()[source]

LLG with proxy rule should run on CPU and GPU and return expected results.

bnelearn.tests.test_llg_auctions.test_LLG_vcg()[source]

LLG with VCG rule should run on CPU and GPU and return expected results.

bnelearn.tests.test_llllgg_auctions module

Testing correctness of LLLLGG combinatorial auction implementations.

bnelearn.tests.test_llllgg_auctions.run_LLLLGG_test(parallel, rule, device, bids, expected_allocation, expected_payments, solver)[source]

Run correctness test for a given LLLLGG rule

bnelearn.tests.test_llllgg_auctions.test_LLLLGG(parallel, rule, bids, expected_allocation, expected_payments)[source]

Testing batch_size > 1, VCG 0 prices, FP, global/local winning

bnelearn.tests.test_llllgg_auctions.test_LLLLGG_gurobi(parallel, rule, bids, expected_allocation, expected_payments, check_gurobi)[source]

Testing batch_size > 1, VCG 0 prices, FP, global/local winning

bnelearn.tests.test_llllgg_core_solver_comp module

Testing for identical results from solvers for the LLLLGG combinatorial auction implementations.

bnelearn.tests.test_llllgg_core_solver_comp.run_LLLLGG_test(parallel, rule, bids, device, solver_1, solver_2)[source]

Run comparison test for different solvers.

bnelearn.tests.test_llllgg_core_solver_comp.test_LLLLGG_solver_identical_results(parallel, rule, bids, device, check_gurobi)[source]

Testing batch_size > 1, VCG 0 prices, FP, global/local winning

bnelearn.tests.test_market_outcomes module

This module tests the calculation of market outcomes.

bnelearn.tests.test_market_outcomes.run_efficiency_test(experiment_type=<class 'str'>, setting_params=<class 'dict'>, true_efficiency=<class 'float'>)[source]

Test the calculation of efficiency for general auction markets

bnelearn.tests.test_market_outcomes.test_efficiency(experiment_type, setting_params, true_efficiency)[source]
bnelearn.tests.test_market_outcomes.test_revenue()[source]

Test the calculation of revenue for general auction markets

bnelearn.tests.test_matrix_FP module
bnelearn.tests.test_matrix_FP.init_setup(game, strategy, initial_beliefs)[source]
bnelearn.tests.test_matrix_FP.strat_to_player(strategy, batch_size, player_position=None)[source]
bnelearn.tests.test_matrix_FP.test_FictitiousPlayMixedStrategy_BoS()[source]
bnelearn.tests.test_matrix_FP.test_FictitiousPlayMixedStrategy_MP()[source]
bnelearn.tests.test_matrix_FP.test_FictitiousPlayMixedStrategy_PD()[source]
bnelearn.tests.test_matrix_FP.test_FictitiousPlaySmoothStrategy_BoS()[source]
bnelearn.tests.test_matrix_FP.test_FictitiousPlaySmoothStrategy_MP()[source]
bnelearn.tests.test_matrix_FP.test_FictitiousPlaySmoothStrategy_PD()[source]
bnelearn.tests.test_matrix_FP.test_FictitiousPlayStrategy_BoS()[source]

initial_beliefs = [None] * 2 #initial_beliefs[0] = torch.tensor([[0.8308,0.5793],[0.4064,0.4113]], device=device) <- converges #initial_beliefs[1] = torch.tensor([[0.2753,0.4043],[0.1596,0.6916]], device=device) <- converges

#initial_beliefs[0] = torch.tensor([[0.5892,0.4108],[0.4970,0.5030]], device=device) #<- converges #initial_beliefs[1] = torch.tensor([[0.4051,0.5949],[0.1875,0.8125]], device=device) #<- converges

#initial_beliefs[0] = torch.tensor([[0.59,0.41],[0.49,0.51]], device=device) #<- converges #initial_beliefs[1] = torch.tensor([[0.41,0.59],[0.19,0.81]], device=device) #<- converges

#initial_beliefs[0] = torch.tensor([[0.59,0.41],[0.49,0.51]], device=device) #<- converges #initial_beliefs[1] = torch.tensor([[0.59,0.41],[0.49,0.51]], device=device) #<- converges

#initial_beliefs[0] = torch.tensor([[0.59,0.41],[0.41,0.59]], device=device) #<- converges #initial_beliefs[1] = torch.tensor([[0.59,0.41],[0.41,0.59]], device=device) #<- converges

#initial_beliefs[0] = torch.tensor([[59.5,40.5],[40.5,59.5]], device=device) #<- converges #initial_beliefs[1] = torch.tensor([[59.5,40.5],[40.5,59.5]], device=device) #<- converges

#initial_beliefs[0] = torch.tensor([[59,41],[49,51]], device=device) #<- doesn’t converge #initial_beliefs[1] = torch.tensor([[41,59],[19,81]], device=device) #<- doens’t converge

#initial_beliefs[0] = torch.tensor([[0.6,0.4],[0.5,0.5]], device=device) #<- doesn’t converge #initial_beliefs[1] = torch.tensor([[0.4,0.6],[0.1875,0.8125]], device=device) #<- doesn’t converge

#initial_beliefs[0] = torch.tensor([[0.6,0.4],[0.5,0.5]], device=device) #<- doesn’t converge #initial_beliefs[1] = torch.tensor([[0.4,0.6],[0.2,0.8]], device=device) #<- doesn’t converge

#initial_beliefs = torch.tensor([[60,41],[41,60]], device=device) #<- doesn’t converge #initial_beliefs[1] = torch.tensor([[60,41],[41,60]], device=device) #<- doesn’t converge

# -> It converges if the init is very close to MNE play for at least one player but not exactly! # -> My hypotheses: it has to be close to cycle. If it is exact, # it is indifferent and takes a random direction, diverging away. # -> $$ The question now is whether we should/have track historical actions with integer!? # -> No. In Fudenberg (1999) - Learning and Equilirbium, p. 389 # they init FP with (1,sqrt(2)), so obviously use float as well.

bnelearn.tests.test_matrix_FP.test_FictitiousPlayStrategy_MP()[source]
bnelearn.tests.test_matrix_FP.test_FictitiousPlayStrategy_PD()[source]
bnelearn.tests.test_matrix_FP.train(epochs, players, strats, tau_update=1, tau=0.99, tau_minimum=0.0001)[source]
bnelearn.tests.test_matrix_game_training module

Test whether agent training in simple matrix games works.

bnelearn.tests.test_matrix_game_training.test_prisoners_dilemma_training_separate_models()[source]

Tests training in MatrixGameEnvironment with unique models for both players.

bnelearn.tests.test_matrix_game_training.test_prisoners_dilemma_training_shared_model()[source]

Tests training in MatrixGameEnvironment with a shared model between players.

bnelearn.tests.test_matrix_games module
bnelearn.tests.test_matrix_games.test_invalid_actions_float()[source]
bnelearn.tests.test_matrix_games.test_invalid_actions_out_of_bounds()[source]
bnelearn.tests.test_matrix_games.test_invalid_actions_shape()[source]
bnelearn.tests.test_matrix_games.test_mixed_strategy_invalid_action_probabilities()[source]
bnelearn.tests.test_matrix_games.test_mixed_strategy_invalid_action_shape()[source]
bnelearn.tests.test_matrix_games.test_mixed_strategy_playing_2p()[source]

Test in Prisoner’s Dilemma

bnelearn.tests.test_matrix_games.test_mixed_strategy_playing_3p()[source]
bnelearn.tests.test_matrix_games.test_output_correctness_2x2()[source]
bnelearn.tests.test_matrix_games.test_output_correctness_2x3()[source]

2 player 3 action game: Rock Paper Scissors

bnelearn.tests.test_matrix_games.test_output_correctness_3x2()[source]

3 player 2 action game: Jordan Anticoordination game.

bnelearn.tests.test_matrix_games.test_output_on_cpu()[source]

Test game that has cuda=False

bnelearn.tests.test_matrix_games.test_output_on_gpu()[source]

If the game has cuda=True, outputs should be on gpu regardless of input.

bnelearn.tests.test_matrix_games.test_output_shapes()[source]
bnelearn.tests.test_multi_unit_auctions module

Testing correctness of auction implementations.

bnelearn.tests.test_multi_unit_auctions.test_mida_correctness()[source]

Test of allocation and payments in MultiUnitDiscriminatoryAuction.

bnelearn.tests.test_multi_unit_auctions.test_miup_correctness()[source]

Test of allocation and payments in MultiUnitUniformPriceAuction.

bnelearn.tests.test_multi_unit_auctions.test_miva_correctness()[source]

Test of allocation and payments in MultiUnitVickreyAuction.

bnelearn.tests.test_reverse_auctions module

Testing correctness of reverse auction implementations.

bnelearn.tests.test_reverse_auctions.test_fpsbsaa_correctness()[source]

Test of allocation and payments in First-price sealed-bid split-award auction.

bnelearn.tests.test_single_item_auctions module

Testing correctness of auction implementations.

bnelearn.tests.test_single_item_auctions.test_allpay_correctness()[source]

Thirdprice should return correct allocations and payments.

bnelearn.tests.test_single_item_auctions.test_allpay_illegal_arguments()[source]

Illegal bid tensors should cause exceptions

bnelearn.tests.test_single_item_auctions.test_fpsb_correctness()[source]

FPSB should return correct allocations and payments.

bnelearn.tests.test_single_item_auctions.test_fpsb_illegal_arguments()[source]

Illegal bid tensors should cause exceptions

bnelearn.tests.test_single_item_auctions.test_thirdprice_correctness()[source]

Thirdprice should return correct allocations and payments.

bnelearn.tests.test_single_item_auctions.test_thirdprice_illegal_arguments()[source]

Illegal bid tensors should cause exceptions

bnelearn.tests.test_single_item_auctions.test_vickrey_correctness()[source]

Vickrey should return correct allocations and payments.

bnelearn.tests.test_single_item_contests module

Testing correctness of contest implementations.

bnelearn.tests.test_single_item_contests.impact_function(x)
bnelearn.tests.test_single_item_contests.test_crowdsourcing_correctness()[source]

Crowdsourcing Contest should return correct allocations and payments.

bnelearn.tests.test_single_item_contests.test_crowdsourcing_illegal_arguments()[source]

Illegal effort tensors should cause exceptions.

bnelearn.tests.test_single_item_contests.test_tullock_correctness()[source]

Tullock Contest should return correct winning probabilities and payments.

bnelearn.tests.test_single_item_contests.test_tullock_illegal_arguments()[source]

Illegal effort tensors should cause exceptions.

bnelearn.tests.test_strategies_and_bidders module

This test file checks whether bidders and strategies have expected behaviour

bnelearn.tests.test_strategies_and_bidders.test_action_caching_with_manual_observation_change()[source]

Manually changing bidder observations should not break action caching logic.

bnelearn.tests.test_strategies_and_bidders.test_bidder_with_cached_actions()[source]

Bidder with action caching should not re-evaluate until valuations have changed.

bnelearn.tests.test_strategies_and_bidders.test_closure_strategy_basic()[source]

Closure Strategy should return expected result

bnelearn.tests.test_strategies_and_bidders.test_closure_strategy_invalid_input()[source]

Invalid closures should raise exception

bnelearn.tests.test_strategies_and_bidders.test_parallel_closure_evaluation()[source]

Parallelism of closure evaluation should work as expected.

bnelearn.tests.test_strategies_and_bidders.test_truthful_strategy()[source]

Truthful strategy should bid truthfully

bnelearn.tests.test_strategies_nn module

This test file checks whether NeuralNetStrategy initializations have the correct behavior.

bnelearn.tests.test_strategies_nn.assert_nn_initialization(input_length, output_length, hidden_nodes, device)[source]

Initializes a specific nn on a specific device.

bnelearn.tests.test_strategies_nn.test_nn_initialization(input_length, output_length, hidden_nodes)[source]

Tests whether nn init works.

bnelearn.tests.test_util_loss_estimator module

Testing correctness of util_loss estimator for a number of settings. Estimates the potential benefit of deviating from the current energy, as:

\[util\_loss(v_i) = Max_{b_i}[ E_{b_{-i}}[u(v_i,b_i,b_{-i})] ]\]
\[util\_loss\_max = Max_{v_i}[ util\_loss(v_i) ]\]
\[util\_loss\_expected = E_{v_i}[ util\_loss(v_i) ]\]
param agent:

1

param bid_profile:

\((batch\_size * n\_player * n\_items)\)

param bid_i:

\((bid\_size * n\_items)\)

return:

util_loss_max

return:

util_loss_expected

bid_i always used as val_i and only using truthful bidding

bnelearn.tests.test_util_loss_estimator.test_ex_interim_util_loss_estimator_fpsb_bne()[source]

Test the util_loss in BNE of fpsb. - ex interim util_loss should be close to zero

bnelearn.tests.test_util_loss_estimator.test_ex_interim_util_loss_estimator_splitaward_bne()[source]

Test the util_loss in BNE of fpsb split-award auction. - ex interim util_loss should be close to zero

bnelearn.tests.test_util_loss_estimator.test_ex_post_util_loss_estimator_truthful(rule, mechanism, bid_profile, bids_i, expected_util_loss)[source]

Check ex-post util loss

bnelearn.tests.test_zzz_experiment_runtime module

This file tests the run of experiments at runtime, so simply whether it technically completes the run. It chooses only 2 runs, with 3 epochs but plots and logs every period. Logging and plotting is not written to disc. It considers each implemented experiment with each payment rule. Fo each experiment no model_sharing is tested once. TODO:

  • Paul: InputLength should become obsolete Stefan: yes! @assigned Paul

  • Paul: Maybe later: Add bne metric to LLLLGG and test for failure

  • Stefan: Later: gaussian with fpsb and util_loss

bnelearn.tests.test_zzz_experiment_runtime.run_auction_test(config, exp_class, known_bne)[source]
bnelearn.tests.test_zzz_experiment_runtime.test_local_global_auctions(config, exp_class, known_bne)[source]
bnelearn.tests.test_zzz_experiment_runtime.test_multi_unit_auctions(config, exp_class, known_bne)[source]
bnelearn.tests.test_zzz_experiment_runtime.test_single_item_auctions(config, exp_class, known_bne)[source]
Module contents
bnelearn.util package
Submodules
bnelearn.util.autograd_hacks module

Library for extracting interesting quantites from autograd, see README.md

Not thread-safe because of module-level variables

Author: cybertronai @ https://github.com/cybertronai/autograd-hacks.

Notation: o: number of output classes (exact Hessian), number of Hessian samples (sampled Hessian) n: batch-size do: output dimension (output channels for convolution) di: input dimension (input channels for convolution) Hi: per-example Hessian of matmul, shaped as matrix of [dim, dim], indices have been row-vectorized Hi_bias: per-example Hessian of bias Oh, Ow: output height, output width (convolution) Kh, Kw: kernel height, kernel width (convolution)

Jb: batch output Jacobian of matmul, output sensitivity for example,class pair, [o, n, ….] Jb_bias: as above, but for bias

A, activations: inputs into current layer B, backprops: backprop values (aka Lop aka Jacobian-vector product) observed at current layer

bnelearn.util.autograd_hacks.add_hooks(model: Module) None[source]

Adds hooks to model to save activations and backprop values.

The hooks will 1. save activations into param.activations during forward pass 2. append backprops to params.backprops_list during backward pass.

Call “remove_hooks(model)” to disable this.

Args:

model:

bnelearn.util.autograd_hacks.backprop_hess(output: Tensor, hess_type: str) None[source]

Call backprop 1 or more times to get values needed for Hessian computation.

Args:

output: prediction of neural network (ie, input of nn.CrossEntropyLoss()) hess_type: type of Hessian propagation, “CrossEntropy” results in exact Hessian for CrossEntropy

Returns:

bnelearn.util.autograd_hacks.clear_backprops(model: Module) None[source]

Delete layer.backprops_list in every layer.

bnelearn.util.autograd_hacks.compute_grad1(model: Module, loss_type: str = 'mean') None[source]

Compute per-example gradients and save them under ‘param.grad1’. Must be called after loss.backprop()

Args:

model: loss_type: either “mean” or “sum” depending whether backpropped loss was averaged or summed over batch

bnelearn.util.autograd_hacks.compute_hess(model: Module) None[source]

Save Hessian under param.hess for each param in the model

bnelearn.util.autograd_hacks.disable_hooks() None[source]

Globally disable all hooks installed by this library.

bnelearn.util.autograd_hacks.enable_hooks() None[source]

the opposite of disable_hooks()

bnelearn.util.autograd_hacks.is_supported(layer: Module) bool[source]

Check if this layer is supported

bnelearn.util.autograd_hacks.remove_hooks(model: Module) None[source]

Remove hooks added by add_hooks(model)

bnelearn.util.autograd_hacks.symsqrt(a, cond=None, return_rank=False, dtype=torch.float32)[source]

Symmetric square root of a positive semi-definite matrix. See https://github.com/pytorch/pytorch/issues/25481

bnelearn.util.distribution_util module

Some utilities to work with torch.Distributions.

bnelearn.util.distribution_util.copy_dist_to_device(dist, device)[source]

A quick an dirty workaround to move torch.Distributions from one device to another.

To do so, we return a copy of the original distribution with all its tensor-valued members moved to the desired device.

Note that this will only work for the most basic distributions and will likely fail for complex or composed distribution objects. See https://github.com/pytorch/pytorch/issues/7795 for details.

bnelearn.util.integration module

Some utilities to leverage parallel computation of the types of integrals that arise in BNEs.

bnelearn.util.integration.cumulatively_integrate(f: callable, upper_bounds: tensor, lower_bound: float = 0.0, n_evaluations: int = 64)[source]

Integrate the fucntion f on the intervals [[lower_bound, upper_bounds[0], [lower_bound, upper_bounds[1], …] that sahre a common lower bound.

This function sorts the upper bounds, decomposes the integral into those between any two adjacent points in lower_bound, *upper_bounds, calculates each partial integral using pytorch’s trapezoid rule with n_evalautions sampling points per interval, then stichtes the resulting masses together to achieve the desired output. Note that this way, we can use pytorch.trapz in parallel over all domains and integrate directly on cuda, if desired.

Arguments:

f: callable, function to be integrated. upper_bounds: torch.tensor of shape (batch_size, 1) that specifies the

upper integration bounds.

lower_bound: float that specifies the lower bound of all domains. n_evaluations: int that specifies the number of function evaluations per

indivdidual interval.

Returns:

integrals: torch.tensor of shape (batch_size, 1).

bnelearn.util.logging module

This module contains utilities for logging of experiments

class bnelearn.util.logging.CustomSummaryWriter(log_dir=None, comment='', purge_step=None, max_queue=10, flush_secs=120, filename_suffix='')[source]

Bases: SummaryWriter

Extends SummaryWriter with two methods:

  • a method to add multiple scalars in the way that we intend. The original

    SummaryWriter can either add a single scalar at a time or multiple scalars, but in the latter case, multiple runs are created without the option to control these.

  • overwriting the the add_hparams method to write hparams without creating

    another tensorboard run file

add_hparams(hparam_dict=None, metric_dict=None, global_step=None)[source]

Overides the parent method to prevent the creation of unwanted additional subruns while logging hyperparams, as it is done by the original PyTorch method

add_metrics_dict(metrics_dict: dict, run_suffices: List[str], global_step=None, walltime=None, group_prefix: Optional[str] = None, metric_tag_mapping: Optional[dict] = None)[source]
Args:
metric_dict (dict): A dict of metrics. Keys are tag names, values are values.

values can be float, List[float] or Tensor. When List or (nonscalar) tensor, the length must match n_models

run_suffices (List[str]): if each value in metrics_dict is scalar, doesn’t need to be supplied.

When metrics_dict contains lists/iterables, they must all have the same length which should be equal to the length of run_suffices

global_step (int, optional): The step/iteration at which the metrics are being logged. walltime group_prefix (str, optional): If given each metric name will be prepended with this prefix (and a ‘/’),

which will group tags in tensorboard into categories.

metric_tag_mapping (dict, optional): A dactionary that provides a mapping between the metrics (keys of metrics_dict)

and the desired tag names in tensorboard. If given, each metric name will be converted to the corresponding tag name. NOTE: bnelearn.util.metrics.MAPPING_METRICS_TAGS contains a standard mapping for common metrics. These already include (metric-specific) prefixes.

bnelearn.util.logging.export_stepwise_linear_bid(experiment_dir, bidders: List[Bidder], step=0.01)[source]

expoerting grid valuations and corresponding bids for usage of verifier.

Args

experiment_dir: str, dir where export is going to be saved bidders: List[Bidder], to be evaluated here step: float, step length

Returns

to disk: List[csv]

bnelearn.util.logging.log_git_commit_hash(experiment_dir)[source]

Saves the hash of the current git commit into experiment_dir.

bnelearn.util.logging.print_aggregate_tensorboard_logs(experiment_dir)[source]

Prints in a tabular form the aggregate log from all the runs in the current experiment, reads data from the csv file in the experiment directory

bnelearn.util.logging.print_full_tensorboard_logs(experiment_dir, first_row: int = 0, last_row=None)[source]

Prints in a tabular form the full log from all the runs in the current experiment, reads data from a pkl file in the experiment directory :param first_row: the first row to be printed if the full log is used :param last_row: the last row to be printed if the full log is used

bnelearn.util.logging.process_figure(fig, epoch=None, figure_name='plot', tb_group='eval', tb_writer=None, display=False, output_dir=None, save_png=False, save_svg=False)[source]

displays, logs and/or saves a figure

bnelearn.util.logging.read_bne_utility_database(exp: Experiment)[source]

Check if this setting’s BNE has been saved to disk before.

Args:

exp: Experiment

Returns:
db_batch_size: int

sample size of a DB entry if found, else -1

db_bne_utility: List[n_players]

list of the saved BNE utilites

bnelearn.util.logging.save_experiment_config(experiment_log_dir, experiment_configuration: ExperimentConfig)[source]

Serializes ExperimentConfiguration into a readable JSON file

Parameters:
  • experiment_log_dir – full path except for the file name

  • experiment_configuration – experiment configuration as given by ConfigurationManager

bnelearn.util.logging.tabulate_tensorboard_logs(experiment_dir, write_aggregate=True, write_detailed=False, write_binary=False)[source]

This function reads all tensorboard event log files in subdirectories and converts their content into a single csv file containing info of all runs.

bnelearn.util.logging.write_bne_utility_database(exp: Experiment, bne_utilities_sampled: list)[source]

Write the sampled BNE utilities to disk.

Args:

exp: Experiment bne_utilities_sampled: list

BNE utilites that are to be writen to disk

bnelearn.util.metrics module

This module implements metrics that may be interesting.

bnelearn.util.metrics.ex_interim_util_loss(env: AuctionEnvironment, player_position: int, agent_observations: Tensor, grid_size: int, opponent_batch_size: Optional[int] = None, grid_best_response: bool = False)[source]

Estimates a bidder’s utility loss in the current state of the environment, i.e. the potential benefit of deviating from the current strategy, evaluated at each point of the agent_valuations. Therefore, we calculate

\[\max_{v_i \in V_i} \max_{b_i^* \in A_i} E_{v_{-i}|v_i} [u(v_i, b_i^*, b_{-i}(v_{-i})) - u(v_i, b_i, b_{-i}(v_{-i}))]\]

We’re conditioning on the agent’s observation at player_position. That means, types and observations of other players as well as its own type have to be conditioned. As it’s conditioned on the observation, the agent’s action stays the same.

Args:

env: bnelearn.Environment. player_position: int, position of the player in the environment. grid_size: int, stating the number of alternative actions sampled via

env.agents[player_position].get_valuation_grid(grid_size, True).

opponent_batch_size: int, specifying the sample size for opponents. grid_best_response: bool, whether or not the BRs live on the grid or

possibly come from the actual actions (in case no better response was found on grid).

Returns:
utility_loss (torch.Tensor, shape: [batch_size]): the computed

approximate utility loss for for each input observation.

best_response (torch.Tensor, shape: [batch_size, action_size]):

the best response found for each input observation (This is either a grid point, or the actual action according to the player’s strategy.)

Remarks:

Relies on availability of draw_conditional_profiles and generate_valuation_grid in the env’s ValuationObservationSampler.

bnelearn.util.metrics.ex_interim_utility(env: AuctionEnvironment, player_position: int, agent_observations: Tensor, agent_actions: Tensor, opponent_batch_size: int) Tensor[source]

Wrapper for ex_interim_utility that makes some computations sequentially if device is OOM.

bnelearn.util.metrics.ex_post_util_loss(mechanism: Mechanism, bidder_valuations: Tensor, bid_profile: Tensor, bidder: Bidder, grid: Tensor, half_precision=False)[source]

Estimates a bidder’s ex post util_loss in the current bid_profile vs a potential grid, i.e. the potential benefit of having deviated from the current strategy, as:

\[\texttt{util_loss} = max(0, BR(v_i, b_-i) - u_i(b_i, b_-i))\]
Args:

mechanism player_valuations: the valuations of the player that is to be evaluated bid_profile: (batch_size x n_player x n_items) bidder: a Bidder (used to retrieve valuations and utilities) grid: Option 1: 1d tensor with length grid_size todo for n_items > 1,

all grid_size**n_items combination will be used. Should be replaced by e.g. torch.meshgrid. Option 2: tensor with shape (grid_size, n_items)

player_position (optional): specific position in which the player will be evaluated

(defaults to player_position of bidder)

half_precision: (optional, bool) Whether to use half precision tensors. default: false

Returns:

util_loss (batch_size)

Useful: To get the memory used by a tensor (in MB): (tensor.element_size() * tensor.nelement())/(1024*1024)

bnelearn.util.metrics.get_best_responses_among_alternatives(env: AuctionEnvironment, player_position: int, agent_observations: Tensor, action_alternatives: Tensor, opponent_batch_size: int) Tuple[Tensor, IntTensor][source]

Wrapper for _get_best_responses_among_alternatives that makes some computations sequentially if device is OOM.

bnelearn.util.metrics.norm_actions(b1: Tensor, b2: Tensor, p: float = 2) float[source]

Calculates the approximate “mean” Lp-norm between two action vectors.

\[\sum_{i=1}^n(1/n \cdot |b_1 - b_2|^p)^{1/p}\]

If p = Infty, this evaluates to the supremum.

bnelearn.util.metrics.norm_strategies(strategy1: Strategy, strategy2: Strategy, valuations: Tensor, p: float = 2) float[source]

Calculates the approximate “mean” \(L_p\)-norm between two strategies approximated via Monte-Carlo integration on a sample of valuations that have been drawn according to the prior.

The function \(L_p\) norm is given by

\[\left( \int_V |s_1(v) - s_2(v)|^p dv \right)^{1/p}.\]

With Monte-Carlo integration this is approximated by

\[\left( |V|/n \cdot \sum_i^n(|s1(v) - s2(v)|^p) \right)^{1/p}\]

where \(|V|\) is the volume of the set \(V\). Here, we ignore the volume. This gives us the RMSE for \(L_2\), supremum for \(L\)-infty, etc.

bnelearn.util.metrics.norm_strategy_and_actions(strategy, actions, valuations: Tensor, p: float = 2, componentwise=False) Tensor[source]

Calculates the norm as above, but given one action vector and one strategy. The valuations must match the given actions.

This helper function is useful when recalculating an action vector is prohibitive and it should be reused.

Args:

strategy: Strategy actions: torch.Tensor valuations: torch.Tensor p: float=2 componentwise: bool=False, only returns smallest norm of all output

dimensions if true

Returns:

norm: (scalar Tensor)

bnelearn.util.mpc module

This module contains the implementation of our custom GPU-enabled solver for batched constrained quadratic programs, based on Mehrotra’s Predictor-Corrector-Method (MPC).

authors:

Anne Christopher Stefan Heidekrüger (@heidekrueger) Paul Sutterer

class bnelearn.util.mpc.MpcSolver(max_iter=20)[source]

Bases: object

A batched qp-solver that solves batches of QPs of the form

min 0.5 x.T Q x + q.T x s.t. Gx <= h

Ax = b

with problem sice n (i.e. \(x\in\mathbb{R}^n}\)) , n_ineq many inequality constraints and n_eq equality constraints.

The device and dtype used by the solver will be inferred from Q.

Args:

Q (torch.Tensor of dimension (n_batches, n, n)): A batch of positive definite n-by-n matrices. q (Tensor of dimension (n_batches, n)) G (Tensor of dimension (n_batches, n_ineq, n)) h (Tensor of dimension (n_batches, n_ineq)) A (Tensor of dimension (n_batches, n_eq, n)) b (Tensor of dimension (n_batches, n_eq)) refine: bool. When set to True, if after max_iter iterations there are

still batches with residuals over 1e-6, the algorithm will run for another max_iter iterations, up to two additional times.

print_warning (bool): if True, will print warnings if after three runs of max_iter iterations,

the algorithm still hasn’t converged sufficiently.

static is_pd(Q)[source]

checks whether Q (respectively, its entry-matrices in each batch, are positive definite.

solve(Q: Tensor, q: Tensor, G: Tensor, h: Tensor, A: Optional[Tensor] = None, b: Optional[Tensor] = None, refine=False, print_warning=False)[source]
bnelearn.util.tensor_util module

This module implements util functions for PyTorch tensor operations.

class bnelearn.util.tensor_util.GaussLayer(**kwargs)[source]

Bases: Module

Custom layer for normally distributed predictions (non-negative).

Has no trainable parameters.

forward(x, deterministic=False, pretrain=False)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
class bnelearn.util.tensor_util.UniformLayer(**kwargs)[source]

Bases: Module

Custom layer for predictions following a uniform distribution.

Has no trainable parameters.

forward(x, deterministic=False, pretrain=False)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
bnelearn.util.tensor_util.apply_average_dynamic_mini_batching(function: callable, batch_size: int, shape, device) List[Tensor][source]
bnelearn.util.tensor_util.apply_with_dynamic_mini_batching(function: callable, args: Tensor, mute: bool = False) List[Tensor][source]

Apply the function function batch wise to the tensor argument args with error handling for CUDA Out-Of-Memory problems. Starting with the full batch, this method will cut the batch size in half until the operation succeeds (or a non-CUDA-OOM error occurs).

NOTE: The automatic error handling applies to CUDA memory limits only. This function does not provide any benefits when processing on CPU with regular RAM.

Args:

function :callable: function to be evaluated. args :torch.Tensor: pytorch.tensor arguments passed to function. mute :bool: Suppress console output.

Returns:

function evaluated at args.

bnelearn.util.tensor_util.batched_index_select(input: Tensor, dim: int, index: Tensor) Tensor[source]

Extends the torch index_select function to be used for multiple batches at once.

This code is borrowed from https://discuss.pytorch.org/t/batched-index-select/9115/11.

author:

dashesy

args:

input :torch.Tensor: Tensor which is to be indexed dim :int: Dimension index: :torch.Tensor: Index tensor which provides the selecting and ordering.

returns:

Indexed tensor :torch.Tensor:

Module contents

Submodules

bnelearn.bidder module

Bidder module

This module implements players / bidders / agents in games.

class bnelearn.bidder.Bidder(strategy: Strategy, player_position: Optional[Tensor] = None, batch_size: int = 1, valuation_size: int = 1, observation_size: int = 1, bid_size: int = 1, cuda: str = True, enable_action_caching: bool = False, risk: float = 1.0)[source]

Bases: Player

A player in an auction game. Has a distribution over valuations/types that is common knowledge. These valuations correspond to the ´n_items´ available.

Attributes:

batch_size: corresponds to the number of individual auctions. descending_valuations: if is true, the valuations will be returned

in decreasing order.

enable_action_caching: determines whether actions should be cached and

retrieved from memory, rather than recomputed as long as valuations haven’t changed.

TODO …

property cached_observations
property cached_valuations
get_action(observations=None, deterministic: bool = False)[source]

Calculate action from given observations, or retrieve from cache

get_utility(allocations, payments, valuations=None)[source]

For a batch of valuations, allocations, and payments of the bidder, return their utility.

Can handle multiple batch dimensions, e.g. for allocations a shape of ( outer_batch_size, inner_batch_size, n_items). These batch dimensions are kept in returned payoff.

get_welfare(allocations, valuations=None)[source]

For a batch of allocations return the player’s welfare.

If valuations are not specified, welfare is calculated for self.valuations.

Can handle multiple batch dimensions, e.g. for valuations a shape of (…, batch_size, n_items). These batch dimensions are kept in returned welfare.

class bnelearn.bidder.CombinatorialBidder(**kwargs)[source]

Bases: Bidder

Bidder in combinatorial auctions.

Note: Currently only set up for full LLG setting.

get_welfare(allocations, valuations: Optional[Tensor] = None) Tensor[source]

For a batch of allocations return the player’s welfare.

If valuations are not specified, welfare is calculated for self.valuations.

Can handle multiple batch dimensions, e.g. for valuations a shape of (…, batch_size, n_items). These batch dimensions are kept in returned welfare.

class bnelearn.bidder.Contestant(strategy: Strategy, player_position: Optional[Tensor] = None, batch_size: int = 1, valuation_size: int = 1, observation_size: int = 1, bid_size: int = 1, cuda: str = True, enable_action_caching: bool = False, risk: float = 1.0)[source]

Bases: Bidder

get_utility(winning_probabilities, payments, valuations=None)[source]

For a batch of valuations, allocations, and payments of the contestant, return their utility.

Can handle multiple batch dimensions, e.g. for allocations a shape of ( outer_batch_size, inner_batch_size, n_items). These batch dimensions are kept in returned payoff.

get_welfare(payments, valuations=None)[source]

For a batch of allocations return the player’s welfare.

If valuations are not specified, welfare is calculated for self.valuations.

Can handle multiple batch dimensions, e.g. for valuations a shape of (…, batch_size, n_items). These batch dimensions are kept in returned welfare.

class bnelearn.bidder.CrowdsourcingContestant(strategy: Strategy, player_position: int, batch_size: int, enable_action_caching: bool = False, crowdsourcing_values: bool = True, value_contest: bool = True)[source]

Bases: Bidder

get_utility(allocations, payments, ability=None)[source]

For a batch of valuations, allocations, and payments of the contestant, return their utility.

Can handle multiple batch dimensions, e.g. for allocations a shape of ( outer_batch_size, inner_batch_size, n_items). These batch dimensions are kept in returned payoff.

class bnelearn.bidder.MatrixGamePlayer(strategy, player_position=None, batch_size=1, cuda=True)[source]

Bases: Player

A player playing a matrix game

get_action()[source]

Chooses an action according to the player’s strategy.

get_utility(*outcome)[source]

get player’s utility for a batch of outcomes

class bnelearn.bidder.Player(strategy, player_position=None, batch_size=1, cuda=True)[source]

Bases: ABC

A player in a game, determined by her - strategy - utility function over outcomes

abstract get_action()[source]

Chooses an action according to the player’s strategy.

abstract get_utility(*args, **kwargs)[source]

Calculates player’s utility based on outcome of a game.

class bnelearn.bidder.ReverseBidder(efficiency_parameter=None, **kwargs)[source]

Bases: Bidder

Bidder that has reversed utility \(\cdot (-1)\) as valuations correspond to their costs and payments to what they get payed.

get_utility(allocations, payments, valuations=None)[source]

For reverse bidders, returns are inverted.

bnelearn.environment module

This module contains environments - a collection of players and possibly state histories that is used to control game playing and implements reward allocation to agents.

class bnelearn.environment.AuctionEnvironment(mechanism: Mechanism, agents: Iterable[Bidder], valuation_observation_sampler: ValuationObservationSampler, batch_size=100, n_players=None, strategy_to_player_closure: Optional[Callable[[Strategy], Bidder]] = None, redraw_every_iteration: bool = False)[source]

Bases: Environment

An environment of agents to play against and evaluate strategies.

Args:

… (TODO: document) correlation_structure

strategy_to_bidder_closure: A closure (strategy, batch_size) -> Bidder to

transform strategies into a Bidder compatible with the environment

draw_conditionals(conditioned_player: int, conditioned_observation: Tensor, inner_batch_size: Optional[int] = None, device: Optional[str] = None) Tuple[Tensor, Tensor][source]

Draws a conditional valuation / observation profile based on a (vector of) fixed observations for one player.

Total batch size will be conditioned_observation.shape[0] x inner_batch_size

draw_valuations()[source]

Draws a new valuation and observation profile

returns/yields:

nothing

side effects:

updates agent’s valuations and observation states

get_allocation(agent, redraw_valuations: bool = False, aggregate: bool = True) Tensor[source]

Returns allocation of a single player against the environment.

get_efficiency(redraw_valuations: bool = False) float[source]

Average percentage that the actual welfare reaches of the maximal possible welfare over a batch.

Args:
redraw_valuations (:bool:) whether or not to redraw the valuations of

the agents.

Returns:
efficiency (:float:) Percentage that the actual welfare reaches of

the maximale possible welfare. Averaged over batch.

get_revenue(redraw_valuations: bool = False) float[source]

Returns the average seller revenue over a batch.

Args:
redraw_valuations (bool): whether or not to redraw the valuations of

the agents.

Returns:

revenue (float): average of seller revenue over a batch of games.

get_reward(agent: Bidder, redraw_valuations: bool = False, aggregate: bool = True, regularize: float = 0.0, return_allocation: bool = False, smooth_market: bool = False, deterministic: bool = False) Tensor[source]

Returns reward of a single player against the environment, and optionally additionally the allocation of that player. Reward is calculated as average utility for each of the batch_size x env_size games

prepare_iteration()[source]

Prepares the interim-stage of a Bayesian game, (e.g. in an Auction, draw bidders’ valuations)

class bnelearn.environment.Environment(agents: Iterable, n_players=2, batch_size=1, strategy_to_player_closure: Optional[Callable] = None, **kwargs)[source]

Bases: ABC

An Environment object ‘manages’ a repeated game, i.e. manages the current players and their models, collects players’ actions, distributes rewards, runs the game itself and allows ‘simulations’ as in ‘how would a mutated player do in the current setting’?

abstract get_reward(agent: Player, **kwargs) Tensor[source]

Return reward for a player playing a certain strategy

get_strategy_action_and_reward(strategy: Strategy, player_position: int, redraw_valuations=False, **strat_to_player_kwargs) Tensor[source]

Returns reward of a given strategy in given environment agent position.

get_strategy_reward(strategy: Strategy, player_position: int, redraw_valuations=False, aggregate_batch=True, regularize: float = 0, smooth_market: bool = False, deterministic: bool = False, **strat_to_player_kwargs) Tensor[source]

Returns reward of a given strategy in given environment agent position.

Args:

strategy: the strategy to be evaluated player_position: the player position at which the agent will be evaluated redraw_valuation: whether to redraw valuations (default false) aggregate_batch: whether to aggregate rewards into a single scalar (True),

or return batch_size many rewards (one for each sample). Default True

strat_to_player_kwargs: further arguments needed for agent creation regularize: paramter that penalizes high action values (e.g. if we

get the same utility with different actions, we prefer the lower one). Default value of zero corresponds to no regularization.

is_empty()[source]

True if no agents in the environment

prepare_iteration()[source]

Prepares the interim-stage of a Bayesian game, (e.g. in an Auction, draw bidders’ valuations)

class bnelearn.environment.MatrixGameEnvironment(game: MatrixGame, agents, n_players=2, batch_size=1, strategy_to_player_closure=None, **kwargs)[source]

Bases: Environment

An environment for matrix games.

Important features of matrix games for implementation:

  • not necessarily symmetric, i.e. each player has a fixed position

  • agents strategies do not take any input, the actions only depend on the game itself (no Bayesian Game)

get_reward(agent, **kwargs) tensor[source]

Simulates one batch of the environment and returns the average reward for agent as a scalar tensor.

bnelearn.learner module

Implements multi-agent learning rules

class bnelearn.learner.AESPGLearner(model: NeuralNetStrategy, environment: Environment, hyperparams: dict, optimizer_type: Type[Optimizer], optimizer_hyperparams: dict, strat_to_player_kwargs: Optional[dict] = None)[source]

Bases: GradientBasedLearner

Implements Deterministic Policy Gradients http://proceedings.mlr.press/v32/silver14.pdf with ES-pseudogradients of dQ/da

class bnelearn.learner.DDPGLearner[source]

Bases: GradientBasedLearner

Implements Deep Deterministic Policy Gradients (Lilicrap et al 2016)

http://arxiv.org/abs/1509.02971

class bnelearn.learner.DPGLearner[source]

Bases: GradientBasedLearner

Implements Deterministic Policy Gradients

http://proceedings.mlr.press/v32/silver14.pdf

via directly calculating dQ/da and da/dtheta

class bnelearn.learner.DummyNonLearner(model: Module, environment: Environment, hyperparams: dict, optimizer_type: Type[Optimizer], optimizer_hyperparams: dict, strat_to_player_kwargs: Optional[dict] = None)[source]

Bases: GradientBasedLearner

A learner that does nothing.

class bnelearn.learner.ESPGLearner(hyperparams: dict, **kwargs)[source]

Bases: GradientBasedLearner

Neural Self-Play with Evolutionary Strategy Pseudo-PG as proposed in Bichler et. al (2021).

Uses pseudo-policy gradients calculated as

(rewards - baseline).mean() * epsilons / sigma**2

over a population of models perturbed by parameter noise epsilon yielding perturbed rewards.

Arguments:

model: bnelearn.bidder environment: bnelearn.Environment hyperparams: dict

(required:)

population_size: int sigma: float scale_sigma_by_model_size: bool

(optional:)
normalize_gradients: bool (default: False)

If true will scale rewards to N(0,1) in weighted-noise update: (F - baseline).mean()/sigma/F.std() resulting in an (approximately) normalized vector pointing in the same direction as the true gradient. (normalization requires small enough sigma!) If false or not provided, will approximate true gradient using current utility as a baseline for variance reduction.

baseline: (‘current_reward’, ‘mean_reward’ or a float.)

If ‘current_reward’, will use current utility before update as a baseline. If ‘mean_reward’, will use mean of candidate rewards.

For small perturbations, ‘mean_reward’ is cheaper to compute (one fewer game played) and yields slightly lower gradient sample variance but yields a biased estimate of the true gradient:

Expect(ES_grad with mean) = (pop_size - 1) / pop_size * true_grad

If a float is given, will use that float as reward. Defaults to ‘current_reward’ if normalize_gradients is False, or to ‘mean_reward’ if normalize_gradients is True.

regularization: dict of

initial_strength: float, initial penalization factor of bid value regularize_decay: float, decay rate by which the regularization factor

is multiplied each iteration.

symmetric_sampling: bool

whether or not we sample symmetric pairs of perturbed parameters, e.g. p + eps and p - eps.

optimizer_type: Type[torch.optim.Optimizer]

A class implementing torch’s optimizer interface used for parameter update step.

strat_to_player_kwargs: dict

dict of arguments provided to environment used for evaluating utility of current and candidate strategies.

class bnelearn.learner.GradientBasedLearner(model: Module, environment: Environment, optimizer_type: Type[Optimizer], optimizer_hyperparams: dict, scheduler_type: Optional[Type[_LRScheduler]] = None, scheduler_hyperparams: Optional[dict] = None, strat_to_player_kwargs: Optional[dict] = None, smooth_market: bool = False, log_gradient_variance: bool = False)[source]

Bases: Learner

A learning rule that is based on computing some version of (pseudo-) gradient, then applying an SGD-like update via a torch.optim.Optimizer

update_strategy(closure: Optional[Callable] = None) Tensor[source]

Performs one model-update to the player’s strategy.

Params:
closure: (optional) Callable that recomputes model loss.

Required by some optimizers such as LBFGS. When given, optimizer.step() (and thus this function) return the last evaluated loss. (Usually evaluated BEFORE the model update). For correct usage see: https://pytorch.org/docs/stable/optim.html#optimizer-step-closure

Returns: None or loss evaluated by closure. (See above.)

update_strategy_and_evaluate_utility(closure=None)[source]

updates model and returns utility after the update.

class bnelearn.learner.Learner[source]

Bases: ABC

A learning rule used to update a player’s policy in self-play

abstract update_strategy() None[source]

Updates the player’s strategy.

abstract update_strategy_and_evaluate_utility(closure=None) Tensor[source]

updates model and returns utility after the update.

class bnelearn.learner.PGLearner(hyperparams: dict, **kwargs)[source]

Bases: GradientBasedLearner

Neural Self-Play with directly computed Policy Gradients.

class bnelearn.learner.PSOLearner(model: Module, environment: Environment, hyperparams: dict, optimizer_type: Type[Optimizer], optimizer_hyperparams: dict, scheduler_type: Optional[Type[_LRScheduler]] = None, scheduler_hyperparams: Optional[dict] = None, strat_to_player_kwargs: Optional[dict] = None, smooth_market: bool = False, log_gradient_variance: bool = False)[source]

Bases: Learner

Implements the Particle Swarm Optimization Algorithm as a Learner Particles represent a possible solutions to the model parameters. Every update step they move one step in the search space to sample a new solution point. They are guided by their previously best found solution (personal best position) and the best solution found by the entire swarm (best position) NOTE: dim = number of parameters in the model to be optimized Arguments:

model: bnelearn.bidder environment: bnelearn.Environment hyperparams: dict

(required:)
swarm_size: int

Number of particles in the swarm

topology: str

Defines the communication network of the swarm If ‘global’, particles are drawn to the global best position of the swarm.

Neighborhood size = swarm size

If ‘ring’, particles are drawn to the best position in their neighborhood.

Particles form a neighborhood based on their position in the population array. The first and last particles are connected to form a ring structure. Neighborhood size = 3. E.g., neighborhood of particle i: particle i-1, particle i, particle i+1

If ‘von_neumann’, particles are drawn to the best position in their neighborhood.

Particles form a neighborhood based on their position in the population matrix. A particle is connected to its left, right, upper and lower neighbor in the matrix. Neighborhood size = 5

max_velocity: float

Max step size in each direction during one update step If velocity_clamping == False then only used for initialization

(optional:)

The default values for the inertia weight and the cognition & social ratio are commonly used values performing well form most problem settings. Based on: Clerc, M., & Kennedy, J. (2002) inertia_weight: float, List, Tuple (default: 0.792)

Scales the impact of the old velocity on the new one. If float, will set value as constant If List or Tuple, with lenght == 2, will take the first value as w_max and second as w_min for a linear decreasing inertia weight !!! max number of iteration is hardcoded to 2000 !!!

cognition_ratio: float (default: 1.49445)

Upper limit for the impact of the personal best solution on the velocity

social_ratio: float (default: 1.49445)

Upper limit for the impact of the swarm’s best solution on the velocity

reeval_frequency: int (default: None)

Number of epochs after which the personal and overall bests are reevaluated to prevent false memory introduced by varying batch data

decrease_fitness: List or Tuple (default None)

The to evaporation constants are used to reduce the remembered fitness of the bests to prevent false memory introduced by varying batch data. !!! Use either ‘reeval_frequency’or ‘decrease_fitness’ !!! with lenght == 2, will take the first value as evaporation constant for personal best and second as evaporation constant for global (neighborhood) best

pretrain_deviation: float (default: 0)

If pretrain_deviation > 0 the positions will be initialized as: model.parameters + N(mean=0.0, std=pretrain_deviation) otherwise positions will be initialized randomly over the whole search space

bound_handling: bool (default: False)

If true will clamp particle’s positions in each dim to the interval [-max_position, max_position]

velocity_clamping: bool (default: True)

If true will clamp particle’s velocities in each dim to the interval [-max_velocity, max_velocity] before adding to the positions

optimizer_type: Type[torch.optim.Optimizer]

A class implementing torch’s optimizer interface used for parameter update step. PSO does not need an torch optimizer to compute an parameter update step. -> currently only used to have an consistent interface with other learners

optimizer_hyperparams: dict strat_to_player_kwargs: dict

Dict of arguments provided to environment used for evaluating utility of current and candidate strategies.

update_strategy()[source]

Updates the player’s strategy.

update_strategy_and_evaluate_utility()[source]

updates model and returns utility after the update.

class bnelearn.learner.ReinforceLearner(hyperparams: Optional[dict] = None, **kwargs)[source]

Bases: GradientBasedLearner

REINFORCE Learner. Also known as Score function estimator.

See https://link.springer.com/article/10.1007/BF00992696 and https://pytorch.org/docs/stable/distributions.html.

bnelearn.strategy module

Implementations of strategies for playing in Auctions and Matrix Games.

class bnelearn.strategy.ClosureStrategy(closure: Callable, parallel: int = 0, mute=False)[source]

Bases: Strategy

A strategy specified by a closure

Args:

closure: Callable a function or lambda that defines the strategy parallel: int (optional) maximum number of processes for parallel execution of closure. Default is

0/1 (i.e. no parallelism)

play(inputs, deterministic: bool = False)[source]

Takes (private) information as input and decides on the actions an agent should play.

to(device: str)[source]

Compatibility to Pytorch’s .to().

class bnelearn.strategy.FictitiousNeuralPlayStrategy(n_actions, beliefs, init_weight_normalization=False)[source]

Bases: MatrixGameStrategy, Module

An implementation of the concept of Fictitious Play with NN. An implementation inspired by: https://www.groundai.com/project/deep-fictitious-play-for-stochastic-differential-games2589/2 Take the beliefs about others strategies as input for the NN.

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

training: bool
class bnelearn.strategy.FictitiousPlayMixedStrategy(game: Game, initial_beliefs: Optional[Iterable[Tensor]] = None)[source]

Bases: FictitiousPlaySmoothStrategy

Play (communicate) probabilities for play (same as in smooth FP) instead of one action. One strategy should be shared among all players such that they share the same beliefs. This is purely fictitious since it does not simulate actions.

play(player_position) Tensor[source]

Takes (private) information as input and decides on the actions an agent should play.

update_observations(actions: None)[source]
class bnelearn.strategy.FictitiousPlaySmoothStrategy(game: Game, initial_beliefs: Optional[Iterable[Tensor]] = None)[source]

Bases: FictitiousPlayStrategy

Implementation based on Fudenberg (1999) but extended by smooth fictitious play. Randomize action by taking the softmax over the expected utilities for each action and sample. Also, add a temperature (tau) that ensures convergence by becoming smaller.

play(player_position) Tensor[source]

Takes (private) information as input and decides on the actions an agent should play.

update_tau(param=0.9)[source]

Updates temperature parameter

class bnelearn.strategy.FictitiousPlayStrategy(game: MatrixGame, initial_beliefs: Optional[Iterable[Tensor]] = None)[source]

Bases: Strategy

Based on description in: Fudenberg, 1999 - The Theory of Learning, Chapter 2.2 Always play best response (that maximizes utility based on current beliefs).

play(player_position: int)[source]

Takes (private) information as input and decides on the actions an agent should play.

update_beliefs()[source]

Update beliefs about play

update_observations(actions: Iterable[Tensor])[source]
class bnelearn.strategy.MatrixGameStrategy(n_actions, init_weights=None, init_weight_normalization=False)[source]

Bases: Strategy, Module

A dummy neural network that encodes and returns a mixed strategy

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

play(inputs=None, batch_size=1)[source]

Takes (private) information as input and decides on the actions an agent should play.

to(device)[source]

Moves and/or casts the parameters and buffers.

This can be called as

to(device=None, dtype=None, non_blocking=False)[source]
to(dtype, non_blocking=False)[source]
to(tensor, non_blocking=False)[source]
to(memory_format=torch.channels_last)[source]

Its signature is similar to torch.Tensor.to(), but only accepts floating point or complex dtypes. In addition, this method will only cast the floating point or complex parameters and buffers to dtype (if given). The integral parameters and buffers will be moved device, if that is given, but with dtypes unchanged. When non_blocking is set, it tries to convert/move asynchronously with respect to the host if possible, e.g., moving CPU Tensors with pinned memory to CUDA devices.

See below for examples.

Note

This method modifies the module in-place.

Args:
device (torch.device): the desired device of the parameters

and buffers in this module

dtype (torch.dtype): the desired floating point or complex dtype of

the parameters and buffers in this module

tensor (torch.Tensor): Tensor whose dtype and device are the desired

dtype and device for all parameters and buffers in this module

memory_format (torch.memory_format): the desired memory

format for 4D parameters and buffers in this module (keyword only argument)

Returns:

Module: self

Examples:

>>> # xdoctest: +IGNORE_WANT("non-deterministic")
>>> linear = nn.Linear(2, 2)
>>> linear.weight
Parameter containing:
tensor([[ 0.1913, -0.3420],
        [-0.5113, -0.2325]])
>>> linear.to(torch.double)
Linear(in_features=2, out_features=2, bias=True)
>>> linear.weight
Parameter containing:
tensor([[ 0.1913, -0.3420],
        [-0.5113, -0.2325]], dtype=torch.float64)
>>> # xdoctest: +REQUIRES(env:TORCH_DOCTEST_CUDA1)
>>> gpu1 = torch.device("cuda:1")
>>> linear.to(gpu1, dtype=torch.half, non_blocking=True)
Linear(in_features=2, out_features=2, bias=True)
>>> linear.weight
Parameter containing:
tensor([[ 0.1914, -0.3420],
        [-0.5112, -0.2324]], dtype=torch.float16, device='cuda:1')
>>> cpu = torch.device("cpu")
>>> linear.to(cpu)
Linear(in_features=2, out_features=2, bias=True)
>>> linear.weight
Parameter containing:
tensor([[ 0.1914, -0.3420],
        [-0.5112, -0.2324]], dtype=torch.float16)

>>> linear = nn.Linear(2, 2, bias=None).to(torch.cdouble)
>>> linear.weight
Parameter containing:
tensor([[ 0.3741+0.j,  0.2382+0.j],
        [ 0.5593+0.j, -0.4443+0.j]], dtype=torch.complex128)
>>> linear(torch.ones(3, 2, dtype=torch.cdouble))
tensor([[0.6122+0.j, 0.1150+0.j],
        [0.6122+0.j, 0.1150+0.j],
        [0.6122+0.j, 0.1150+0.j]], dtype=torch.complex128)
training: bool
class bnelearn.strategy.NeuralNetStrategy(input_length: int, hidden_nodes: Iterable[int], hidden_activations: Iterable[Module], ensure_positive_output: Optional[Tensor] = None, output_length: int = 1, dropout: float = 0.0, mixed_strategy: Optional[str] = None, bias: bool = True, res_net: bool = False)[source]

Bases: Strategy, Module

A strategy played by a fully connected neural network

Args:
input_length:

dimension of the input layer

hidden_nodes:

Iterable of number of nodes in hidden layers

hidden_activations:

Iterable of activation functions to be used in the hidden layers. Should be instances of classes defined in torch.nn.modules.activation

ensure_positive_output (optional): torch.Tensor

When provided, will check whether the initialized model will return a positive bid anywhere at the given input tensor. Otherwise, the weights will be reinitialized.

output_length (optional): int

length of output/action vector defaults to 1 (currently given last for backwards-compatibility)

dropout (optional): float

If not 0, applies AlphaDropout (https://pytorch.org/docs/stable/nn.html#torch.nn.AlphaDropout) to dropout share of nodes in each hidden layer during training.

mixed_strategy (otional): str

Which distribution to use when the strategy should be mixed.

res_net (optional): bool

Switch to use ResNet skip connections, s.t. only the difference from a ruthful strategy is learned.

forward(x, deterministic=False, pretrain=False)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

get_gradient_norm()[source]

Get the norm of the gradient

classmethod load(path: str, device='cpu')[source]

Initializes a saved NeuralNetStrategy from path.

play(inputs, deterministic: bool = False)[source]

Takes (private) information as input and decides on the actions an agent should play.

pretrain(input_tensor: Tensor, iterations: int, transformation: Optional[Callable] = None)[source]

Performs iters steps of supervised learning on input tensor, in order to find an initial bid function that is suitable for learning.

args:

input: torch.Tensor, same dimension as self.input_length iters: number of iterations for supervised learning transformation (optional): Callable. Defaulting to identity function if input_length == output_length

returns: Nothing

reset(ensure_positive_output=None)[source]

Re-initialize weights of the Neural Net, ensuring positive model output for a given input.

training: bool
class bnelearn.strategy.Strategy[source]

Bases: ABC

A Strategy to map (optional) private inputs of a player to actions in a game.

abstract play(inputs)[source]

Takes (private) information as input and decides on the actions an agent should play.

pretrain(input_tensor, iterations, transformation=None)[source]

If implemented by subclass, pretrains the strategy to yield desired initial outputs.

class bnelearn.strategy.TruthfulStrategy[source]

Bases: Strategy, Module

A strategy that plays truthful valuations.

forward(x)[source]

Defines the computation performed at every call.

Should be overridden by all subclasses.

Note

Although the recipe for forward pass needs to be defined within this function, one should call the Module instance afterwards instead of this since the former takes care of running the registered hooks while the latter silently ignores them.

play(inputs, deterministic: bool = False)[source]

Takes (private) information as input and decides on the actions an agent should play.

training: bool

Module contents

Features

In this section, we will present the bnelearn package with its most essential features and the auction games and learning algorithms it contains.

Structure

  • I(PV) and non-PV (e.g., common values), with arbitrary priors/correlation profiles, utilities, valuation/observation/bid dimensionalities.

  • Modular organization allows for easy construction of new markets (e.g., bid languages, etc.) from existing or custom building blocks.

  • Extensive metrics (learning-related: estimates of “equilibrium quality”, utilities over time, market analysis: efficiency, revenue, individual payoffs) and built-in plotting capacities.

  • Wide range of predefined settings and building blocks:

    • Learning rules: Policy Gradients, NPGA, PSO.

    • Auctions: Single-item, multi-unit, LLG combinatorial auction, LLLLGG combinatorial auction.

    • Priors/correlations: Uniform and normal priors that are either independent or Bernoulli or constant weight dependent.

    • Utility functions: Quasi-linear utility (risk-neutral) , risk averse, or risk seeking.

  • Fully vectorized, CUDA enabled, massive parallelism

  • For combinatorial auctions: Custom batched, CUDA-enabled QP solver for quadratic auction rules and Gurobi/Cvxpy integration for arbitrary auctions stated as a MIP.

Predefined Auction Settings

A diverse set of auction games is implemented in the framework.

Predefined Learners

Algorithms for trying to iteratively learn equilibria implement the base class Learner in the framework. Two noteworthy algorithms that are contained are

Limitations and Alternatives

All players in a game must have the same dimensionality (i.e. same-dimensional type-spaces and action-spaces). Current implementations and learners use deterministic/pure continuous actions.

Other existing multi-agent Learning Packages: Other multi-agent learning frameworks, such as OpenSpiel that is a collection of games and algorithms for reinforcement learning and planning or PettingZoo that is a multi-agent extension of the famous OpenAI Gym framework, mainly focus on zero-sum games and on games with discrete action spaces. Crucially, they neither allow an efficient evaluation of running a large batch of games in parallel.

Indices and tables