diff --git a/README.md b/README.md index 2a8ac55..4433e10 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This package implements the models of [Shelegia and Motta (2021)](shelegia_motta_2021.pdf). +This package implements the models of [Shelegia and Motta (2021)](resources/shelegia_motta_2021.pdf). ![GitHub](https://img.shields.io/github/license/manuelbieri/shelegia_motta_2021) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/Shelegia-Motta-2021) @@ -94,14 +94,5 @@ Generate api-documentation with the following command: pdoc -o ./docs Shelegia_Motta_2021 --docformat "numpy" --math ``` -#### Dependencies - -| Package  | Version   | Annotation   | -|:-----------|:---------|:------------------------------------------------| -| matplotlib | 3.4.3 | Always needed (includes numpy) | -| jupyter | 1.0.0 | Just for the demonstration in demo.ipynb | -| pdoc | 8.0.1 | Only to generate the documentation from scratch | -
- #### Additional Notes -For further information about the coordinates used in the code, see dev_notes.md. +For further information about the coordinates used in the code, see resources/dev_notes.md. diff --git a/Shelegia_Motta_2021/IModel.py b/Shelegia_Motta_2021/IModel.py index b967082..09c8ccb 100644 --- a/Shelegia_Motta_2021/IModel.py +++ b/Shelegia_Motta_2021/IModel.py @@ -159,7 +159,7 @@ def get_optimal_choice(self, A: float, F: float) -> Dict[str, str]: pass @abc.abstractmethod - def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: """ Plots the best answers of the incumbent to all possible actions of the entrant. @@ -167,6 +167,10 @@ def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matp ---------- axis : matplotlib.axes.Axes Axis to draw the plot on. (optional) + **kwargs + Optional key word arguments for the best answers plot.
+ - title: title on top of the plot, instead of the default title.
+ - options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
Returns ------- @@ -176,7 +180,7 @@ def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matp pass @abc.abstractmethod - def plot_equilibrium(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_equilibrium(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: """ Plots the equilibrium path based on the choices of the entrant and incumbent. @@ -184,6 +188,10 @@ def plot_equilibrium(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes ---------- axis : matplotlib.axes.Axes Axis to draw the plot on. (optional) + **kwargs + Optional key word arguments for the equilibrium plot.
+ - title: title on top of the plot, instead of the default title.
+ - options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
Returns ------- diff --git a/Shelegia_Motta_2021/Models.py b/Shelegia_Motta_2021/Models.py index 5f57d81..d8365db 100644 --- a/Shelegia_Motta_2021/Models.py +++ b/Shelegia_Motta_2021/Models.py @@ -1,4 +1,4 @@ -from typing import Dict, List, Tuple, Literal +from typing import Dict, List, Tuple, Literal, Final import matplotlib.axes import matplotlib.pyplot as plt @@ -15,7 +15,7 @@ class BaseModel(Shelegia_Motta_2021.IModel): There are two players in our base model: The Incumbent, which sells the primary product, denoted by Ip, and a start-up, called the Entrant, which sells a product Ec complementary to Ip. (One may think of Ip as a platform, and Ec as a service or product which can be accessed through the platform.) We are interested in studying the choice of E between developing a substitute to Ip, denoted by Ep, or another complement to Ip, denoted by Ẽc and the choice of I between copying E’s original complementary product Ec by creating a perfect substitute Ic, or not. Since E may not have enough assets to cover the development cost of its second product, copying its current product will affect the entrant’s ability to obtain funding for the development. We shall show that the incumbent has a strategic incentive to copy when the entrant plans to compete, and to abstain from copying when it plans to create another complement. """ - tolerance: float = 10 ** (-8) + TOLERANCE: Final[float] = 10 ** (-8) """Tolerance for the comparison of two floating numbers.""" def __init__(self, u: float = 1, B: float = 0.5, small_delta: float = 0.5, delta: float = 0.51, @@ -235,7 +235,7 @@ def _plot(self, coordinates: List[List[Tuple[float, float]]], labels: List[str], Axis containing the plot. """ if axis is None: - fig, axis = plt.subplots() + figure, axis = plt.subplots() self._draw_thresholds(axis) for i, coordinates in enumerate(coordinates): @@ -243,18 +243,19 @@ def _plot(self, coordinates: List[List[Tuple[float, float]]], labels: List[str], axis.add_patch(poly) axis.legend(bbox_to_anchor=(1.3, 1), loc="upper left") + if kwargs.get('options_legend', False): + axis.text(-0.05, -0.4, self._create_options_legend(), verticalalignment='top') BaseModel._set_axis_labels(axis, title=kwargs.get('title', ''), x_label=kwargs.get('xlabel', 'Assets of the entrant'), y_label=kwargs.get('ylabel', 'Fixed costs of copying for the incumbent')) BaseModel._set_axis(axis) - plt.show() return axis - def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: poly_coordinates: List[List[Tuple[float, float]]] = self._get_incumbent_best_answer_coordinates() poly_labels: List[str] = self._get_incumbent_best_answer_labels() - axis: matplotlib.axes.Axes = self._plot(title="Best Answers of the incumbent to the choices of the entrant", - coordinates=poly_coordinates, labels=poly_labels, axis=axis) + axis: matplotlib.axes.Axes = self._plot(title=kwargs.get("title", "Best Answers of the incumbent to the choices of the entrant"), + coordinates=poly_coordinates, labels=poly_labels, axis=axis, options_legend=kwargs.get('options_legend', False)) return axis def _create_choice_answer_label(self, entrant: Literal["complement", "substitute", "indifferent"], @@ -267,7 +268,7 @@ def _get_incumbent_best_answer_labels(self) -> List[str]: """ Returns a list containing the labels for the squares in the plot of the best answers of the incumbent to the choice of the entrant. - For the order of the labels refer to the file devnotes.md. + For the order of the labels refer to the file resources/dev_notes.md. Returns ------- @@ -298,7 +299,7 @@ def _get_incumbent_best_answer_coordinates(self) -> List[List[Tuple[float, float """ Returns a list containing the coordinates for the squares in the plot of the best answers of the incumbent to the choice of the entrant. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -330,18 +331,18 @@ def _get_incumbent_best_answer_coordinates(self) -> List[List[Tuple[float, float (x_max, y_max), (0, y_max), (0, self._copying_fixed_costs['F(YN)s']), (self._assets['A-s'], self._copying_fixed_costs['F(YN)s'])]] - def plot_equilibrium(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_equilibrium(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: poly_coordinates: List[List[Tuple[float, float]]] = self._get_equilibrium_coordinates() poly_labels: List[str] = self._get_equilibrium_labels() - axis: matplotlib.axes.Axes = self._plot(title='Equilibrium Path in the base Model', - coordinates=poly_coordinates, labels=poly_labels, axis=axis) + axis: matplotlib.axes.Axes = self._plot(title=kwargs.get("title", "Equilibrium Path"), + coordinates=poly_coordinates, labels=poly_labels, axis=axis, options_legend=kwargs.get('options_legend', False)) return axis def _get_equilibrium_labels(self) -> List[str]: """ Returns a list containing the labels for the squares in the plot of the equilibrium path. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -362,7 +363,7 @@ def _get_equilibrium_coordinates(self) -> List[List[Tuple[float, float]]]: """ Returns a list containing the coordinates for the squares in the plot of the equilibrium path. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -388,7 +389,7 @@ def _get_equilibrium_coordinates(self) -> List[List[Tuple[float, float]]]: def plot_payoffs(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: if axis is None: - fig, axis = plt.subplots() + figure, axis = plt.subplots() index = arange(0, len(self._payoffs) * 2, 2) bar_width = 0.35 opacity = 0.8 @@ -517,7 +518,7 @@ def _draw_thresholds(self, axis: matplotlib.axes.Axes) -> None: self._draw_horizontal_line_with_label(axis, y=self._copying_fixed_costs['F(YN)s'], label="$F^{YN}_S$") self._draw_horizontal_line_with_label(axis, y=self._copying_fixed_costs['F(YY)c'], label="$F^{YY}_C$") - if abs(self._copying_fixed_costs['F(YY)s'] - self._copying_fixed_costs['F(YN)c']) < BaseModel.tolerance: + if abs(self._copying_fixed_costs['F(YY)s'] - self._copying_fixed_costs['F(YN)c']) < BaseModel.TOLERANCE: self._draw_horizontal_line_with_label(axis, y=self._copying_fixed_costs['F(YY)s'], label="$F^{YY}_S=F^{YN}_C$") else: @@ -564,6 +565,19 @@ def _draw_vertical_line_with_label(self, axis: matplotlib.axes.Axes, x: float, l if label is not None: axis.text(x, label_y, label) + def _create_options_legend(self, latex: bool = True) -> str: + space: str = "$\quad$" if latex else "\t" + return "Options of the entrant:\n" + \ + space + self.ENTRANT_CHOICES['complement'] + ": Tries to develop an additional complementary product to a primary product.\n" + \ + space + self.ENTRANT_CHOICES['substitute'] + ": Tries to develop an substitute to the primary product of the incumbent.\n" + \ + space + self.ENTRANT_CHOICES['indifferent'] + " : Indifferent between the options mentioned above.\n" + \ + "Options of the incumbent:\n" + \ + space + self.INCUMBENT_CHOICES['copy'] + " : Tries to develop an additional complementary product to a primary product.\n" + \ + space + self.INCUMBENT_CHOICES['refrain'] + " : Tries to develop an additional complementary product to a primary product.\n" + \ + "Outcomes of the development:\n" + \ + space + self.DEVELOPMENT_OUTCOME['success'] + " : The additional product can be developed, since the entrant has sufficient assets.\n" + \ + space + self.DEVELOPMENT_OUTCOME['failure'] + " : The additional product can not be developed, since the entrant has not enough assets." + @staticmethod def _get_color(i: int) -> str: """ @@ -793,8 +807,8 @@ def __init__(self, u: float = 1, B: float = 0.5, small_delta: float = 0.5, delta """ super(UnobservableModel, self).__init__(u=u, B=B, small_delta=small_delta, delta=delta, K=K, beta=beta) - def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: - return self.plot_equilibrium(axis=axis) + def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: + return self.plot_equilibrium(axis=axis, kwargs=kwargs) def _create_choice_answer_label(self, entrant: Literal["complement", "substitute", "indifferent"], incumbent: Literal["copy", "refrain"], @@ -806,7 +820,7 @@ def _get_equilibrium_labels(self) -> List[str]: """ Returns a list containing the labels for the squares in the plot of the equilibrium path. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -823,6 +837,13 @@ def _get_equilibrium_labels(self) -> List[str]: self._create_choice_answer_label(entrant="substitute", incumbent="refrain", development="success") ] + def get_optimal_choice(self, A: float, F: float) -> Dict[str, str]: + result: Dict = super().get_optimal_choice(A, F) + # adjust the different choices in area three -> since the kill zone does not exist in this model. + if result["entrant"] == self.ENTRANT_CHOICES["complement"]: + result = {"entrant": self.ENTRANT_CHOICES["substitute"], "incumbent": self.INCUMBENT_CHOICES["copy"], "development": self.DEVELOPMENT_OUTCOME["failure"]} + return result + class AcquisitionModel(BargainingPowerModel): """ @@ -864,6 +885,6 @@ def get_copying_fixed_costs_values(self) -> Dict[str, float]: if __name__ == '__main__': - base_model = UnobservableModel(beta=0.6) - base_model.plot_equilibrium() - print(base_model) + bargaining_power_model = Shelegia_Motta_2021.BargainingPowerModel(beta=0.6) + bargaining_power_model.plot_equilibrium() + plt.show() diff --git a/Shelegia_Motta_2021_Test/ModelTest.py b/Shelegia_Motta_2021_Test/ModelTest.py index 45c4711..1bb88e6 100644 --- a/Shelegia_Motta_2021_Test/ModelTest.py +++ b/Shelegia_Motta_2021_Test/ModelTest.py @@ -2,10 +2,13 @@ from typing import Dict from Shelegia_Motta_2021.IModel import IModel -from Shelegia_Motta_2021.Models import BaseModel +from Shelegia_Motta_2021.Models import BaseModel, BargainingPowerModel, UnobservableModel class BaseModelTest(unittest.TestCase): + """ + See dev_notes.md for the enumeration of the areas used in the testcases. + """ @staticmethod def setUpModel() -> IModel: return BaseModel() @@ -16,6 +19,26 @@ def setUp(self) -> None: self.assets: Dict[str, float] = self.model.get_asset_values() self.utility: Dict[str, Dict[str, float]] = self.model.get_payoffs() + def assert_area_one(self, choice: Dict[str, str]): + self.assertEqual(choice["entrant"], self.model.ENTRANT_CHOICES["indifferent"]) + self.assertEqual(choice["incumbent"], self.model.INCUMBENT_CHOICES["copy"]) + self.assertEqual(choice["development"], self.model.DEVELOPMENT_OUTCOME["failure"]) + + def assert_area_two(self, choice: Dict[str, str]): + self.assertEqual(choice["entrant"], self.model.ENTRANT_CHOICES["substitute"]) + self.assertEqual(choice["incumbent"], self.model.INCUMBENT_CHOICES["copy"]) + self.assertEqual(choice["development"], self.model.DEVELOPMENT_OUTCOME["success"]) + + def assert_area_three(self, choice: Dict[str, str]): + self.assertEqual(choice["entrant"], self.model.ENTRANT_CHOICES["complement"]) + self.assertEqual(choice["incumbent"], self.model.INCUMBENT_CHOICES["refrain"]) + self.assertEqual(choice["development"], self.model.DEVELOPMENT_OUTCOME["success"]) + + def assert_area_four(self, choice: Dict[str, str]): + self.assertEqual(choice["entrant"], self.model.ENTRANT_CHOICES["substitute"]) + self.assertEqual(choice["incumbent"], self.model.INCUMBENT_CHOICES["refrain"]) + self.assertEqual(choice["development"], self.model.DEVELOPMENT_OUTCOME["success"]) + def test_invalid_A1b(self): self.assertRaises(AssertionError, BaseModel, small_delta=0.2) self.assertRaises(AssertionError, BaseModel, delta=0.2) @@ -25,24 +48,82 @@ def test_invalid_A2(self): def test_path_indifferent_copy(self): choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"]*0.9, F=self.copying_fixed_costs["F(YN)c"]*0.9) - self.assertEqual(choice["entrant"], self.model.ENTRANT_CHOICES["indifferent"]) - self.assertEqual(choice["incumbent"], self.model.INCUMBENT_CHOICES["copy"]) - self.assertEqual(choice["development"], self.model.DEVELOPMENT_OUTCOME["failure"]) + self.assert_area_one(choice) def test_path_kill_zone(self): choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"]*0.9, F=self.copying_fixed_costs["F(YN)c"]*1.1) - self.assertEqual(choice["entrant"], self.model.ENTRANT_CHOICES["complement"]) - self.assertEqual(choice["incumbent"], self.model.INCUMBENT_CHOICES["refrain"]) - self.assertEqual(choice["development"], self.model.DEVELOPMENT_OUTCOME["success"]) + self.assert_area_three(choice) def test_path_substitute_refrain(self): - choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"]*1.1, F=self.copying_fixed_costs["F(YN)c"]*1.1) - self.assertEqual(choice["entrant"], self.model.ENTRANT_CHOICES["substitute"]) - self.assertEqual(choice["incumbent"], self.model.INCUMBENT_CHOICES["refrain"]) - self.assertEqual(choice["development"], self.model.DEVELOPMENT_OUTCOME["success"]) + choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"]*1.1, F=self.copying_fixed_costs["F(YY)s"]*1.1) + self.assert_area_four(choice) def test_path_substitute_copy(self): - choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"]*1.1, F=self.copying_fixed_costs["F(YN)c"]*0.9) + choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"]*1.1, F=self.copying_fixed_costs["F(YY)s"]*0.9) + self.assert_area_two(choice) + + def test_path_four_areas_corner(self): + choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"], F=self.copying_fixed_costs["F(YY)s"]) + self.assert_area_two(choice) + + def test_path_area_three_area_four_corner(self): + choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"], F=self.copying_fixed_costs["F(YN)s"]) + self.assert_area_four(choice) + + def test_path_area_three_area_four(self): + choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"]*0.9, F=self.copying_fixed_costs["F(YN)s"]) + self.assert_area_three(choice) + + def test_path_area_one_area_two(self): + choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"], F=min(self.copying_fixed_costs["F(YY)s"], self.copying_fixed_costs["F(YN)c"])*0.9) + self.assert_area_two(choice) + + def test_path_area_one_area_three(self): + choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"]*0.9, F=self.copying_fixed_costs["F(YN)c"]) + self.assert_area_three(choice) + + def test_path_area_two_area_four(self): + choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"]*1.1, F=self.copying_fixed_costs["F(YY)s"]) + self.assert_area_two(choice) + + +class BargainingPowerModelTestBeta6(BaseModelTest): + @staticmethod + def setUpModel() -> IModel: + return BargainingPowerModel(beta=0.6) + + def test_path_area_two_area_three(self): + choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"], F=(self.copying_fixed_costs["F(YY)s"] + self.copying_fixed_costs["F(YN)c"])/2) + self.assert_area_two(choice) + + +class BargainingPowerModelTestBeta4(BaseModelTest): + @staticmethod + def setUpModel() -> IModel: + return BargainingPowerModel(beta=0.4) + + def test_path_area_one_area_four(self): + choice: Dict[str, str] = self.model.get_optimal_choice(A=self.assets["A-s"], F=(self.copying_fixed_costs["F(YY)s"] + self.copying_fixed_costs["F(YN)c"])/2) + self.assert_area_four(choice) + + +class UnobservableModelTestBeta6(BargainingPowerModelTestBeta6): + @staticmethod + def setUpModel() -> IModel: + return UnobservableModel(beta=0.6) + + def assert_area_three(self, choice: Dict[str, str]): self.assertEqual(choice["entrant"], self.model.ENTRANT_CHOICES["substitute"]) self.assertEqual(choice["incumbent"], self.model.INCUMBENT_CHOICES["copy"]) - self.assertEqual(choice["development"], self.model.DEVELOPMENT_OUTCOME["success"]) + self.assertEqual(choice["development"], self.model.DEVELOPMENT_OUTCOME["failure"]) + + +class UnobservableModelTestBeta4(BargainingPowerModelTestBeta4): + @staticmethod + def setUpModel() -> IModel: + return UnobservableModel(beta=0.4) + + def assert_area_three(self, choice: Dict[str, str]): + self.assertEqual(choice["entrant"], self.model.ENTRANT_CHOICES["substitute"]) + self.assertEqual(choice["incumbent"], self.model.INCUMBENT_CHOICES["copy"]) + self.assertEqual(choice["development"], self.model.DEVELOPMENT_OUTCOME["failure"]) diff --git a/docs/Shelegia_Motta_2021.html b/docs/Shelegia_Motta_2021.html index 1a89e2b..91f9f3a 100644 --- a/docs/Shelegia_Motta_2021.html +++ b/docs/Shelegia_Motta_2021.html @@ -61,7 +61,6 @@

Contents

  • Documentation
  • @@ -94,7 +93,7 @@

    API Documentation

    Shelegia_Motta_2021

    -

    This package implements the models of Shelegia and Motta (2021).

    +

    This package implements the models of Shelegia and Motta (2021).

    GitHub PyPI - Python Version @@ -116,7 +115,7 @@

    Installation

    Or clone the repository via GitHub:

    -
    git clone manuelbieri/shelegia_motta_2021
    +
    git clone https://github.com/manuelbieri/shelegia_motta_2021.git
     

    Introduction

    @@ -218,40 +217,9 @@

    Build Documentation

    pdoc -o ./docs Shelegia_Motta_2021 --docformat "numpy" --math
     
    -

    Dependencies

    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Package  Version  Annotation  
    matplotlib3.4.3Always needed (includes numpy)
    jupyter1.0.0Just for the demonstration in demo.ipynb
    pdoc8.0.1Only to generate the documentation from scratch
    - -


    -

    Additional Notes

    -

    For further information about the coordinates used in the code, see dev_notes.md.

    +

    For further information about the coordinates used in the code, see resources/dev_notes.md.

    diff --git a/docs/Shelegia_Motta_2021/IModel.html b/docs/Shelegia_Motta_2021/IModel.html index d37533c..feb3ebb 100644 --- a/docs/Shelegia_Motta_2021/IModel.html +++ b/docs/Shelegia_Motta_2021/IModel.html @@ -266,7 +266,7 @@

    pass @abc.abstractmethod - def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: """ Plots the best answers of the incumbent to all possible actions of the entrant. @@ -274,6 +274,10 @@

    ---------- axis : matplotlib.axes.Axes Axis to draw the plot on. (optional) + **kwargs + Optional key word arguments for the best answers plot.<br> + - title: title on top of the plot, instead of the default title.<br> + - options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.<br> Returns ------- @@ -283,7 +287,7 @@

    pass @abc.abstractmethod - def plot_equilibrium(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_equilibrium(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: """ Plots the equilibrium path based on the choices of the entrant and incumbent. @@ -291,6 +295,10 @@

    ---------- axis : matplotlib.axes.Axes Axis to draw the plot on. (optional) + **kwargs + Optional key word arguments for the equilibrium plot.<br> + - title: title on top of the plot, instead of the default title.<br> + - options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.<br> Returns ------- @@ -503,7 +511,7 @@

    pass @abc.abstractmethod - def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: """ Plots the best answers of the incumbent to all possible actions of the entrant. @@ -511,6 +519,10 @@

    ---------- axis : matplotlib.axes.Axes Axis to draw the plot on. (optional) + **kwargs + Optional key word arguments for the best answers plot.<br> + - title: title on top of the plot, instead of the default title.<br> + - options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.<br> Returns ------- @@ -520,7 +532,7 @@

    pass @abc.abstractmethod - def plot_equilibrium(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_equilibrium(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: """ Plots the equilibrium path based on the choices of the entrant and incumbent. @@ -528,6 +540,10 @@

    ---------- axis : matplotlib.axes.Axes Axis to draw the plot on. (optional) + **kwargs + Optional key word arguments for the equilibrium plot.<br> + - title: title on top of the plot, instead of the default title.<br> + - options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.<br> Returns ------- @@ -944,14 +960,15 @@

    Returns
    def plot_incumbent_best_answers( self, - axis: matplotlib.axes._axes.Axes = None + axis: matplotlib.axes._axes.Axes = None, + **kwargs ) -> matplotlib.axes._axes.Axes:
    View Source
        @abc.abstractmethod
    -    def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes:
    +    def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes:
             """
             Plots the best answers of the incumbent to all possible actions of the entrant.
     
    @@ -959,6 +976,10 @@ 
    Returns
    ---------- axis : matplotlib.axes.Axes Axis to draw the plot on. (optional) + **kwargs + Optional key word arguments for the best answers plot.<br> + - title: title on top of the plot, instead of the default title.<br> + - options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.<br> Returns ------- @@ -977,6 +998,11 @@
    Parameters
    • axis (matplotlib.axes.Axes): Axis to draw the plot on. (optional)
    • +
    • **kwargs: Optional key word arguments for the best answers plot.
      +
        +
      • title: title on top of the plot, instead of the default title.
      • +
      • options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
      • +
    Returns
    @@ -996,14 +1022,15 @@
    Returns
    def plot_equilibrium( self, - axis: matplotlib.axes._axes.Axes = None + axis: matplotlib.axes._axes.Axes = None, + **kwargs ) -> matplotlib.axes._axes.Axes:
    View Source
        @abc.abstractmethod
    -    def plot_equilibrium(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes:
    +    def plot_equilibrium(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes:
             """
             Plots the equilibrium path based on the choices of the entrant and incumbent.
     
    @@ -1011,6 +1038,10 @@ 
    Returns
    ---------- axis : matplotlib.axes.Axes Axis to draw the plot on. (optional) + **kwargs + Optional key word arguments for the equilibrium plot.<br> + - title: title on top of the plot, instead of the default title.<br> + - options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.<br> Returns ------- @@ -1029,6 +1060,11 @@
    Parameters
    • axis (matplotlib.axes.Axes): Axis to draw the plot on. (optional)
    • +
    • **kwargs: Optional key word arguments for the equilibrium plot.
      +
        +
      • title: title on top of the plot, instead of the default title.
      • +
      • options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
      • +
    Returns
    diff --git a/docs/Shelegia_Motta_2021/Models.html b/docs/Shelegia_Motta_2021/Models.html index 042589e..b96fc49 100644 --- a/docs/Shelegia_Motta_2021/Models.html +++ b/docs/Shelegia_Motta_2021/Models.html @@ -54,7 +54,7 @@

    API Documentation

    BaseModel
  • - tolerance + TOLERANCE
  • get_asset_values @@ -107,6 +107,9 @@

    API Documentation

  • plot_incumbent_best_answers
  • +
  • + get_optimal_choice +
  • @@ -141,7 +144,7 @@

    View Source -
    from typing import Dict, List, Tuple, Literal
    +            
    from typing import Dict, List, Tuple, Literal, Final
     
     import matplotlib.axes
     import matplotlib.pyplot as plt
    @@ -158,7 +161,7 @@ 

    There are two players in our base model: The Incumbent, which sells the primary product, denoted by Ip, and a start-up, called the Entrant, which sells a product Ec complementary to Ip. (One may think of Ip as a platform, and Ec as a service or product which can be accessed through the platform.) We are interested in studying the choice of E between developing a substitute to Ip, denoted by Ep, or another complement to Ip, denoted by Ẽc and the choice of I between copying E’s original complementary product Ec by creating a perfect substitute Ic, or not. Since E may not have enough assets to cover the development cost of its second product, copying its current product will affect the entrant’s ability to obtain funding for the development. We shall show that the incumbent has a strategic incentive to copy when the entrant plans to compete, and to abstain from copying when it plans to create another complement. """ - tolerance: float = 10 ** (-8) + TOLERANCE: Final[float] = 10 ** (-8) """Tolerance for the comparison of two floating numbers.""" def __init__(self, u: float = 1, B: float = 0.5, small_delta: float = 0.5, delta: float = 0.51, @@ -378,7 +381,7 @@

    Axis containing the plot. """ if axis is None: - fig, axis = plt.subplots() + figure, axis = plt.subplots() self._draw_thresholds(axis) for i, coordinates in enumerate(coordinates): @@ -386,18 +389,19 @@

    axis.add_patch(poly) axis.legend(bbox_to_anchor=(1.3, 1), loc="upper left") + if kwargs.get('options_legend', False): + axis.text(-0.05, -0.4, self._create_options_legend(), verticalalignment='top') BaseModel._set_axis_labels(axis, title=kwargs.get('title', ''), x_label=kwargs.get('xlabel', 'Assets of the entrant'), y_label=kwargs.get('ylabel', 'Fixed costs of copying for the incumbent')) BaseModel._set_axis(axis) - plt.show() return axis - def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: poly_coordinates: List[List[Tuple[float, float]]] = self._get_incumbent_best_answer_coordinates() poly_labels: List[str] = self._get_incumbent_best_answer_labels() - axis: matplotlib.axes.Axes = self._plot(title="Best Answers of the incumbent to the choices of the entrant", - coordinates=poly_coordinates, labels=poly_labels, axis=axis) + axis: matplotlib.axes.Axes = self._plot(title=kwargs.get("title", "Best Answers of the incumbent to the choices of the entrant"), + coordinates=poly_coordinates, labels=poly_labels, axis=axis, options_legend=kwargs.get('options_legend', False)) return axis def _create_choice_answer_label(self, entrant: Literal["complement", "substitute", "indifferent"], @@ -410,7 +414,7 @@

    """ Returns a list containing the labels for the squares in the plot of the best answers of the incumbent to the choice of the entrant. - For the order of the labels refer to the file devnotes.md. + For the order of the labels refer to the file resources/dev_notes.md. Returns ------- @@ -441,7 +445,7 @@

    """ Returns a list containing the coordinates for the squares in the plot of the best answers of the incumbent to the choice of the entrant. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -473,18 +477,18 @@

    (x_max, y_max), (0, y_max), (0, self._copying_fixed_costs['F(YN)s']), (self._assets['A-s'], self._copying_fixed_costs['F(YN)s'])]] - def plot_equilibrium(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_equilibrium(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: poly_coordinates: List[List[Tuple[float, float]]] = self._get_equilibrium_coordinates() poly_labels: List[str] = self._get_equilibrium_labels() - axis: matplotlib.axes.Axes = self._plot(title='Equilibrium Path in the base Model', - coordinates=poly_coordinates, labels=poly_labels, axis=axis) + axis: matplotlib.axes.Axes = self._plot(title=kwargs.get("title", "Equilibrium Path"), + coordinates=poly_coordinates, labels=poly_labels, axis=axis, options_legend=kwargs.get('options_legend', False)) return axis def _get_equilibrium_labels(self) -> List[str]: """ Returns a list containing the labels for the squares in the plot of the equilibrium path. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -505,7 +509,7 @@

    """ Returns a list containing the coordinates for the squares in the plot of the equilibrium path. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -531,7 +535,7 @@

    def plot_payoffs(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: if axis is None: - fig, axis = plt.subplots() + figure, axis = plt.subplots() index = arange(0, len(self._payoffs) * 2, 2) bar_width = 0.35 opacity = 0.8 @@ -660,7 +664,7 @@

    self._draw_horizontal_line_with_label(axis, y=self._copying_fixed_costs['F(YN)s'], label="$F^{YN}_S$") self._draw_horizontal_line_with_label(axis, y=self._copying_fixed_costs['F(YY)c'], label="$F^{YY}_C$") - if abs(self._copying_fixed_costs['F(YY)s'] - self._copying_fixed_costs['F(YN)c']) < BaseModel.tolerance: + if abs(self._copying_fixed_costs['F(YY)s'] - self._copying_fixed_costs['F(YN)c']) < BaseModel.TOLERANCE: self._draw_horizontal_line_with_label(axis, y=self._copying_fixed_costs['F(YY)s'], label="$F^{YY}_S=F^{YN}_C$") else: @@ -707,6 +711,19 @@

    if label is not None: axis.text(x, label_y, label) + def _create_options_legend(self, latex: bool = True) -> str: + space: str = "$\quad$" if latex else "\t" + return "Options of the entrant:\n" + \ + space + self.ENTRANT_CHOICES['complement'] + ": Tries to develop an additional complementary product to a primary product.\n" + \ + space + self.ENTRANT_CHOICES['substitute'] + ": Tries to develop an substitute to the primary product of the incumbent.\n" + \ + space + self.ENTRANT_CHOICES['indifferent'] + " : Indifferent between the options mentioned above.\n" + \ + "Options of the incumbent:\n" + \ + space + self.INCUMBENT_CHOICES['copy'] + " : Tries to develop an additional complementary product to a primary product.\n" + \ + space + self.INCUMBENT_CHOICES['refrain'] + " : Tries to develop an additional complementary product to a primary product.\n" + \ + "Outcomes of the development:\n" + \ + space + self.DEVELOPMENT_OUTCOME['success'] + " : The additional product can be developed, since the entrant has sufficient assets.\n" + \ + space + self.DEVELOPMENT_OUTCOME['failure'] + " : The additional product can not be developed, since the entrant has not enough assets." + @staticmethod def _get_color(i: int) -> str: """ @@ -936,8 +953,8 @@

    """ super(UnobservableModel, self).__init__(u=u, B=B, small_delta=small_delta, delta=delta, K=K, beta=beta) - def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: - return self.plot_equilibrium(axis=axis) + def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: + return self.plot_equilibrium(axis=axis, kwargs=kwargs) def _create_choice_answer_label(self, entrant: Literal["complement", "substitute", "indifferent"], incumbent: Literal["copy", "refrain"], @@ -949,7 +966,7 @@

    """ Returns a list containing the labels for the squares in the plot of the equilibrium path. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -966,6 +983,12 @@

    self._create_choice_answer_label(entrant="substitute", incumbent="refrain", development="success") ] + def get_optimal_choice(self, A: float, F: float) -> Dict[str, str]: + result: Dict = super().get_optimal_choice(A, F) + if result["entrant"] == self.ENTRANT_CHOICES["complement"]: + result = {"entrant": self.ENTRANT_CHOICES["substitute"], "incumbent": self.INCUMBENT_CHOICES["copy"], "development": self.DEVELOPMENT_OUTCOME["failure"]} + return result + class AcquisitionModel(BargainingPowerModel): """ @@ -1007,9 +1030,9 @@

    if __name__ == '__main__': - base_model = UnobservableModel(beta=0.6) - base_model.plot_equilibrium() - print(base_model) + bargaining_power_model = Shelegia_Motta_2021.BargainingPowerModel(beta=0.6) + bargaining_power_model.plot_equilibrium() + plt.show()

    @@ -1031,7 +1054,7 @@

    There are two players in our base model: The Incumbent, which sells the primary product, denoted by Ip, and a start-up, called the Entrant, which sells a product Ec complementary to Ip. (One may think of Ip as a platform, and Ec as a service or product which can be accessed through the platform.) We are interested in studying the choice of E between developing a substitute to Ip, denoted by Ep, or another complement to Ip, denoted by Ẽc and the choice of I between copying E’s original complementary product Ec by creating a perfect substitute Ic, or not. Since E may not have enough assets to cover the development cost of its second product, copying its current product will affect the entrant’s ability to obtain funding for the development. We shall show that the incumbent has a strategic incentive to copy when the entrant plans to compete, and to abstain from copying when it plans to create another complement. """ - tolerance: float = 10 ** (-8) + TOLERANCE: Final[float] = 10 ** (-8) """Tolerance for the comparison of two floating numbers.""" def __init__(self, u: float = 1, B: float = 0.5, small_delta: float = 0.5, delta: float = 0.51, @@ -1251,7 +1274,7 @@

    Axis containing the plot. """ if axis is None: - fig, axis = plt.subplots() + figure, axis = plt.subplots() self._draw_thresholds(axis) for i, coordinates in enumerate(coordinates): @@ -1259,18 +1282,19 @@

    axis.add_patch(poly) axis.legend(bbox_to_anchor=(1.3, 1), loc="upper left") + if kwargs.get('options_legend', False): + axis.text(-0.05, -0.4, self._create_options_legend(), verticalalignment='top') BaseModel._set_axis_labels(axis, title=kwargs.get('title', ''), x_label=kwargs.get('xlabel', 'Assets of the entrant'), y_label=kwargs.get('ylabel', 'Fixed costs of copying for the incumbent')) BaseModel._set_axis(axis) - plt.show() return axis - def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: poly_coordinates: List[List[Tuple[float, float]]] = self._get_incumbent_best_answer_coordinates() poly_labels: List[str] = self._get_incumbent_best_answer_labels() - axis: matplotlib.axes.Axes = self._plot(title="Best Answers of the incumbent to the choices of the entrant", - coordinates=poly_coordinates, labels=poly_labels, axis=axis) + axis: matplotlib.axes.Axes = self._plot(title=kwargs.get("title", "Best Answers of the incumbent to the choices of the entrant"), + coordinates=poly_coordinates, labels=poly_labels, axis=axis, options_legend=kwargs.get('options_legend', False)) return axis def _create_choice_answer_label(self, entrant: Literal["complement", "substitute", "indifferent"], @@ -1283,7 +1307,7 @@

    """ Returns a list containing the labels for the squares in the plot of the best answers of the incumbent to the choice of the entrant. - For the order of the labels refer to the file devnotes.md. + For the order of the labels refer to the file resources/dev_notes.md. Returns ------- @@ -1314,7 +1338,7 @@

    """ Returns a list containing the coordinates for the squares in the plot of the best answers of the incumbent to the choice of the entrant. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -1346,18 +1370,18 @@

    (x_max, y_max), (0, y_max), (0, self._copying_fixed_costs['F(YN)s']), (self._assets['A-s'], self._copying_fixed_costs['F(YN)s'])]] - def plot_equilibrium(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: + def plot_equilibrium(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: poly_coordinates: List[List[Tuple[float, float]]] = self._get_equilibrium_coordinates() poly_labels: List[str] = self._get_equilibrium_labels() - axis: matplotlib.axes.Axes = self._plot(title='Equilibrium Path in the base Model', - coordinates=poly_coordinates, labels=poly_labels, axis=axis) + axis: matplotlib.axes.Axes = self._plot(title=kwargs.get("title", "Equilibrium Path"), + coordinates=poly_coordinates, labels=poly_labels, axis=axis, options_legend=kwargs.get('options_legend', False)) return axis def _get_equilibrium_labels(self) -> List[str]: """ Returns a list containing the labels for the squares in the plot of the equilibrium path. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -1378,7 +1402,7 @@

    """ Returns a list containing the coordinates for the squares in the plot of the equilibrium path. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -1404,7 +1428,7 @@

    def plot_payoffs(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: if axis is None: - fig, axis = plt.subplots() + figure, axis = plt.subplots() index = arange(0, len(self._payoffs) * 2, 2) bar_width = 0.35 opacity = 0.8 @@ -1533,7 +1557,7 @@

    self._draw_horizontal_line_with_label(axis, y=self._copying_fixed_costs['F(YN)s'], label="$F^{YN}_S$") self._draw_horizontal_line_with_label(axis, y=self._copying_fixed_costs['F(YY)c'], label="$F^{YY}_C$") - if abs(self._copying_fixed_costs['F(YY)s'] - self._copying_fixed_costs['F(YN)c']) < BaseModel.tolerance: + if abs(self._copying_fixed_costs['F(YY)s'] - self._copying_fixed_costs['F(YN)c']) < BaseModel.TOLERANCE: self._draw_horizontal_line_with_label(axis, y=self._copying_fixed_costs['F(YY)s'], label="$F^{YY}_S=F^{YN}_C$") else: @@ -1580,6 +1604,19 @@

    if label is not None: axis.text(x, label_y, label) + def _create_options_legend(self, latex: bool = True) -> str: + space: str = "$\quad$" if latex else "\t" + return "Options of the entrant:\n" + \ + space + self.ENTRANT_CHOICES['complement'] + ": Tries to develop an additional complementary product to a primary product.\n" + \ + space + self.ENTRANT_CHOICES['substitute'] + ": Tries to develop an substitute to the primary product of the incumbent.\n" + \ + space + self.ENTRANT_CHOICES['indifferent'] + " : Indifferent between the options mentioned above.\n" + \ + "Options of the incumbent:\n" + \ + space + self.INCUMBENT_CHOICES['copy'] + " : Tries to develop an additional complementary product to a primary product.\n" + \ + space + self.INCUMBENT_CHOICES['refrain'] + " : Tries to develop an additional complementary product to a primary product.\n" + \ + "Outcomes of the development:\n" + \ + space + self.DEVELOPMENT_OUTCOME['success'] + " : The additional product can be developed, since the entrant has sufficient assets.\n" + \ + space + self.DEVELOPMENT_OUTCOME['failure'] + " : The additional product can not be developed, since the entrant has not enough assets." + @staticmethod def _get_color(i: int) -> str: """ @@ -1740,10 +1777,10 @@

    Parameters
    -
    -
    #   +
    +
    #   - tolerance: float = 1e-08 + TOLERANCE: Final[float] = 1e-08

    Tolerance for the comparison of two floating numbers.

    @@ -2092,17 +2129,18 @@
    Returns
    def plot_incumbent_best_answers( self, - axis: matplotlib.axes._axes.Axes = None + axis: matplotlib.axes._axes.Axes = None, + **kwargs ) -> matplotlib.axes._axes.Axes:
    View Source -
        def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes:
    +            
        def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes:
             poly_coordinates: List[List[Tuple[float, float]]] = self._get_incumbent_best_answer_coordinates()
             poly_labels: List[str] = self._get_incumbent_best_answer_labels()
    -        axis: matplotlib.axes.Axes = self._plot(title="Best Answers of the incumbent to the choices of the entrant",
    -                                                coordinates=poly_coordinates, labels=poly_labels, axis=axis)
    +        axis: matplotlib.axes.Axes = self._plot(title=kwargs.get("title", "Best Answers of the incumbent to the choices of the entrant"),
    +                                                coordinates=poly_coordinates, labels=poly_labels, axis=axis, options_legend=kwargs.get('options_legend', False))
             return axis
     
    @@ -2115,6 +2153,11 @@
    Parameters
    • axis (matplotlib.axes.Axes): Axis to draw the plot on. (optional)
    • +
    • **kwargs: Optional key word arguments for the best answers plot.
      +
        +
      • title: title on top of the plot, instead of the default title.
      • +
      • options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
      • +
    Returns
    @@ -2133,17 +2176,18 @@
    Returns
    def plot_equilibrium( self, - axis: matplotlib.axes._axes.Axes = None + axis: matplotlib.axes._axes.Axes = None, + **kwargs ) -> matplotlib.axes._axes.Axes:
    View Source -
        def plot_equilibrium(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes:
    +            
        def plot_equilibrium(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes:
             poly_coordinates: List[List[Tuple[float, float]]] = self._get_equilibrium_coordinates()
             poly_labels: List[str] = self._get_equilibrium_labels()
    -        axis: matplotlib.axes.Axes = self._plot(title='Equilibrium Path in the base Model',
    -                                                coordinates=poly_coordinates, labels=poly_labels, axis=axis)
    +        axis: matplotlib.axes.Axes = self._plot(title=kwargs.get("title", "Equilibrium Path"),
    +                                                coordinates=poly_coordinates, labels=poly_labels, axis=axis, options_legend=kwargs.get('options_legend', False))
             return axis
     
    @@ -2156,6 +2200,11 @@
    Parameters
    • axis (matplotlib.axes.Axes): Axis to draw the plot on. (optional)
    • +
    • **kwargs: Optional key word arguments for the equilibrium plot.
      +
        +
      • title: title on top of the plot, instead of the default title.
      • +
      • options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
      • +
    Returns
    @@ -2182,7 +2231,7 @@
    Returns
    View Source
        def plot_payoffs(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes:
             if axis is None:
    -            fig, axis = plt.subplots()
    +            figure, axis = plt.subplots()
             index = arange(0, len(self._payoffs) * 2, 2)
             bar_width = 0.35
             opacity = 0.8
    @@ -2734,7 +2783,7 @@ 
    Returns
    Inherited Members
    BaseModel
    -
    tolerance
    +
    TOLERANCE
    get_optimal_choice
    plot_incumbent_best_answers
    plot_equilibrium
    @@ -2772,8 +2821,8 @@
    Inherited Members
    """ super(UnobservableModel, self).__init__(u=u, B=B, small_delta=small_delta, delta=delta, K=K, beta=beta) - def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes: - return self.plot_equilibrium(axis=axis) + def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes: + return self.plot_equilibrium(axis=axis, kwargs=kwargs) def _create_choice_answer_label(self, entrant: Literal["complement", "substitute", "indifferent"], incumbent: Literal["copy", "refrain"], @@ -2785,7 +2834,7 @@
    Inherited Members
    """ Returns a list containing the labels for the squares in the plot of the equilibrium path. - For the order of the squares refer to the file devnotes.md. + For the order of the squares refer to the file resources/dev_notes.md. Returns ------- @@ -2801,6 +2850,12 @@
    Inherited Members
    # Square 4 self._create_choice_answer_label(entrant="substitute", incumbent="refrain", development="success") ] + + def get_optimal_choice(self, A: float, F: float) -> Dict[str, str]: + result: Dict = super().get_optimal_choice(A, F) + if result["entrant"] == self.ENTRANT_CHOICES["complement"]: + result = {"entrant": self.ENTRANT_CHOICES["substitute"], "incumbent": self.INCUMBENT_CHOICES["copy"], "development": self.DEVELOPMENT_OUTCOME["failure"]} + return result
    @@ -2847,14 +2902,15 @@
    Inherited Members
    def plot_incumbent_best_answers( self, - axis: matplotlib.axes._axes.Axes = None + axis: matplotlib.axes._axes.Axes = None, + **kwargs ) -> matplotlib.axes._axes.Axes:
    View Source -
        def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None) -> matplotlib.axes.Axes:
    -        return self.plot_equilibrium(axis=axis)
    +            
        def plot_incumbent_best_answers(self, axis: matplotlib.axes.Axes = None, **kwargs) -> matplotlib.axes.Axes:
    +        return self.plot_equilibrium(axis=axis, kwargs=kwargs)
     
    @@ -2866,6 +2922,11 @@
    Parameters
    • axis (matplotlib.axes.Axes): Axis to draw the plot on. (optional)
    • +
    • **kwargs: Optional key word arguments for the best answers plot.
      +
        +
      • title: title on top of the plot, instead of the default title.
      • +
      • options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
      • +
    Returns
    @@ -2876,6 +2937,53 @@
    Returns
    +
    +
    +
    #   + + + def + get_optimal_choice(self, A: float, F: float) -> Dict[str, str]: +
    + +
    + View Source +
        def get_optimal_choice(self, A: float, F: float) -> Dict[str, str]:
    +        result: Dict = super().get_optimal_choice(A, F)
    +        if result["entrant"] == self.ENTRANT_CHOICES["complement"]:
    +            result = {"entrant": self.ENTRANT_CHOICES["substitute"], "incumbent": self.INCUMBENT_CHOICES["copy"], "development": self.DEVELOPMENT_OUTCOME["failure"]}
    +        return result
    +
    + +
    + +

    Returns the optimal choice of the entrant and the incumbent based on a pair of assets of the entrant and fixed costs for copying of the incumbent.

    + +

    The output dictionary will contain the following details:

    + + + +
    Parameters
    + +
      +
    • A (float): +Assets of the entrant.
    • +
    • F (float): +Fixed costs for copying of the incumbent.
    • +
    + +
    Returns
    + +
      +
    • Dict[str, str]: Optimal choice of the entrant, the incumbent and the outcome of the development.
    • +
    +
    + +
    Inherited Members
    @@ -2887,8 +2995,7 @@
    Inherited Members
    BaseModel
    -
    tolerance
    -
    get_optimal_choice
    +
    TOLERANCE
    plot_equilibrium
    plot_payoffs
    @@ -3070,7 +3177,7 @@
    Inherited Members
    BaseModel
    -
    tolerance
    +
    TOLERANCE
    get_optimal_choice
    plot_incumbent_best_answers
    plot_equilibrium
    diff --git a/docs/search.js b/docs/search.js index e4be15d..3b0ebce 100644 --- a/docs/search.js +++ b/docs/search.js @@ -1,6 +1,6 @@ window.pdocSearch = (function(){ /** elasticlunr - http://weixsong.github.io * Copyright (C) 2017 Oliver Nightingale * Copyright (C) 2017 Wei Song * MIT Licensed */!function(){function e(e){if(null===e||"object"!=typeof e)return e;var t=e.constructor();for(var n in e)e.hasOwnProperty(n)&&(t[n]=e[n]);return t}var t=function(e){var n=new t.Index;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),e&&e.call(n,n),n};t.version="0.9.5",lunr=t,t.utils={},t.utils.warn=function(e){return function(t){e.console&&console.warn&&console.warn(t)}}(this),t.utils.toString=function(e){return void 0===e||null===e?"":e.toString()},t.EventEmitter=function(){this.events={}},t.EventEmitter.prototype.addListener=function(){var e=Array.prototype.slice.call(arguments),t=e.pop(),n=e;if("function"!=typeof t)throw new TypeError("last argument must be a function");n.forEach(function(e){this.hasHandler(e)||(this.events[e]=[]),this.events[e].push(t)},this)},t.EventEmitter.prototype.removeListener=function(e,t){if(this.hasHandler(e)){var n=this.events[e].indexOf(t);-1!==n&&(this.events[e].splice(n,1),0==this.events[e].length&&delete this.events[e])}},t.EventEmitter.prototype.emit=function(e){if(this.hasHandler(e)){var t=Array.prototype.slice.call(arguments,1);this.events[e].forEach(function(e){e.apply(void 0,t)},this)}},t.EventEmitter.prototype.hasHandler=function(e){return e in this.events},t.tokenizer=function(e){if(!arguments.length||null===e||void 0===e)return[];if(Array.isArray(e)){var n=e.filter(function(e){return null===e||void 0===e?!1:!0});n=n.map(function(e){return t.utils.toString(e).toLowerCase()});var i=[];return n.forEach(function(e){var n=e.split(t.tokenizer.seperator);i=i.concat(n)},this),i}return e.toString().trim().toLowerCase().split(t.tokenizer.seperator)},t.tokenizer.defaultSeperator=/[\s\-]+/,t.tokenizer.seperator=t.tokenizer.defaultSeperator,t.tokenizer.setSeperator=function(e){null!==e&&void 0!==e&&"object"==typeof e&&(t.tokenizer.seperator=e)},t.tokenizer.resetSeperator=function(){t.tokenizer.seperator=t.tokenizer.defaultSeperator},t.tokenizer.getSeperator=function(){return t.tokenizer.seperator},t.Pipeline=function(){this._queue=[]},t.Pipeline.registeredFunctions={},t.Pipeline.registerFunction=function(e,n){n in t.Pipeline.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[n]=e},t.Pipeline.getRegisteredFunction=function(e){return e in t.Pipeline.registeredFunctions!=!0?null:t.Pipeline.registeredFunctions[e]},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn("Function is not registered with pipeline. This may cause problems when serialising the index.\n",e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(e){var i=t.Pipeline.getRegisteredFunction(e);if(!i)throw new Error("Cannot load un-registered function: "+e);n.add(i)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(e){t.Pipeline.warnIfFunctionNotRegistered(e),this._queue.push(e)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i+1,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var i=this._queue.indexOf(e);if(-1===i)throw new Error("Cannot find existingFn");this._queue.splice(i,0,n)},t.Pipeline.prototype.remove=function(e){var t=this._queue.indexOf(e);-1!==t&&this._queue.splice(t,1)},t.Pipeline.prototype.run=function(e){for(var t=[],n=e.length,i=this._queue.length,o=0;n>o;o++){for(var r=e[o],s=0;i>s&&(r=this._queue[s](r,o,e),void 0!==r&&null!==r);s++);void 0!==r&&null!==r&&t.push(r)}return t},t.Pipeline.prototype.reset=function(){this._queue=[]},t.Pipeline.prototype.get=function(){return this._queue},t.Pipeline.prototype.toJSON=function(){return this._queue.map(function(e){return t.Pipeline.warnIfFunctionNotRegistered(e),e.label})},t.Index=function(){this._fields=[],this._ref="id",this.pipeline=new t.Pipeline,this.documentStore=new t.DocumentStore,this.index={},this.eventEmitter=new t.EventEmitter,this._idfCache={},this.on("add","remove","update",function(){this._idfCache={}}.bind(this))},t.Index.prototype.on=function(){var e=Array.prototype.slice.call(arguments);return this.eventEmitter.addListener.apply(this.eventEmitter,e)},t.Index.prototype.off=function(e,t){return this.eventEmitter.removeListener(e,t)},t.Index.load=function(e){e.version!==t.version&&t.utils.warn("version mismatch: current "+t.version+" importing "+e.version);var n=new this;n._fields=e.fields,n._ref=e.ref,n.documentStore=t.DocumentStore.load(e.documentStore),n.pipeline=t.Pipeline.load(e.pipeline),n.index={};for(var i in e.index)n.index[i]=t.InvertedIndex.load(e.index[i]);return n},t.Index.prototype.addField=function(e){return this._fields.push(e),this.index[e]=new t.InvertedIndex,this},t.Index.prototype.setRef=function(e){return this._ref=e,this},t.Index.prototype.saveDocument=function(e){return this.documentStore=new t.DocumentStore(e),this},t.Index.prototype.addDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.addDoc(i,e),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));this.documentStore.addFieldLength(i,n,o.length);var r={};o.forEach(function(e){e in r?r[e]+=1:r[e]=1},this);for(var s in r){var u=r[s];u=Math.sqrt(u),this.index[n].addToken(s,{ref:i,tf:u})}},this),n&&this.eventEmitter.emit("add",e,this)}},t.Index.prototype.removeDocByRef=function(e){if(e&&this.documentStore.isDocStored()!==!1&&this.documentStore.hasDoc(e)){var t=this.documentStore.getDoc(e);this.removeDoc(t,!1)}},t.Index.prototype.removeDoc=function(e,n){if(e){var n=void 0===n?!0:n,i=e[this._ref];this.documentStore.hasDoc(i)&&(this.documentStore.removeDoc(i),this._fields.forEach(function(n){var o=this.pipeline.run(t.tokenizer(e[n]));o.forEach(function(e){this.index[n].removeToken(e,i)},this)},this),n&&this.eventEmitter.emit("remove",e,this))}},t.Index.prototype.updateDoc=function(e,t){var t=void 0===t?!0:t;this.removeDocByRef(e[this._ref],!1),this.addDoc(e,!1),t&&this.eventEmitter.emit("update",e,this)},t.Index.prototype.idf=function(e,t){var n="@"+t+"/"+e;if(Object.prototype.hasOwnProperty.call(this._idfCache,n))return this._idfCache[n];var i=this.index[t].getDocFreq(e),o=1+Math.log(this.documentStore.length/(i+1));return this._idfCache[n]=o,o},t.Index.prototype.getFields=function(){return this._fields.slice()},t.Index.prototype.search=function(e,n){if(!e)return[];e="string"==typeof e?{any:e}:JSON.parse(JSON.stringify(e));var i=null;null!=n&&(i=JSON.stringify(n));for(var o=new t.Configuration(i,this.getFields()).get(),r={},s=Object.keys(e),u=0;u0&&t.push(e);for(var i in n)"docs"!==i&&"df"!==i&&this.expandToken(e+i,t,n[i]);return t},t.InvertedIndex.prototype.toJSON=function(){return{root:this.root}},t.Configuration=function(e,n){var e=e||"";if(void 0==n||null==n)throw new Error("fields should not be null");this.config={};var i;try{i=JSON.parse(e),this.buildUserConfig(i,n)}catch(o){t.utils.warn("user configuration parse failed, will use default configuration"),this.buildDefaultConfig(n)}},t.Configuration.prototype.buildDefaultConfig=function(e){this.reset(),e.forEach(function(e){this.config[e]={boost:1,bool:"OR",expand:!1}},this)},t.Configuration.prototype.buildUserConfig=function(e,n){var i="OR",o=!1;if(this.reset(),"bool"in e&&(i=e.bool||i),"expand"in e&&(o=e.expand||o),"fields"in e)for(var r in e.fields)if(n.indexOf(r)>-1){var s=e.fields[r],u=o;void 0!=s.expand&&(u=s.expand),this.config[r]={boost:s.boost||0===s.boost?s.boost:1,bool:s.bool||i,expand:u}}else t.utils.warn("field name in user configuration not found in index instance fields");else this.addAllFields2UserConfig(i,o,n)},t.Configuration.prototype.addAllFields2UserConfig=function(e,t,n){n.forEach(function(n){this.config[n]={boost:1,bool:e,expand:t}},this)},t.Configuration.prototype.get=function(){return this.config},t.Configuration.prototype.reset=function(){this.config={}},lunr.SortedSet=function(){this.length=0,this.elements=[]},lunr.SortedSet.load=function(e){var t=new this;return t.elements=e,t.length=e.length,t},lunr.SortedSet.prototype.add=function(){var e,t;for(e=0;e1;){if(r===e)return o;e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o]}return r===e?o:-1},lunr.SortedSet.prototype.locationFor=function(e){for(var t=0,n=this.elements.length,i=n-t,o=t+Math.floor(i/2),r=this.elements[o];i>1;)e>r&&(t=o),r>e&&(n=o),i=n-t,o=t+Math.floor(i/2),r=this.elements[o];return r>e?o:e>r?o+1:void 0},lunr.SortedSet.prototype.intersect=function(e){for(var t=new lunr.SortedSet,n=0,i=0,o=this.length,r=e.length,s=this.elements,u=e.elements;;){if(n>o-1||i>r-1)break;s[n]!==u[i]?s[n]u[i]&&i++:(t.add(s[n]),n++,i++)}return t},lunr.SortedSet.prototype.clone=function(){var e=new lunr.SortedSet;return e.elements=this.toArray(),e.length=e.elements.length,e},lunr.SortedSet.prototype.union=function(e){var t,n,i;this.length>=e.length?(t=this,n=e):(t=e,n=this),i=t.clone();for(var o=0,r=n.toArray();oThis package implements the models of Shelegia and Motta (2021).

    \n\n

    \"GitHub\"\n\"PyPI\n\"GitHub\n\"GitHub\n\"CI\"\n\"PyPi\"\n\"PyPI\"\n\"PyPI\n\"GitHub\n\"GitHub

    \n\n

    Installation

    \n\n

    Installation over PyPI:

    \n\n
    pip install Shelegia-Motta-2021\n
    \n\n

    Or clone the repository via GitHub:

    \n\n
    git clone manuelbieri/shelegia_motta_2021\n
    \n\n

    Introduction

    \n\n

    Since all models implement the Shelegia_Motta_2021.IModel.IModel - Interface, therefore all models provide the same functionality (public methods), even though the results may change substantially.

    \n\n

    For all models add the following import statement:

    \n\n
    import Shelegia_Motta_2021.Models\n
    \n\n

    Models

    \n\n

    Base Model

    \n\n
    base_model = Shelegia_Motta_2021.Models.BaseModel()\n
    \n\n

    Bargaining Power Model

    \n\n
    bargaining_power_model = Shelegia_Motta_2021.Models.BargainingPowerModel()\n
    \n\n

    Unobservable Choices Model

    \n\n
    unobservable_model = Shelegia_Motta_2021.Models.UnobservableModel()\n
    \n\n

    Acquisition Model

    \n\n
    acquisition_model = Shelegia_Motta_2021.Models.AcquisitionModel()\n
    \n\n

    Basic usage

    \n\n
    # every model type can be plugged in without changing the following code.\nmodel: Shelegia_Motta_2021.IModel.IModel = Shelegia_Motta_2021.Models.BaseModel()\n\n# print string representation of the model\nprint(model)\n\n# plot the best answers of the incumbent to the choice of the entrant\nmodel.plot_incumbent_best_answers()\n\n# plot the equilibrium path\nmodel.plot_equilibrium()\n
    \n\n

    Dependencies

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n
    Package  Version  Annotation  
    matplotlib3.4.3Always needed (includes numpy)
    jupyter1.0.0Just for the demonstration in demo.ipynb
    pdoc8.0.1Only to generate the documentation from scratch
    \n\n


    \nThese packages include all the needed imports for the functionality of this package.

    \n\n

    Documentation

    \n\n

    For the latest version of the documentation open manuelbieri.github.io/shelegia_motta_2021 in your browser or call:

    \n\n
    import Shelegia_Motta_2021\n\nShelegia_Motta_2021.docs()\n
    \n\n

    Build Documentation

    \n\n

    Install the pdoc package:

    \n\n
    pip install pdoc\n
    \n\n

    Generate api-documentation with the following command:

    \n\n
    pdoc -o ./docs Shelegia_Motta_2021 --docformat \"numpy\" --math\n
    \n\n

    Additional Notes

    \n\n

    For further information about the coordinates used in the code, see dev_notes.md.

    \n"}, {"fullname": "Shelegia_Motta_2021.docs", "modulename": "Shelegia_Motta_2021", "qualname": "docs", "type": "function", "doc": "

    Opens the latest published version of the documentation of this package.

    \n", "parameters": [], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "", "type": "module", "doc": "

    \n"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel", "type": "class", "doc": "

    Interface for all models in Shelegia and Motta (2021).

    \n"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.__init__", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.__init__", "type": "function", "doc": "

    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.ENTRANT_CHOICES", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.ENTRANT_CHOICES", "type": "variable", "doc": "

    Contains all the possible product choices of the entrant.

    \n\n
      \n
    • complement (C)
    • \n
    • substitute (S)
    • \n
    • indifferent (I)
    • \n
    \n"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.INCUMBENT_CHOICES", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.INCUMBENT_CHOICES", "type": "variable", "doc": "

    Contains all the possible answers of the incumbent to the choice of the entrant.

    \n\n
      \n
    • copy (\u00a9)
    • \n
    • refrain (\u00d8)
    • \n
    \n"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.DEVELOPMENT_OUTCOME", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.DEVELOPMENT_OUTCOME", "type": "variable", "doc": "

    Contains all the possible outcomes of the development for the chosen product of the entrant or the merged entity.

    \n\n
      \n
    • success (Y)
    • \n
    • failure (N)
    • \n
    \n"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.get_asset_values", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.get_asset_values", "type": "function", "doc": "

    Returns the asset thresholds of the entrant.

    \n\n

    Number and type of the thresholds will be specific to the model.

    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the assets of the entrant.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.get_copying_fixed_costs_values", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.get_copying_fixed_costs_values", "type": "function", "doc": "

    Returns the fixed costs for copying thresholds of the incumbent.

    \n\n

    Number and type of the thresholds will be specific to the model.

    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the fixed costs for copying of the incumbent.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.get_payoffs", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.get_payoffs", "type": "function", "doc": "

    Returns the payoffs for different market configurations.

    \n\n

    A market configuration can include:

    \n\n
      \n
    • $I_P$ : Primary product sold by the incumbent.
    • \n
    • $I_C$ : Complementary product to $I_P$ potentially sold by the incumbent, which is copied from $E_C$.
    • \n
    • $E_P$ : Perfect substitute to $I_P$ potentially sold by the entrant.
    • \n
    • $E_C$ : Complementary product to $I_P$ currently sold by the entrant
    • \n
    • $\\tilde{E}_C$ : Complementary product to $I_P$ potentially sold by the entrant.\n
    • \n
    \n\n\n\n\n \n \n \n \n \n\n\n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n
    Market Config.$\\pi(I)$$\\pi(E)$CSW
    $I_P$ ; $E_C$N.A.N.A.N.A.N.A.
    $I_P + I_C$ ; $E_C$N.A.N.A.N.A.N.A.
    $I_P$ ; $E_P + E_C$N.A.N.A.N.A.N.A.
    $I_P + I_C$ ; $E_P + E_C$N.A.N.A.N.A.N.A.
    $I_P$ ; $E_C + \\tilde{E}_C$N.A.N.A.N.A.N.A.
    $I_P + I_C$ ; $E_C + \\tilde{E}_C$N.A.N.A.N.A.N.A.
    \n\n


    \nThe payoffs are specific to the models.

    \n\n
    Returns
    \n\n
      \n
    • Dict[str, Dict[str, float]]: Contains the mentioned payoffs for different market configurations.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.get_optimal_choice", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.get_optimal_choice", "type": "function", "doc": "

    Returns the optimal choice of the entrant and the incumbent based on a pair of assets of the entrant and fixed costs for copying of the incumbent.

    \n\n

    The output dictionary will contain the following details:

    \n\n
      \n
    • \"entrant\": choice of the entrant (possible choices listed in Shelegia_Motta_2021.IModel.IModel.ENTRANT_CHOICES))
    • \n
    • \"incumbent\": choice of the incumbent (possible choices listed in Shelegia_Motta_2021.IModel.IModel.INCUMBENT_CHOICES)
    • \n
    • \"development\": outcome of the development (possible outcomes listed in Shelegia_Motta_2021.IModel.IModel.DEVELOPMENT_OUTCOME)
    • \n
    \n\n
    Parameters
    \n\n
      \n
    • A (float):\nAssets of the entrant.
    • \n
    • F (float):\nFixed costs for copying of the incumbent.
    • \n
    \n\n
    Returns
    \n\n
      \n
    • Dict[str, str]: Optimal choice of the entrant, the incumbent and the outcome of the development.
    • \n
    \n", "parameters": ["self", "A", "F"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.plot_incumbent_best_answers", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.plot_incumbent_best_answers", "type": "function", "doc": "

    Plots the best answers of the incumbent to all possible actions of the entrant.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.plot_equilibrium", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.plot_equilibrium", "type": "function", "doc": "

    Plots the equilibrium path based on the choices of the entrant and incumbent.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.plot_payoffs", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.plot_payoffs", "type": "function", "doc": "

    Plots the payoffs for different market configurations.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models", "modulename": "Shelegia_Motta_2021.Models", "qualname": "", "type": "module", "doc": "

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel", "type": "class", "doc": "

    There are two players in our base model: The Incumbent, which sells the primary product, denoted by Ip, and a start-up, called the Entrant, which sells a product Ec complementary to Ip. (One may think of Ip as a platform, and Ec as a service or product which can be accessed through the platform.) We are interested in studying the choice of E between developing a substitute to Ip, denoted by Ep, or another complement to Ip, denoted by \u1ebcc and the choice of I between copying E\u2019s original complementary product Ec by creating a perfect substitute Ic, or not. Since E may not have enough assets to cover the development cost of its second product, copying its current product will affect the entrant\u2019s ability to obtain funding for the development. We shall show that the incumbent has a strategic incentive to copy when the entrant plans to compete, and to abstain from copying when it plans to create another complement.

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.__init__", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.__init__", "type": "function", "doc": "

    Initializes a valid BaseModel object.

    \n\n

    The following preconditions have to be satisfied:

    \n\n
      \n
    • (A1b) $\\delta$ / 2 < $\\Delta$ < 3 * $\\delta$ / 2
    • \n
    • (A2) K < $\\delta$ / 2
    • \n
    \n\n
    Parameters
    \n\n
      \n
    • u (float):\nUtility gained from consuming the primary product.
    • \n
    • B (float):\nMinimal difference between the return in case of a success and the return in case of failure of E. B is called the private benefit of the entrant in case of failure.
    • \n
    • small_delta (float):\n($\\delta$) Additional utility gained from a complement combined with a primary product.
    • \n
    • delta (float):\n($\\Delta$) Additional utility gained from the substitute of the entrant compared to the primary product of the incumbent.
    • \n
    • K (float):\nInvestment costs for the entrant to develop a second product.
    • \n
    \n", "parameters": ["self", "u", "B", "small_delta", "delta", "K"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.tolerance", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.tolerance", "type": "variable", "doc": "

    Tolerance for the comparison of two floating numbers.

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.get_asset_values", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.get_asset_values", "type": "function", "doc": "

    Returns the asset thresholds of the entrant.

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n
    Threshold $\\:\\:\\:\\:\\:$Name $\\:\\:\\:\\:\\:$Formula $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $A_S$A_s$(2)\\: B + K - \\Delta - 3\\delta/2$
    $A_C$A_c$(3)\\: B + K - 3\\delta/2$
    $\\overline{A}_S$A-s$(4)\\: B + K - \\Delta$
    $\\overline{A}_C$A-c$(5)\\: B + K - \\delta/2$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the assets of the entrant.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.get_copying_fixed_costs_values", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.get_copying_fixed_costs_values", "type": "function", "doc": "

    Returns the fixed costs for copying thresholds of the incumbent.

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n
    Threshold $\\:\\:\\:\\:\\:$Name $\\:\\:\\:\\:\\:$Formula $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $F^{YY}_S$F(YY)s$(6)\\: \\delta/2$
    $F^{YN}_S$F(YN)s$(6)\\: u + 3\\delta/2$
    $F^{YY}_C$F(YY)c$(6)\\: \\delta$
    $F^{YN}_C$F(YN)c$(6)\\: \\delta/2$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the fixed costs for copying of the incumbent.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.get_payoffs", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.get_payoffs", "type": "function", "doc": "

    Returns the payoffs for different market configurations.

    \n\n

    A market configuration can include:

    \n\n
      \n
    • $I_P$ : Primary product sold by the incumbent.
    • \n
    • $I_C$ : Complementary product to $I_P$ potentially sold by the incumbent, which is copied from $E_C$.
    • \n
    • $E_P$ : Perfect substitute to $I_P$ potentially sold by the entrant.
    • \n
    • $E_C$ : Complementary product to $I_P$ currently sold by the entrant
    • \n
    • $\\tilde{E}_C$ : Complementary product to $I_P$ potentially sold by the entrant.\n
    • \n
    \n\n\n\n\n \n \n \n \n \n\n\n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n
    Market Config. $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$$\\pi(I) \\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$$\\pi(E) \\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$CS $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$W $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $I_P$ ; $E_C$$u + \\delta/2$$\\delta/2$0$u + \\delta$
    $I_P + I_C$ ; $E_C$$u + \\delta$00$u + \\delta$
    $I_P$ ; $E_P + E_C$0$\\Delta + \\delta$$u$$u + \\Delta + \\delta$
    $I_P + I_C$ ; $E_P + E_C$0$\\Delta$$u + \\delta$$u + \\Delta + \\delta$
    $I_P$ ; $E_C + \\tilde{E}_C$$u + \\delta$$\\delta$0$u + 2\\delta$
    $I_P + I_C$ ; $E_C + \\tilde{E}_C$$u + 3\\delta/2$$\\delta/2$0$u + 2\\delta$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, Dict[str, float]]: Contains the mentioned payoffs for different market configurations.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.get_optimal_choice", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.get_optimal_choice", "type": "function", "doc": "

    Returns the optimal choice of the entrant and the incumbent based on a pair of assets of the entrant and fixed costs for copying of the incumbent.

    \n\n

    The output dictionary will contain the following details:

    \n\n
      \n
    • \"entrant\": choice of the entrant (possible choices listed in Shelegia_Motta_2021.IModel.IModel.ENTRANT_CHOICES))
    • \n
    • \"incumbent\": choice of the incumbent (possible choices listed in Shelegia_Motta_2021.IModel.IModel.INCUMBENT_CHOICES)
    • \n
    • \"development\": outcome of the development (possible outcomes listed in Shelegia_Motta_2021.IModel.IModel.DEVELOPMENT_OUTCOME)
    • \n
    \n\n
    Parameters
    \n\n
      \n
    • A (float):\nAssets of the entrant.
    • \n
    • F (float):\nFixed costs for copying of the incumbent.
    • \n
    \n\n
    Returns
    \n\n
      \n
    • Dict[str, str]: Optimal choice of the entrant, the incumbent and the outcome of the development.
    • \n
    \n", "parameters": ["self", "A", "F"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.plot_incumbent_best_answers", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.plot_incumbent_best_answers", "type": "function", "doc": "

    Plots the best answers of the incumbent to all possible actions of the entrant.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.plot_equilibrium", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.plot_equilibrium", "type": "function", "doc": "

    Plots the equilibrium path based on the choices of the entrant and incumbent.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.plot_payoffs", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.plot_payoffs", "type": "function", "doc": "

    Plots the payoffs for different market configurations.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BargainingPowerModel", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BargainingPowerModel", "type": "class", "doc": "

    Besides the parameters used in the paper, this class will introduce the parameter $\\beta$ in the models, called\nthe bargaining power of the incumbent. In the paper the default value 0.5 is used to derive the results.

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.BargainingPowerModel.__init__", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BargainingPowerModel.__init__", "type": "function", "doc": "

    Besides $\\beta$ the parameters in this model do not change compared to Shelegia_Motta_2021.Models.BaseModel.

    \n\n
    Parameters
    \n\n
      \n
    • beta (float):\nBargaining power of the incumbent relative to the entrant ($0 < \\beta < 1$).
    • \n
    \n", "parameters": ["self", "u", "B", "small_delta", "delta", "K", "beta"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BargainingPowerModel.get_asset_values", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BargainingPowerModel.get_asset_values", "type": "function", "doc": "

    Returns the asset thresholds of the entrant.

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n
    Threshold $\\:\\:\\:\\:\\:$Name $\\:\\:\\:\\:\\:$Formula $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $A_S$A_s$B + K - \\Delta - \\delta(2 - \\beta)$
    $A_C$A_c$B + K - 3\\delta(1 - \\beta)$
    $\\overline{A}_S$A-s$B + K - \\Delta$
    $\\overline{A}_C$A-c$B + K - \\delta(1 - \\beta)$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the assets of the entrant.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BargainingPowerModel.get_copying_fixed_costs_values", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BargainingPowerModel.get_copying_fixed_costs_values", "type": "function", "doc": "

    Returns the fixed costs for copying thresholds of the incumbent.

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n
    Threshold $\\:\\:\\:\\:\\:$Name $\\:\\:\\:\\:\\:$Formula $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $F^{YY}_S$F(YY)s$\\delta(1 - \\beta)$
    $F^{YN}_S$F(YN)s$u + \\delta(2 - \\beta)$
    $F^{YY}_C$F(YY)c$2\\delta(1 - \\beta)$
    $F^{YN}_C$F(YN)c$\\delta(2 - \\beta)$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the fixed costs for copying of the incumbent.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BargainingPowerModel.get_payoffs", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BargainingPowerModel.get_payoffs", "type": "function", "doc": "

    Returns the payoffs for different market configurations.

    \n\n

    A market configuration can include:

    \n\n
      \n
    • $I_P$ : Primary product sold by the incumbent.
    • \n
    • $I_C$ : Complementary product to $I_P$ potentially sold by the incumbent, which is copied from $E_C$.
    • \n
    • $E_P$ : Perfect substitute to $I_P$ potentially sold by the entrant.
    • \n
    • $E_C$ : Complementary product to $I_P$ currently sold by the entrant
    • \n
    • $\\tilde{E}_C$ : Complementary product to $I_P$ potentially sold by the entrant.\n
    • \n
    \n\n\n\n\n \n \n \n \n \n\n\n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n
    Market Config. $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$$\\pi(I) \\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$$\\pi(E) \\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$CS $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$W $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $I_P$ ; $E_C$$u + \\delta\\beta$$\\delta(1 - \\beta)$0$u + \\delta$
    $I_P + I_C$ ; $E_C$$u + \\delta$00$u + \\delta$
    $I_P$ ; $E_P + E_C$0$\\Delta + \\delta$$u$$u + \\Delta + \\delta$
    $I_P + I_C$ ; $E_P + E_C$0$\\Delta$$u + \\delta$$u + \\Delta + \\delta$
    $I_P$ ; $E_C + \\tilde{E}_C$$u + 2\\delta\\beta$$2\\delta(1 - \\beta)$0$u + 2\\delta$
    $I_P + I_C$ ; $E_C + \\tilde{E}_C$$u + \\delta(1 + \\beta)$$\\delta(1 - \\beta)$0$u + 2\\delta$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, Dict[str, float]]: Contains the mentioned payoffs for different market configurations.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.UnobservableModel", "modulename": "Shelegia_Motta_2021.Models", "qualname": "UnobservableModel", "type": "class", "doc": "

    This model indicates that if the incumbent were not able to observe the entrant at the moment of choosing, the \u201ckill zone\u201d effect whereby the entrant stays away from the substitute in order to avoid being copied) would not take place. Intuitively, in the game as we studied it so far, the only reason why the entrant is choosing a trajectory leading to another complement is that it anticipates that if it chose one leading to a substitute, the incumbent would copy, making it an inefficient strategy for entering the market. However, if the incumbent cannot observe the entrant\u2019s choice of strategy, the entrant could not hope to strategically affect the decision of the incumbent. This would lead to the entrant having a host of new opportunities when entering the market and it makes competing with a large company much more attractive.

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.UnobservableModel.__init__", "modulename": "Shelegia_Motta_2021.Models", "qualname": "UnobservableModel.__init__", "type": "function", "doc": "

    The parameters do not change compared to Shelegia_Motta_2021.Models.BargainingPowerModel.

    \n", "parameters": ["self", "u", "B", "small_delta", "delta", "K", "beta"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.UnobservableModel.plot_incumbent_best_answers", "modulename": "Shelegia_Motta_2021.Models", "qualname": "UnobservableModel.plot_incumbent_best_answers", "type": "function", "doc": "

    Plots the best answers of the incumbent to all possible actions of the entrant.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.AcquisitionModel", "modulename": "Shelegia_Motta_2021.Models", "qualname": "AcquisitionModel", "type": "class", "doc": "

    In order to explore how acquisitions may modify the entrant\u2019s and the incumbent\u2019s strategic choices, we extend the base model in order to allow an acquisition to take place after the incumbent commits to copying the entrant\u2019s original complementary product (between t=1 and t=2, see table 2). We assume that the incumbent and the entrant share the gains (if any) attained from the acquisition equally.

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.AcquisitionModel.__init__", "modulename": "Shelegia_Motta_2021.Models", "qualname": "AcquisitionModel.__init__", "type": "function", "doc": "

    An additional constraint is added compared to Shelegia_Motta_2021.Models.BaseModel. Namely, $\\Delta$ has to be bigger than $\\delta$, meaning the innovation of the entrant is not too drastic.

    \n\n

    Meanwhile, the parameters do not change compared to Shelegia_Motta_2021.Models.BargainingPowerModel.

    \n", "parameters": ["self", "u", "B", "small_delta", "delta", "K"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.AcquisitionModel.get_copying_fixed_costs_values", "modulename": "Shelegia_Motta_2021.Models", "qualname": "AcquisitionModel.get_copying_fixed_costs_values", "type": "function", "doc": "

    Returns the fixed costs for copying thresholds of the incumbent.

    \n\n

    Additional thresholds for the fixed cost of copying of the incumbent compared to the Shelegia_Motta_2021.Models.BargainingModel:

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n
    Threshold $\\:\\:\\:\\:\\:$Name $\\:\\:\\:\\:\\:$Formula $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $F^{ACQ}_S$F(ACQ)s$\\frac{(u + \\Delta - K)}{2} + \\delta(2 - \\beta)$
    $F^{ACQ}_C$F(ACQ)c$\\frac{K}{2} + \\delta(2.5 - 3\\beta)$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the fixed costs for copying of the incumbent.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}]; + /** pdoc search index */const docs = [{"fullname": "Shelegia_Motta_2021", "modulename": "Shelegia_Motta_2021", "qualname": "", "type": "module", "doc": "

    This package implements the models of Shelegia and Motta (2021).

    \n\n

    \"GitHub\"\n\"PyPI\n\"GitHub\n\"GitHub\n\"CI\"\n\"PyPi\"\n\"PyPI\"\n\"PyPI\n\"GitHub\n\"GitHub

    \n\n

    Installation

    \n\n

    Installation over PyPI:

    \n\n
    pip install Shelegia-Motta-2021\n
    \n\n

    Or clone the repository via GitHub:

    \n\n
    git clone https://github.com/manuelbieri/shelegia_motta_2021.git\n
    \n\n

    Introduction

    \n\n

    Since all models implement the Shelegia_Motta_2021.IModel.IModel - Interface, therefore all models provide the same functionality (public methods), even though the results may change substantially.

    \n\n

    For all models add the following import statement:

    \n\n
    import Shelegia_Motta_2021.Models\n
    \n\n

    Models

    \n\n

    Base Model

    \n\n
    base_model = Shelegia_Motta_2021.Models.BaseModel()\n
    \n\n

    Bargaining Power Model

    \n\n
    bargaining_power_model = Shelegia_Motta_2021.Models.BargainingPowerModel()\n
    \n\n

    Unobservable Choices Model

    \n\n
    unobservable_model = Shelegia_Motta_2021.Models.UnobservableModel()\n
    \n\n

    Acquisition Model

    \n\n
    acquisition_model = Shelegia_Motta_2021.Models.AcquisitionModel()\n
    \n\n

    Basic usage

    \n\n
    # every model type can be plugged in without changing the following code.\nmodel: Shelegia_Motta_2021.IModel.IModel = Shelegia_Motta_2021.Models.BaseModel()\n\n# print string representation of the model\nprint(model)\n\n# plot the best answers of the incumbent to the choice of the entrant\nmodel.plot_incumbent_best_answers()\n\n# plot the equilibrium path\nmodel.plot_equilibrium()\n
    \n\n

    Dependencies

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n
    Package  Version  Annotation  
    matplotlib3.4.3Always needed (includes numpy)
    jupyter1.0.0Just for the demonstration in demo.ipynb
    pdoc8.0.1Only to generate the documentation from scratch
    \n\n


    \nThese packages include all the needed imports for the functionality of this package.

    \n\n

    Documentation

    \n\n

    For the latest version of the documentation open manuelbieri.github.io/shelegia_motta_2021 in your browser or call:

    \n\n
    import Shelegia_Motta_2021\n\nShelegia_Motta_2021.docs()\n
    \n\n

    Build Documentation

    \n\n

    Install the pdoc package:

    \n\n
    pip install pdoc\n
    \n\n

    Generate api-documentation with the following command:

    \n\n
    pdoc -o ./docs Shelegia_Motta_2021 --docformat \"numpy\" --math\n
    \n\n

    Additional Notes

    \n\n

    For further information about the coordinates used in the code, see resources/dev_notes.md.

    \n"}, {"fullname": "Shelegia_Motta_2021.docs", "modulename": "Shelegia_Motta_2021", "qualname": "docs", "type": "function", "doc": "

    Opens the latest published version of the documentation of this package.

    \n", "parameters": [], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "", "type": "module", "doc": "

    \n"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel", "type": "class", "doc": "

    Interface for all models in Shelegia and Motta (2021).

    \n"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.__init__", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.__init__", "type": "function", "doc": "

    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.ENTRANT_CHOICES", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.ENTRANT_CHOICES", "type": "variable", "doc": "

    Contains all the possible product choices of the entrant.

    \n\n
      \n
    • complement (C)
    • \n
    • substitute (S)
    • \n
    • indifferent (I)
    • \n
    \n"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.INCUMBENT_CHOICES", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.INCUMBENT_CHOICES", "type": "variable", "doc": "

    Contains all the possible answers of the incumbent to the choice of the entrant.

    \n\n
      \n
    • copy (\u00a9)
    • \n
    • refrain (\u00d8)
    • \n
    \n"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.DEVELOPMENT_OUTCOME", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.DEVELOPMENT_OUTCOME", "type": "variable", "doc": "

    Contains all the possible outcomes of the development for the chosen product of the entrant or the merged entity.

    \n\n
      \n
    • success (Y)
    • \n
    • failure (N)
    • \n
    \n"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.get_asset_values", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.get_asset_values", "type": "function", "doc": "

    Returns the asset thresholds of the entrant.

    \n\n

    Number and type of the thresholds will be specific to the model.

    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the assets of the entrant.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.get_copying_fixed_costs_values", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.get_copying_fixed_costs_values", "type": "function", "doc": "

    Returns the fixed costs for copying thresholds of the incumbent.

    \n\n

    Number and type of the thresholds will be specific to the model.

    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the fixed costs for copying of the incumbent.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.get_payoffs", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.get_payoffs", "type": "function", "doc": "

    Returns the payoffs for different market configurations.

    \n\n

    A market configuration can include:

    \n\n
      \n
    • $I_P$ : Primary product sold by the incumbent.
    • \n
    • $I_C$ : Complementary product to $I_P$ potentially sold by the incumbent, which is copied from $E_C$.
    • \n
    • $E_P$ : Perfect substitute to $I_P$ potentially sold by the entrant.
    • \n
    • $E_C$ : Complementary product to $I_P$ currently sold by the entrant
    • \n
    • $\\tilde{E}_C$ : Complementary product to $I_P$ potentially sold by the entrant.\n
    • \n
    \n\n\n\n\n \n \n \n \n \n\n\n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n
    Market Config.$\\pi(I)$$\\pi(E)$CSW
    $I_P$ ; $E_C$N.A.N.A.N.A.N.A.
    $I_P + I_C$ ; $E_C$N.A.N.A.N.A.N.A.
    $I_P$ ; $E_P + E_C$N.A.N.A.N.A.N.A.
    $I_P + I_C$ ; $E_P + E_C$N.A.N.A.N.A.N.A.
    $I_P$ ; $E_C + \\tilde{E}_C$N.A.N.A.N.A.N.A.
    $I_P + I_C$ ; $E_C + \\tilde{E}_C$N.A.N.A.N.A.N.A.
    \n\n


    \nThe payoffs are specific to the models.

    \n\n
    Returns
    \n\n
      \n
    • Dict[str, Dict[str, float]]: Contains the mentioned payoffs for different market configurations.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.get_optimal_choice", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.get_optimal_choice", "type": "function", "doc": "

    Returns the optimal choice of the entrant and the incumbent based on a pair of assets of the entrant and fixed costs for copying of the incumbent.

    \n\n

    The output dictionary will contain the following details:

    \n\n
      \n
    • \"entrant\": choice of the entrant (possible choices listed in Shelegia_Motta_2021.IModel.IModel.ENTRANT_CHOICES))
    • \n
    • \"incumbent\": choice of the incumbent (possible choices listed in Shelegia_Motta_2021.IModel.IModel.INCUMBENT_CHOICES)
    • \n
    • \"development\": outcome of the development (possible outcomes listed in Shelegia_Motta_2021.IModel.IModel.DEVELOPMENT_OUTCOME)
    • \n
    \n\n
    Parameters
    \n\n
      \n
    • A (float):\nAssets of the entrant.
    • \n
    • F (float):\nFixed costs for copying of the incumbent.
    • \n
    \n\n
    Returns
    \n\n
      \n
    • Dict[str, str]: Optimal choice of the entrant, the incumbent and the outcome of the development.
    • \n
    \n", "parameters": ["self", "A", "F"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.plot_incumbent_best_answers", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.plot_incumbent_best_answers", "type": "function", "doc": "

    Plots the best answers of the incumbent to all possible actions of the entrant.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    • **kwargs: Optional key word arguments for the best answers plot.
      \n
        \n
      • title: title on top of the plot, instead of the default title.
      • \n
      • options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
      • \n
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis", "kwargs"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.plot_equilibrium", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.plot_equilibrium", "type": "function", "doc": "

    Plots the equilibrium path based on the choices of the entrant and incumbent.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    • **kwargs: Optional key word arguments for the equilibrium plot.
      \n
        \n
      • title: title on top of the plot, instead of the default title.
      • \n
      • options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
      • \n
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis", "kwargs"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.IModel.IModel.plot_payoffs", "modulename": "Shelegia_Motta_2021.IModel", "qualname": "IModel.plot_payoffs", "type": "function", "doc": "

    Plots the payoffs for different market configurations.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models", "modulename": "Shelegia_Motta_2021.Models", "qualname": "", "type": "module", "doc": "

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel", "type": "class", "doc": "

    There are two players in our base model: The Incumbent, which sells the primary product, denoted by Ip, and a start-up, called the Entrant, which sells a product Ec complementary to Ip. (One may think of Ip as a platform, and Ec as a service or product which can be accessed through the platform.) We are interested in studying the choice of E between developing a substitute to Ip, denoted by Ep, or another complement to Ip, denoted by \u1ebcc and the choice of I between copying E\u2019s original complementary product Ec by creating a perfect substitute Ic, or not. Since E may not have enough assets to cover the development cost of its second product, copying its current product will affect the entrant\u2019s ability to obtain funding for the development. We shall show that the incumbent has a strategic incentive to copy when the entrant plans to compete, and to abstain from copying when it plans to create another complement.

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.__init__", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.__init__", "type": "function", "doc": "

    Initializes a valid BaseModel object.

    \n\n

    The following preconditions have to be satisfied:

    \n\n
      \n
    • (A1b) $\\delta$ / 2 < $\\Delta$ < 3 * $\\delta$ / 2
    • \n
    • (A2) K < $\\delta$ / 2
    • \n
    \n\n
    Parameters
    \n\n
      \n
    • u (float):\nUtility gained from consuming the primary product.
    • \n
    • B (float):\nMinimal difference between the return in case of a success and the return in case of failure of E. B is called the private benefit of the entrant in case of failure.
    • \n
    • small_delta (float):\n($\\delta$) Additional utility gained from a complement combined with a primary product.
    • \n
    • delta (float):\n($\\Delta$) Additional utility gained from the substitute of the entrant compared to the primary product of the incumbent.
    • \n
    • K (float):\nInvestment costs for the entrant to develop a second product.
    • \n
    \n", "parameters": ["self", "u", "B", "small_delta", "delta", "K"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.TOLERANCE", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.TOLERANCE", "type": "variable", "doc": "

    Tolerance for the comparison of two floating numbers.

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.get_asset_values", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.get_asset_values", "type": "function", "doc": "

    Returns the asset thresholds of the entrant.

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n
    Threshold $\\:\\:\\:\\:\\:$Name $\\:\\:\\:\\:\\:$Formula $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $A_S$A_s$(2)\\: B + K - \\Delta - 3\\delta/2$
    $A_C$A_c$(3)\\: B + K - 3\\delta/2$
    $\\overline{A}_S$A-s$(4)\\: B + K - \\Delta$
    $\\overline{A}_C$A-c$(5)\\: B + K - \\delta/2$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the assets of the entrant.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.get_copying_fixed_costs_values", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.get_copying_fixed_costs_values", "type": "function", "doc": "

    Returns the fixed costs for copying thresholds of the incumbent.

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n
    Threshold $\\:\\:\\:\\:\\:$Name $\\:\\:\\:\\:\\:$Formula $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $F^{YY}_S$F(YY)s$(6)\\: \\delta/2$
    $F^{YN}_S$F(YN)s$(6)\\: u + 3\\delta/2$
    $F^{YY}_C$F(YY)c$(6)\\: \\delta$
    $F^{YN}_C$F(YN)c$(6)\\: \\delta/2$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the fixed costs for copying of the incumbent.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.get_payoffs", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.get_payoffs", "type": "function", "doc": "

    Returns the payoffs for different market configurations.

    \n\n

    A market configuration can include:

    \n\n
      \n
    • $I_P$ : Primary product sold by the incumbent.
    • \n
    • $I_C$ : Complementary product to $I_P$ potentially sold by the incumbent, which is copied from $E_C$.
    • \n
    • $E_P$ : Perfect substitute to $I_P$ potentially sold by the entrant.
    • \n
    • $E_C$ : Complementary product to $I_P$ currently sold by the entrant
    • \n
    • $\\tilde{E}_C$ : Complementary product to $I_P$ potentially sold by the entrant.\n
    • \n
    \n\n\n\n\n \n \n \n \n \n\n\n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n
    Market Config. $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$$\\pi(I) \\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$$\\pi(E) \\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$CS $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$W $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $I_P$ ; $E_C$$u + \\delta/2$$\\delta/2$0$u + \\delta$
    $I_P + I_C$ ; $E_C$$u + \\delta$00$u + \\delta$
    $I_P$ ; $E_P + E_C$0$\\Delta + \\delta$$u$$u + \\Delta + \\delta$
    $I_P + I_C$ ; $E_P + E_C$0$\\Delta$$u + \\delta$$u + \\Delta + \\delta$
    $I_P$ ; $E_C + \\tilde{E}_C$$u + \\delta$$\\delta$0$u + 2\\delta$
    $I_P + I_C$ ; $E_C + \\tilde{E}_C$$u + 3\\delta/2$$\\delta/2$0$u + 2\\delta$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, Dict[str, float]]: Contains the mentioned payoffs for different market configurations.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.get_optimal_choice", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.get_optimal_choice", "type": "function", "doc": "

    Returns the optimal choice of the entrant and the incumbent based on a pair of assets of the entrant and fixed costs for copying of the incumbent.

    \n\n

    The output dictionary will contain the following details:

    \n\n
      \n
    • \"entrant\": choice of the entrant (possible choices listed in Shelegia_Motta_2021.IModel.IModel.ENTRANT_CHOICES))
    • \n
    • \"incumbent\": choice of the incumbent (possible choices listed in Shelegia_Motta_2021.IModel.IModel.INCUMBENT_CHOICES)
    • \n
    • \"development\": outcome of the development (possible outcomes listed in Shelegia_Motta_2021.IModel.IModel.DEVELOPMENT_OUTCOME)
    • \n
    \n\n
    Parameters
    \n\n
      \n
    • A (float):\nAssets of the entrant.
    • \n
    • F (float):\nFixed costs for copying of the incumbent.
    • \n
    \n\n
    Returns
    \n\n
      \n
    • Dict[str, str]: Optimal choice of the entrant, the incumbent and the outcome of the development.
    • \n
    \n", "parameters": ["self", "A", "F"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.plot_incumbent_best_answers", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.plot_incumbent_best_answers", "type": "function", "doc": "

    Plots the best answers of the incumbent to all possible actions of the entrant.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    • **kwargs: Optional key word arguments for the best answers plot.
      \n
        \n
      • title: title on top of the plot, instead of the default title.
      • \n
      • options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
      • \n
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis", "kwargs"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.plot_equilibrium", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.plot_equilibrium", "type": "function", "doc": "

    Plots the equilibrium path based on the choices of the entrant and incumbent.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    • **kwargs: Optional key word arguments for the equilibrium plot.
      \n
        \n
      • title: title on top of the plot, instead of the default title.
      • \n
      • options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
      • \n
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis", "kwargs"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BaseModel.plot_payoffs", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BaseModel.plot_payoffs", "type": "function", "doc": "

    Plots the payoffs for different market configurations.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BargainingPowerModel", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BargainingPowerModel", "type": "class", "doc": "

    Besides the parameters used in the paper, this class will introduce the parameter $\\beta$ in the models, called\nthe bargaining power of the incumbent. In the paper the default value 0.5 is used to derive the results.

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.BargainingPowerModel.__init__", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BargainingPowerModel.__init__", "type": "function", "doc": "

    Besides $\\beta$ the parameters in this model do not change compared to Shelegia_Motta_2021.Models.BaseModel.

    \n\n
    Parameters
    \n\n
      \n
    • beta (float):\nBargaining power of the incumbent relative to the entrant ($0 < \\beta < 1$).
    • \n
    \n", "parameters": ["self", "u", "B", "small_delta", "delta", "K", "beta"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BargainingPowerModel.get_asset_values", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BargainingPowerModel.get_asset_values", "type": "function", "doc": "

    Returns the asset thresholds of the entrant.

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n
    Threshold $\\:\\:\\:\\:\\:$Name $\\:\\:\\:\\:\\:$Formula $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $A_S$A_s$B + K - \\Delta - \\delta(2 - \\beta)$
    $A_C$A_c$B + K - 3\\delta(1 - \\beta)$
    $\\overline{A}_S$A-s$B + K - \\Delta$
    $\\overline{A}_C$A-c$B + K - \\delta(1 - \\beta)$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the assets of the entrant.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BargainingPowerModel.get_copying_fixed_costs_values", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BargainingPowerModel.get_copying_fixed_costs_values", "type": "function", "doc": "

    Returns the fixed costs for copying thresholds of the incumbent.

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n \n \n \n\n\n
    Threshold $\\:\\:\\:\\:\\:$Name $\\:\\:\\:\\:\\:$Formula $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $F^{YY}_S$F(YY)s$\\delta(1 - \\beta)$
    $F^{YN}_S$F(YN)s$u + \\delta(2 - \\beta)$
    $F^{YY}_C$F(YY)c$2\\delta(1 - \\beta)$
    $F^{YN}_C$F(YN)c$\\delta(2 - \\beta)$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the fixed costs for copying of the incumbent.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.BargainingPowerModel.get_payoffs", "modulename": "Shelegia_Motta_2021.Models", "qualname": "BargainingPowerModel.get_payoffs", "type": "function", "doc": "

    Returns the payoffs for different market configurations.

    \n\n

    A market configuration can include:

    \n\n
      \n
    • $I_P$ : Primary product sold by the incumbent.
    • \n
    • $I_C$ : Complementary product to $I_P$ potentially sold by the incumbent, which is copied from $E_C$.
    • \n
    • $E_P$ : Perfect substitute to $I_P$ potentially sold by the entrant.
    • \n
    • $E_C$ : Complementary product to $I_P$ currently sold by the entrant
    • \n
    • $\\tilde{E}_C$ : Complementary product to $I_P$ potentially sold by the entrant.\n
    • \n
    \n\n\n\n\n \n \n \n \n \n\n\n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n \n \n \n \n \n\n\n
    Market Config. $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$$\\pi(I) \\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$$\\pi(E) \\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$CS $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$W $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $I_P$ ; $E_C$$u + \\delta\\beta$$\\delta(1 - \\beta)$0$u + \\delta$
    $I_P + I_C$ ; $E_C$$u + \\delta$00$u + \\delta$
    $I_P$ ; $E_P + E_C$0$\\Delta + \\delta$$u$$u + \\Delta + \\delta$
    $I_P + I_C$ ; $E_P + E_C$0$\\Delta$$u + \\delta$$u + \\Delta + \\delta$
    $I_P$ ; $E_C + \\tilde{E}_C$$u + 2\\delta\\beta$$2\\delta(1 - \\beta)$0$u + 2\\delta$
    $I_P + I_C$ ; $E_C + \\tilde{E}_C$$u + \\delta(1 + \\beta)$$\\delta(1 - \\beta)$0$u + 2\\delta$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, Dict[str, float]]: Contains the mentioned payoffs for different market configurations.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.UnobservableModel", "modulename": "Shelegia_Motta_2021.Models", "qualname": "UnobservableModel", "type": "class", "doc": "

    This model indicates that if the incumbent were not able to observe the entrant at the moment of choosing, the \u201ckill zone\u201d effect whereby the entrant stays away from the substitute in order to avoid being copied) would not take place. Intuitively, in the game as we studied it so far, the only reason why the entrant is choosing a trajectory leading to another complement is that it anticipates that if it chose one leading to a substitute, the incumbent would copy, making it an inefficient strategy for entering the market. However, if the incumbent cannot observe the entrant\u2019s choice of strategy, the entrant could not hope to strategically affect the decision of the incumbent. This would lead to the entrant having a host of new opportunities when entering the market and it makes competing with a large company much more attractive.

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.UnobservableModel.__init__", "modulename": "Shelegia_Motta_2021.Models", "qualname": "UnobservableModel.__init__", "type": "function", "doc": "

    The parameters do not change compared to Shelegia_Motta_2021.Models.BargainingPowerModel.

    \n", "parameters": ["self", "u", "B", "small_delta", "delta", "K", "beta"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.UnobservableModel.plot_incumbent_best_answers", "modulename": "Shelegia_Motta_2021.Models", "qualname": "UnobservableModel.plot_incumbent_best_answers", "type": "function", "doc": "

    Plots the best answers of the incumbent to all possible actions of the entrant.

    \n\n
    Parameters
    \n\n
      \n
    • axis (matplotlib.axes.Axes):\nAxis to draw the plot on. (optional)
    • \n
    • **kwargs: Optional key word arguments for the best answers plot.
      \n
        \n
      • title: title on top of the plot, instead of the default title.
      • \n
      • options_legend: If true, an additional legend, explaining the options of the entrant and the incumbent, will be added to the plot.
      • \n
    • \n
    \n\n
    Returns
    \n\n
      \n
    • matplotlib.axes.Axes: Axis containing the plot.
    • \n
    \n", "parameters": ["self", "axis", "kwargs"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.UnobservableModel.get_optimal_choice", "modulename": "Shelegia_Motta_2021.Models", "qualname": "UnobservableModel.get_optimal_choice", "type": "function", "doc": "

    Returns the optimal choice of the entrant and the incumbent based on a pair of assets of the entrant and fixed costs for copying of the incumbent.

    \n\n

    The output dictionary will contain the following details:

    \n\n
      \n
    • \"entrant\": choice of the entrant (possible choices listed in Shelegia_Motta_2021.IModel.IModel.ENTRANT_CHOICES))
    • \n
    • \"incumbent\": choice of the incumbent (possible choices listed in Shelegia_Motta_2021.IModel.IModel.INCUMBENT_CHOICES)
    • \n
    • \"development\": outcome of the development (possible outcomes listed in Shelegia_Motta_2021.IModel.IModel.DEVELOPMENT_OUTCOME)
    • \n
    \n\n
    Parameters
    \n\n
      \n
    • A (float):\nAssets of the entrant.
    • \n
    • F (float):\nFixed costs for copying of the incumbent.
    • \n
    \n\n
    Returns
    \n\n
      \n
    • Dict[str, str]: Optimal choice of the entrant, the incumbent and the outcome of the development.
    • \n
    \n", "parameters": ["self", "A", "F"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.AcquisitionModel", "modulename": "Shelegia_Motta_2021.Models", "qualname": "AcquisitionModel", "type": "class", "doc": "

    In order to explore how acquisitions may modify the entrant\u2019s and the incumbent\u2019s strategic choices, we extend the base model in order to allow an acquisition to take place after the incumbent commits to copying the entrant\u2019s original complementary product (between t=1 and t=2, see table 2). We assume that the incumbent and the entrant share the gains (if any) attained from the acquisition equally.

    \n"}, {"fullname": "Shelegia_Motta_2021.Models.AcquisitionModel.__init__", "modulename": "Shelegia_Motta_2021.Models", "qualname": "AcquisitionModel.__init__", "type": "function", "doc": "

    An additional constraint is added compared to Shelegia_Motta_2021.Models.BaseModel. Namely, $\\Delta$ has to be bigger than $\\delta$, meaning the innovation of the entrant is not too drastic.

    \n\n

    Meanwhile, the parameters do not change compared to Shelegia_Motta_2021.Models.BargainingPowerModel.

    \n", "parameters": ["self", "u", "B", "small_delta", "delta", "K"], "funcdef": "def"}, {"fullname": "Shelegia_Motta_2021.Models.AcquisitionModel.get_copying_fixed_costs_values", "modulename": "Shelegia_Motta_2021.Models", "qualname": "AcquisitionModel.get_copying_fixed_costs_values", "type": "function", "doc": "

    Returns the fixed costs for copying thresholds of the incumbent.

    \n\n

    Additional thresholds for the fixed cost of copying of the incumbent compared to the Shelegia_Motta_2021.Models.BargainingModel:

    \n\n\n\n\n \n \n \n\n\n\n\n \n \n \n\n\n \n \n \n\n\n
    Threshold $\\:\\:\\:\\:\\:$Name $\\:\\:\\:\\:\\:$Formula $\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:\\:$
    $F^{ACQ}_S$F(ACQ)s$\\frac{(u + \\Delta - K)}{2} + \\delta(2 - \\beta)$
    $F^{ACQ}_C$F(ACQ)c$\\frac{K}{2} + \\delta(2.5 - 3\\beta)$
    \n\n


    \n\n
    Returns
    \n\n
      \n
    • Dict[str, float]: Includes the thresholds for the fixed costs for copying of the incumbent.
    • \n
    \n", "parameters": ["self"], "funcdef": "def"}]; // mirrored in build-search-index.js (part 1) // Also split on html tags. this is a cheap heuristic, but good enough. diff --git a/images/best_acqui.png b/resources/best_acqui.png similarity index 100% rename from images/best_acqui.png rename to resources/best_acqui.png diff --git a/images/best_base.png b/resources/best_base.png similarity index 100% rename from images/best_base.png rename to resources/best_base.png diff --git a/dev_notes.md b/resources/dev_notes.md similarity index 86% rename from dev_notes.md rename to resources/dev_notes.md index 00a67ed..c0e8a74 100644 --- a/dev_notes.md +++ b/resources/dev_notes.md @@ -7,9 +7,9 @@ The number of the square is denoted in brackets (i.e. (1)). ### BaseModel - Best Answer of the incumbent to the choices of the entrant -![](images/plots-best_base.png) +![](plots-best_base.png) - Equilibrium path -![](images/plots-eq_base.png) +![](plots-eq_base.png) ### BargainingPowerModel diff --git a/images/eq_acqui.png b/resources/eq_acqui.png similarity index 100% rename from images/eq_acqui.png rename to resources/eq_acqui.png diff --git a/images/eq_base.png b/resources/eq_base.png similarity index 100% rename from images/eq_base.png rename to resources/eq_base.png diff --git a/images/eq_unobservable.png b/resources/eq_unobservable.png similarity index 100% rename from images/eq_unobservable.png rename to resources/eq_unobservable.png diff --git a/images/plots-best_base.png b/resources/plots-best_base.png similarity index 100% rename from images/plots-best_base.png rename to resources/plots-best_base.png diff --git a/images/plots-eq_base.png b/resources/plots-eq_base.png similarity index 100% rename from images/plots-eq_base.png rename to resources/plots-eq_base.png diff --git a/images/plots.drawio b/resources/plots.drawio similarity index 100% rename from images/plots.drawio rename to resources/plots.drawio diff --git a/shelegia_motta_2021.pdf b/resources/shelegia_motta_2021.pdf similarity index 100% rename from shelegia_motta_2021.pdf rename to resources/shelegia_motta_2021.pdf