Монте Карло симулацията е мощен инструмент за оценка на риска и несигурността в проектното управление. При управлението на софтуерни проекти, точното определяне на бюджета е критично за успеха на проекта.
Монте Карло симулацията за бюджетно планиране се базира на принципа на многократното случайно семплиране. Вместо да разчитаме на единични точкови оценки, които често се оказват неточни, методът генерира хиляди възможни сценарии, вземайки предвид вероятностните разпределения на различните компоненти на бюджета. Това ни позволява да получим не просто една прогнозна стойност, а цяло разпределение на възможните резултати, което много по-добре отразява реалната несигурност в проектното планиране.
Особено важен аспект на методологията е интегрирането на рисковите фактори. За разлика от традиционното бюджетно планиране, където рисковете често се отчитат чрез фиксиран процент буфер, Монте Карло симулацията позволява моделиране на сложни взаимодействия между различните рискове. Всеки рисков фактор се характеризира с вероятност на възникване и потенциално въздействие, като в симулацията тези рискове могат да се материализират независимо един от друг, създавайки множество различни комбинации от сценарии. Това води до много по-реалистична оценка на необходимия буфер, базирана на действителната рискова експозиция на проекта.
Използваме PERT (Program Evaluation and Review Technique) разпределение със следните оценки:
Formula: Expected Value = (O + 4M + P) / 6
ФУНКЦИЯ monte_carlo_simulation(iterations, activities, risks): резултати = празен_масив() ЗА ВСЯКО i ОТ 1 ДО iterations: общ_бюджет = 0 ЗА ВСЯКА дейност В activities: // Генериране на случайна стойност по PERT разпределение стойност = pert_random( дейност.оптимистична, дейност.най_вероятна, дейност.песимистична ) // Прилагане на рискови фактори ЗА ВСЕКИ риск В risks: АКО random() < риск.вероятност: стойност *= (1 + риск.въздействие) общ_бюджет += стойност // Добавяне на допълнителни разходи общ_бюджет *= 1.3 // 30% за технологии и обучения добави(резултати, общ_бюджет) ВЪРНИ резултати ФУНКЦИЯ анализирай_резултати(резултати, планиран_бюджет): средна_стойност = изчисли_средно(резултати) стандартно_отклонение = изчисли_std(резултати) персентил_90 = изчисли_персентил(резултати, 90) вероятност_превишаване = изчисли_вероятност_превишаване(резултати, планиран_бюджет) ВЪРНИ { средна_стойност, стандартно_отклонение, персентил_90, вероятност_превишаване }
Функцията приема три параметра:
iterations
- брой повторения на симулацията (обикновено 10000)activities
- списък с дейностите и техните оценкиrisks
- списък с рисковите факториЗа всяка итерация функцията:
Функцията pert_random
реализира PERT разпределението чрез:
Функцията анализирай_резултати
извършва статистически анализ чрез:
Тези метрики дават цялостна картина на риска и необходимия буфер.
import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy import stats # Define project activities and their estimates activities = { 'Project Manager': { 'optimistic': 6460.48, 'most_likely': 6945.02, 'pessimistic': 7429.55 * 1.2 }, 'Senior Dev 1': { 'optimistic': 26103.69, 'most_likely': 28061.47, 'pessimistic': 30019.24 * 1.3 }, 'Senior Dev 2': { 'optimistic': 24886.95, 'most_likely': 26753.47, 'pessimistic': 28619.99 * 1.3 }, 'Junior Dev 1': { 'optimistic': 6797.73, 'most_likely': 7307.56, 'pessimistic': 7817.39 * 1.15 }, 'Junior Dev 2': { 'optimistic': 6244.19, 'most_likely': 6712.51, 'pessimistic': 7180.82 * 1.15 }, 'QA Engineer': { 'optimistic': 5532.38, 'most_likely': 5947.31, 'pessimistic': 6362.24 * 1.25 } } # Risk factors from risk register risk_factors = { 'integration_issues': {'probability': 0.8, 'impact': 0.25}, 'performance_issues': {'probability': 0.8, 'impact': 0.20}, 'requirement_changes': {'probability': 0.8, 'impact': 0.15}, 'technical_challenges': {'probability': 0.6, 'impact': 0.20} } def pert_random(opt, likely, pess, size=1): """Generate random values using PERT distribution""" alpha = 4 mean = (opt + alpha * likely + pess) / (alpha + 2) variance = ((pess - opt) ** 2) / 36 a = ((mean - opt) * (2 * pess - opt - mean)) / variance b = (a * (pess - mean)) / (mean - opt) return np.random.beta(a, b, size=size) * (pess - opt) + opt def run_simulation(n_iterations=10000): """Run Monte Carlo simulation""" results = [] for _ in range(n_iterations): iteration_total = 0 for activity, estimates in activities.items(): cost = pert_random( estimates['optimistic'], estimates['most_likely'], estimates['pessimistic'] )[0] for risk in risk_factors.values(): if np.random.random() < risk['probability']: cost *= (1 + risk['impact']) iteration_total += cost iteration_total *= 1.3 results.append(iteration_total) return np.array(results) def analyze_results(simulation_results): """Analyze simulation results""" planned_budget = 126772.39 mean_cost = np.mean(simulation_results) std_dev = np.std(simulation_results) percentile_90 = np.percentile(simulation_results, 90) overrun_prob = np.mean(simulation_results > planned_budget) recommended_buffer = percentile_90 - planned_budget print(f"\nSimulation Analysis Results:") print(f"Mean Expected Cost: {mean_cost:,.2f} лв.") print(f"Standard Deviation: {std_dev:,.2f} лв.") print(f"90th Percentile Cost: {percentile_90:,.2f} лв.") print(f"Probability of Budget Overrun: {overrun_prob:.1%}") print(f"Recommended Additional Buffer: {max(0, recommended_buffer):,.2f} лв.") plt.figure(figsize=(10, 6)) plt.hist(simulation_results, bins=50, density=True, alpha=0.7) plt.axvline(planned_budget, color='r', linestyle='dashed', label='Planned Budget') plt.axvline(mean_cost, color='g', linestyle='dashed', label='Mean Simulated Cost') plt.axvline(percentile_90, color='y', linestyle='dashed', label='90th Percentile') plt.title('Monte Carlo Simulation Results') plt.xlabel('Total Project Cost (лв.)') plt.ylabel('Probability Density') plt.legend() plt.grid(True, alpha=0.3) plt.show() # Run simulation and analyze results results = run_simulation(10000) analyze_results(results)
Тази симулация предоставя ценна информация за:
Важно е да се отбележи, че симулацията е толкова добра, колкото са входните данни. Редовното актуализиране на оценките и рисковите фактори е ключово за поддържане на точността на модела.