From b1e0c00f09b40f5dcd94a8f04a0949505df189df Mon Sep 17 00:00:00 2001 From: VincentAURIAU Date: Wed, 10 Apr 2024 18:36:47 +0200 Subject: [PATCH] ADD: intro to pricing with MNLs --- .../auxiliary_tools/assortment_example.ipynb | 57 +++++++++++++++---- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/notebooks/auxiliary_tools/assortment_example.ipynb b/notebooks/auxiliary_tools/assortment_example.ipynb index 474093eb..0f091fb7 100644 --- a/notebooks/auxiliary_tools/assortment_example.ipynb +++ b/notebooks/auxiliary_tools/assortment_example.ipynb @@ -465,7 +465,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We need to define what quantity needs to be optimized by our assortment. A usual answer is to optimize the revenue or margin. In our case we do not have these values, so let's say that we want to obtain the assortment with 12 products that will generate the highest turnover.\\\n", + "We need to define what quantity needs to be optimized by our assortment. A usual answer is to optimize the revenue or margin. In our case we do not have these values, so let's say that we want to obtain the assortment with 12 products that will generate the highest turnover.\n", "\n", "### Choice-Learn's AssortmentOptimizer\n", "Choice-Learn integrates algorithms for assortment planning based on Gurobi. Here is how it works." @@ -560,15 +560,6 @@ "print(\"With an estimated average reveue of:\", opt_obj)" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(opt.solver.ObjVal)" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -631,7 +622,51 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Pricing and Assortment Optimization" + "## Pricing and Assortment Optimization\n", + "\n", + "Since our model takes the price into consideration, it is possible to optimize both the assortment and the price of the products of the assortment at the same time !\n", + "\n", + "The optimization is slightly more complex. The idea is to define a discretization of the prices with the correspondign utilities and itemwise values.\n", + "\n", + "Let's take as an example a product $i$ whose utility function is $U(i) = u_i - p_i$ with $u_i$=1.5 and $p_i$ its price.\\\n", + "We decide that the price range we accept to sell $i$ at is [2.5, 3.5] and to discretize into 6 values.\\\n", + "If we have the cost $c_i=2.0$ we can use the margin $m_i = p_i -c_i$ as itemwise value otherwise we can take the revenue, $r_i=p_i$.\n", + "\n", + "| Price | Utility | Margin | Revenue |\n", + "| --- | --- | --- | --- |\n", + "| 2.5 | -1.0 | 0.5 | 2.5 |\n", + "| 2.7 | -1.2 | 0.7 | 2.7 |\n", + "| 2.9 | -1.4 | 0.9 | 2.9 |\n", + "| 3.1 | -1.6 | 1.1 | 3.1 |\n", + "| 3.3 | -1.8 | 1.3 | 3.3 |\n", + "| 3.5 | -2.0 | 1.5 | 3.5 |\n", + "\n", + "The idea in the optimization is either not to choose the item because another item is more valuable or to choose at most one price that is optimal toward our objective.\n", + "\n", + "Coming back to our example:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "prices_grid = []\n", + "for item_index in range(25):\n", + " min_price = 0.9 * np.min(dataset.items_features_by_choice[0][:, item_index])\n", + " max_price = 1.1 * np.max(dataset.items_features_by_choice[0][:, item_index])\n", + " prices_grid.append(np.linspace(min_price, max_price, 10))\n", + "prices_grid = np.stack(prices_grid, axis=0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "prices_grid.shape" ] }, {