Nagaraj81's picture
Upload 2 files
cc12261 verified
import gradio as gr
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import random
# Constants
regions = ["Riyadh", "Makkah", "Eastern", "Madinah", "Qassim", "Asir", "Tabuk", "Hail", "Northern",
"Jazan", "Najran", "Bahah", "Jawf"]
income_bands = ["Low", "Mid", "High"]
property_types = ["Land", "Off-plan", "Ready", "Self-build"]
def default_subsidy_values():
base = 300_000
factor = 0.5
return {(r, i, p): int((base - 100_000 * income_bands.index(i)) * factor)
for r in regions for i in income_bands for p in property_types}
def default_supply_cost_values():
return {(p, r): {"Supply": random.randint(1000, 10000), "Discount (SAR)": random.randint(50_000, 300_000)}
for p in ["Land", "Off-plan"] for r in regions}
def monte_carlo_optimization(subsidies, budget_limit, target_contracts, supply_dict, interest_rate, demand_increase, n_trials=10000):
keys = list(subsidies.keys())
best_result = None
best_score = float('-inf')
fairness_penalty_weight = 10_000_000
demand_multiplier = 1 + (demand_increase / 100)
cost_multiplier = 1 + (interest_rate / 100)
for _ in range(n_trials):
contracts = {}
total_budget = 0
total_contracts = 0
shuffled_subs = {k: int(random.randint(150000, 400000) * cost_multiplier) for k in keys}
available_supply = {(r, p): supply_dict.get((p, r), 0) for (p, r) in supply_dict}
for k in keys:
r, i, p = k
max_supply = available_supply.get((r, p), 10000)
max_demand = int(max_supply * demand_multiplier)
max_possible_contracts = int(min((budget_limit - total_budget) // shuffled_subs[k], max_demand)) if shuffled_subs[k] > 0 else 0
c = random.randint(0, max_possible_contracts) if max_possible_contracts > 0 else 0
contracts[k] = c
total_budget += shuffled_subs[k] * c
total_contracts += c
if total_budget > budget_limit:
continue
achieved_regions = set(r for (r, i, p) in contracts if contracts[(r, i, p)] > 0)
achieved_income = set(i for (r, i, p) in contracts if contracts[(r, i, p)] > 0)
achieved_props = set(p for (r, i, p) in contracts if contracts[(r, i, p)] > 0)
fairness_penalty = (
len(regions) - len(achieved_regions) +
len(income_bands) - len(achieved_income) +
len(property_types) - len(achieved_props)
) * fairness_penalty_weight
score = total_contracts - fairness_penalty
if score > best_score:
best_score = score
best_result = (contracts, total_budget, total_contracts, shuffled_subs)
return best_result if best_result else ({}, 0, 0, subsidies)
def create_gauge_chart(value, title, max_value=100):
fig = go.Figure(go.Indicator(
mode="gauge+number",
value=value,
gauge={
'axis': {'range': [0, max_value]},
'bar': {'color': "darkblue"},
'steps': [
{'range': [0, max_value * 0.5], 'color': "lightgray"},
{'range': [max_value * 0.5, max_value], 'color': "lightgreen"}
]
},
title={'text': title}
))
fig.update_layout(height=350, width=450, margin=dict(t=40, b=40, l=40, r=40))
return fig
def build_app():
supply_costs = default_supply_cost_values()
with gr.Blocks() as app:
gr.Markdown("# 🏨 Strategic Gears Housing Simulator – Auto Optimization")
with gr.Tab("Inputs"):
with gr.Row():
with gr.Column():
ir = gr.Slider(0, 10, 5, label="Interest Rate (%)")
dp = gr.Slider(0, 100, 10, label="Demand Increase (%)")
n = gr.Slider(100, 10000, 1000, step=100, label="Number of Simulations")
budget_limit = gr.Slider(10_000_000, 1_000_000_000, 500_000_000, step=10_000_000, label="Budget Limit (SAR)")
target_contracts = gr.Slider(1000, 20000, 5000, step=100, label="Target Contracts")
supply_inputs = {}
with gr.Accordion("Supply Inputs by Region and Property Type", open=False):
for p in ["Land", "Off-plan"]:
with gr.Accordion(p, open=False):
for r in regions:
supply_inputs[(p, r)] = gr.Slider(minimum=1, maximum=10000,
value=supply_costs[(p, r)]["Supply"],
step=1,
label=f"{r} {p} Supply")
run = gr.Button("Run Simulation")
with gr.Tab("Outputs"):
summary = gr.Markdown("Optimization summary will appear here.")
with gr.Row():
with gr.Column():
df_subsidy_policy = gr.Dataframe(label="1️⃣ Recommended Subsidy Support (SAR)")
subsidy_by_income_bar = gr.Plot(label="Average Subsidy by Income Band")
with gr.Column():
df_contract_summary = gr.Dataframe(label="2️⃣ Contract Distribution")
contracts_by_region_bar = gr.Plot(label="Contracts by Region")
with gr.Row():
with gr.Column():
df_budget_summary = gr.Dataframe(label="3️⃣ Budget Distribution")
budget_util_gauge = gr.Plot(label="Budget Utilization (%)")
with gr.Column():
df_discount_table = gr.Dataframe(label="4️⃣ Discount Table")
contracts_by_property_pie = gr.Plot(label="Contract Distribution by Property Type")
target_achievement_gauge = gr.Plot(label="Target Achievement (%)")
total_contracts_gauge = gr.Plot(label="Total Contracts (Scaled to Target)")
def run_sim(interest, demand, sims, budget, target, *supplies):
supply_dict = {(p, r): supplies[i] for i, (p, r) in enumerate(supply_inputs)}
result, total_bgt, total_con, final_subs = monte_carlo_optimization(
default_subsidy_values(), budget, target, supply_dict, interest, demand, sims
)
df = pd.DataFrame([{
"Region": r, "Income Band": i, "Property Type": p,
"Contracts": result.get((r, i, p), 0),
"Subsidy (SAR)": final_subs[(r, i, p)],
"Budget (SAR)": result.get((r, i, p), 0) * final_subs[(r, i, p)]
} for (r, i, p) in final_subs])
subsidy_df = df[["Region", "Income Band", "Property Type", "Subsidy (SAR)"]].sort_values(by="Subsidy (SAR)", ascending=False)
contract_df = df[["Region", "Income Band", "Property Type", "Contracts"]].sort_values(by="Contracts", ascending=False)
budget_df = df[["Region", "Income Band", "Property Type", "Budget (SAR)"]].sort_values(by="Budget (SAR)", ascending=False)
df_discount = pd.DataFrame([{
"Region": r, "Property Type": p,
"Discount (SAR)": random.randint(50_000, 300_000)
} for p in ["Land", "Off-plan"] for r in regions])
summary_text = f"""
**Optimization Summary:**
- Total Budget Used: {total_bgt:,.0f} SAR
- Budget Utilization: {(total_bgt / budget) * 100:.1f}%
- Total Contracts: {total_con:,}
- Target Achievement: {(total_con / target) * 100:.1f}%
"""
# Gauges
budget_util_pct = (total_bgt / budget) * 100
target_achieved_pct = (total_con / target) * 100
total_contracts_scaled = min(100, (total_con / target) * 100)
gauge_budget = create_gauge_chart(budget_util_pct, "Budget Utilization (%)")
gauge_target = create_gauge_chart(target_achieved_pct, "Target Achievement (%)")
gauge_contracts = create_gauge_chart(total_contracts_scaled, "Contracts (Scaled to Target %)")
# Contracts by Region Bar
contracts_region = df.groupby("Region")["Contracts"].sum().reset_index()
bar_contract_region = px.bar(contracts_region, x="Region", y="Contracts", title="Contracts by Region")
min_y = 10
max_y = contracts_region["Contracts"].max() * 1.1
bar_contract_region.update_layout(
height=350, width=450,
yaxis=dict(title="Contracts", tickformat=",d", range=[min_y, max_y]),
margin=dict(t=50, b=40, l=60, r=40)
)
# Subsidy by Income Band
subsidy_income = df.groupby("Income Band")["Subsidy (SAR)"].mean().reset_index()
bar_subsidy_income = px.bar(subsidy_income, x="Income Band", y="Subsidy (SAR)", title="Average Subsidy by Income Band")
bar_subsidy_income.update_layout(
height=350, width=450,
yaxis=dict(tickprefix="SAR ", tickformat="~s"),
margin=dict(t=50, b=40, l=60, r=40)
)
# Property Type Pie
contracts_property = df.groupby("Property Type")["Contracts"].sum().reset_index()
pie_property = px.pie(contracts_property, names="Property Type", values="Contracts", title="Contract Distribution by Property Type")
pie_property.update_layout(height=350, width=450, margin=dict(t=50, b=40, l=40, r=40))
return summary_text, subsidy_df, contract_df, budget_df, df_discount, gauge_budget, gauge_target, gauge_contracts, bar_contract_region, bar_subsidy_income, pie_property
run.click(
fn=run_sim,
inputs=[ir, dp, n, budget_limit, target_contracts] + list(supply_inputs.values()),
outputs=[
summary, df_subsidy_policy, df_contract_summary, df_budget_summary, df_discount_table,
budget_util_gauge, target_achievement_gauge, total_contracts_gauge,
contracts_by_region_bar, subsidy_by_income_bar, contracts_by_property_pie
]
)
return app
app = build_app()
app.launch()