{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Päivitetty 2025-08-26 / Aki Taanila\n" ] } ], "source": [ "from datetime import datetime\n", "print(f'Päivitetty {datetime.now().date()} / Aki Taanila')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Lehtikauppiaan ongelma\n", "\n", "Lehtikauppias on tilastoinut iltapäivälehden kysyntää. Kysyntä vaihtelee jonkin verran viikonpäivän \n", "mukaan. Lehtikauppias on laskenut tilaston perusteella kunkin viikonpäivän kysynnälle keskiarvon \n", "ja keskihajonnan. Tietyn viikonpäivän kysynnän voidaan olettaa noudattavan normaalijakaumaa.\n", "\n", "Lehtikauppiaan täytyy ilmoittaa etukäteen tilattavien lehtien lukumäärä. Lehtikauppias pyrkii\n", "tietenkin tyydyttämään kysynnän mahdollisimman hyvin ja toisaalta hankkimaan itselleen \n", "mahdollisimman korkean voiton. Simulointimallissa simuloidaan kysynnän määriä normaalijakaumasta ja lasketaan simulaatiokierrosten tilastolliset tunnusluvut voitolle ja puuttuvien lehtien määrälle.\n", "\n", "Lehtikauppias voisi solmia nk. palautussopimuksen, jolloin myymättömistä lehdistä saa täyden \n", "hyvityksen lehtitalolta. Tässä tapauksessa lehden hinta on kauppiaalle korkeampi. Simulointimallissa on laskettu voiton tunnusluvut myös palautussopimusta käyttäen." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import pandas as pd" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "(Palautus, 510) 331.348433\n", "(Ei palautusta, 510) 365.813892\n", "(Ilman lehteä, 510) 25.882100\n", "(Palautus, 520) 334.866469\n", "(Ei palautusta, 520) 368.184756\n", "(Ilman lehteä, 520) 19.023700\n", "(Palautus, 530) 338.444001\n", "(Ei palautusta, 530) 370.651524\n", "(Ilman lehteä, 530) 15.274600\n", "(Palautus, 540) 341.452100\n", "(Ei palautusta, 540) 372.200400\n", "(Ilman lehteä, 540) 12.062500\n", "(Palautus, 550) 343.010587\n", "(Ei palautusta, 550) 371.412588\n", "(Ilman lehteä, 550) 8.725700\n", "(Palautus, 560) 344.390988\n", "(Ei palautusta, 560) 370.337712\n", "(Ilman lehteä, 560) 6.315000\n", "(Palautus, 570) 345.762277\n", "(Ei palautusta, 570) 369.248148\n", "(Ilman lehteä, 570) 4.274200\n", "(Palautus, 580) 346.699674\n", "(Ei palautusta, 580) 367.459176\n", "(Ilman lehteä, 580) 2.655400\n", "(Palautus, 590) 347.688393\n", "(Ei palautusta, 590) 365.752932\n", "(Ilman lehteä, 590) 1.905100\n", "dtype: float64" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "TOISTOJA = 10000 #simulointikierrosten lukumäärä\n", "KESKIARVO = 520 #päivämyynnin keskiarvo\n", "KESKIHAJONTA = 50 #päivämyynnin keskihajonta\n", "OSTOHINTA_EI_PALAUTUSTA = 0.25\n", "OSTOHINTA_PALAUTUS = 0.33\n", "MYYNTIHINTA = 1\n", "yhteenveto = pd.DataFrame()\n", "\n", "# Alustan satunnaislukugeneraattorin:\n", "rng = np.random.default_rng()\n", "\n", "for tilaus in range(510, 600, 10):\n", " kysyntä = rng.normal(loc = KESKIARVO, scale = KESKIHAJONTA, size = TOISTOJA)\n", " kysyntä = np.round(kysyntä)\n", "\n", " myynti = (kysyntä > tilaus) * tilaus + (kysyntä <= tilaus) * kysyntä\n", "\n", " voitto_palautus = myynti * (MYYNTIHINTA-OSTOHINTA_PALAUTUS)\n", "\n", " voitto_ei_palautusta = myynti * (MYYNTIHINTA - OSTOHINTA_EI_PALAUTUSTA) - (tilaus-myynti) * OSTOHINTA_PALAUTUS \n", " \n", " ilman_lehteä = kysyntä - myynti\n", "\n", " yhteenveto['Palautus', tilaus] = voitto_palautus\n", " yhteenveto['Ei palautusta', tilaus] = voitto_ei_palautusta\n", " yhteenveto['Ilman lehteä', tilaus] = ilman_lehteä \n", "\n", "yhteenveto.mean() #voittojen ja ilman lehteä jääneiden keskiarvot eri tapauksissa" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
 ('Palautus', 510)('Ei palautusta', 510)('Ilman lehteä', 510)('Palautus', 520)('Ei palautusta', 520)('Ilman lehteä', 520)('Palautus', 530)('Ei palautusta', 530)('Ilman lehteä', 530)('Palautus', 540)('Ei palautusta', 540)('Ilman lehteä', 540)('Palautus', 550)('Ei palautusta', 550)('Ilman lehteä', 550)('Palautus', 560)('Ei palautusta', 560)('Ilman lehteä', 560)('Palautus', 570)('Ei palautusta', 570)('Ilman lehteä', 570)('Palautus', 580)('Ei palautusta', 580)('Ilman lehteä', 580)('Palautus', 590)('Ei palautusta', 590)('Ilman lehteä', 590)
count100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000100001000010000
mean3313662633536819338371153413721234337193443706346369434736733483662
std17283319312821352524382326421928451729471330481031509
min218184021817902161740211162022718502281820226177022617302211620
25%326357032635303263510328350032634403263400326337032633503263310
50%3423821034838903483870349384034938103483770348374034837003493680
75%3423824534839032355398243624051636841243714140371410037140603724050
max342382202348390176355398155362405179368412154375420137382428138389435119395442142
\n" ], "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "yhteenveto.describe().style.format('{:.0f}') #tarkempi analyysi eri tapauksista" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lisätietoa satunnaislukujen tuottamisesta: https://numpy.org/doc/stable/reference/random/index.html" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.2" } }, "nbformat": 4, "nbformat_minor": 4 }