Spaces:
Sleeping
Sleeping
File size: 7,465 Bytes
6fde63f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | def initialize_parcels(parcel_map, cluster_labels):
parcel_dict = {}
for i in range(parcel_map.shape[0]):
for j in range(parcel_map.shape[1]):
cluster_id = parcel_map[i, j]
land_type = cluster_labels.get(cluster_id, "Unknown")
parcel_dict[(i, j)] = {
"land_type": land_type,
"forage": None,
"health": 1.0,
"degraded": False,
"cattle_grazing": {
"conservative": land_type == "Productive Grass",
"moderate": land_type in ["Productive Grass", "Pasture/Desert"],
"aggressive": land_type not in ["Water"]
},
"elk_grazing": {
"default": land_type in ["Riparian Sensitive Zone", "Productive Grass"]
}
}
return parcel_dict
def get_land_forage_rates():
return {
'Productive Grass': 1.0,
'Pasture/Desert': 0.4,
'Riparian Sensitive Zone': 1.2,
'Rocky Area': 0.2,
'Water': 0.0
}
def assign_initial_forage(parcel_dict, land_forage_rates):
for parcel in parcel_dict.values():
rate = land_forage_rates.get(parcel["land_type"], 0.0)
parcel["forage"] = rate * 100 # initial AUMs
import numpy as np
import numpy as np
import matplotlib.pyplot as plt
from collections import Counter
from matplotlib.colors import ListedColormap
import matplotlib.patches as mpatches
def simulate_period(parcel_dict, grazing_strategy="moderate", cattle_stocking_rate=100000, elk_pressure=3000):
print(f"\n🟢 Running LP-based simulation using grazing strategy: **{grazing_strategy.upper()}**")
import numpy as np
from scipy.optimize import linprog
keys = list(parcel_dict.keys())
n_rows = max(i for i, _ in keys) + 1
n_cols = max(j for _, j in keys) + 1
num_cells = n_rows * n_cols
# Step 1: Regrowth
land_growth_rates = {
'Productive Grass': 1.0,
'Pasture/Desert': 0.4,
'Riparian Sensitive Zone': 1.2,
'Rocky Area': 0.2,
'Water': 0.0
}
for parcel in parcel_dict.values():
base_growth = land_growth_rates.get(parcel["land_type"], 0.0)
weather = np.random.normal(1.0, 0.15)
regrowth = base_growth * weather * 1
regrowth *= parcel["health"]
parcel["forage"] = min(parcel["forage"] + regrowth, 100)
# Step 2: Subtract uniform elk grazing from all parcels
elk_grazing_per_parcel = elk_pressure / num_cells
for parcel in parcel_dict.values():
parcel["forage"] -= elk_grazing_per_parcel
parcel["forage"] = max(parcel["forage"], 0.0)
# Step 3: LP for cattle
cost = []
bounds = []
eligible_keys = []
for i in range(n_rows):
for j in range(n_cols):
p = parcel_dict[(i, j)]
if not p["cattle_grazing"].get(grazing_strategy, False):
cost.append(0)
bounds.append((0, 0))
continue
if grazing_strategy in {"conservative", "moderate"} and p["land_type"] == "Riparian Sensitive Zone":
cost.append(0)
bounds.append((0, 0))
continue
cost.append((i + j) * 0.02)
bounds.append((0, p["forage"]))
eligible_keys.append((i, j))
A_eq = [1.0 if b[1] > 0 else 0.0 for b in bounds]
b_eq = [cattle_stocking_rate]
result = linprog(c=cost, A_eq=[A_eq], b_eq=b_eq, bounds=bounds, method="highs")
if not result.success:
raise RuntimeError("Grazing LP failed: " + result.message)
grazing_values = result.x
# Step 4: Apply grazing and your specified health rule
for idx, ((i, j), x) in enumerate(zip(parcel_dict.keys(), grazing_values)):
parcel = parcel_dict[(i, j)]
parcel["forage"] -= x
# ✅ Your health rule (fully time-dynamic)
if parcel["forage"] <= 0:
parcel["health"] = max(parcel["health"] - 0.25, 0.0)
elif parcel["forage"] < 20:
parcel["health"] = max(parcel["health"] - 0.1, 0.0)
else:
parcel["health"] = min(parcel["health"] + 0.02, 1.0)
def simulate_periodold(parcel_dict, grazing_strategy="moderate", cattle_stocking_rate=5000, elk_pressure=3000):
print(f"\n🟢 Running simulation using cattle grazing strategy: **{grazing_strategy.upper()}**")
land_growth_rates = {
'Productive Grass': 1.0,
'Pasture/Desert': 0.4,
'Riparian Sensitive Zone': 1.2,
'Rocky Area': 0.2,
'Water': 0.0
}
# 1. Simulate forage regrowth for 8 months
for parcel in parcel_dict.values():
base_growth = land_growth_rates.get(parcel["land_type"], 0.0)
weather = np.random.normal(1.0, 0.15)
regrowth = base_growth * weather * 8 # ← 8 months, as you said
regrowth *= parcel["health"] # degrade means slower regrowth
parcel["forage"] = min(parcel["forage"] + regrowth, 100)
# 2. Count eligible parcels
total_grazed_parcels = sum(
1 for parcel in parcel_dict.values() if parcel["cattle_grazing"].get(grazing_strategy, False)
)
if total_grazed_parcels == 0:
print("⚠️ No parcels match the selected grazing strategy.")
return
cattle_grazing_per_parcel = cattle_stocking_rate / total_grazed_parcels
elk_grazing_per_parcel = elk_pressure / len(parcel_dict)
# 3. Simulate grazing and degradation
for parcel in parcel_dict.values():
if not parcel["cattle_grazing"].get(grazing_strategy, False):
continue
total_grazing = cattle_grazing_per_parcel + elk_grazing_per_parcel
if total_grazing > parcel["forage"]:
parcel["degraded"] = True
parcel["health"] = max(parcel["health"] - 0.1, 0.0)
else:
parcel["health"] = min(parcel["health"] + 0.02, 1.0)
parcel["forage"] = max(parcel["forage"] - total_grazing, 0)
def get_forage_map(parcel_dict, n_rows, n_cols):
return np.array([[parcel_dict[(i, j)]["forage"] for j in range(n_cols)] for i in range(n_rows)])
def get_health_map(parcel_dict, n_rows, n_cols):
"""
Returns a 2D numpy array representing the health of each parcel.
"""
return np.array([[parcel_dict[(i, j)]["health"] for j in range(n_cols)] for i in range(n_rows)])
def plot_health_map(health_map, title="Parcel Health Levels", save_path=None):
"""
Plots a heatmap of the parcel health values.
"""
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 6))
plt.imshow(health_map, cmap='RdYlGn', origin='upper', vmin=0, vmax=1)
plt.colorbar(label="Health Index (0–1)")
plt.title(title)
plt.axis('off')
plt.tight_layout()
if save_path:
plt.savefig(save_path)
plt.show()
def plot_forage_map(forage_map, title="Parcel Forage Levels"):
plt.figure(figsize=(8, 6))
plt.imshow(forage_map, cmap='YlGn', origin='upper')
plt.colorbar(label="Forage AUMs")
plt.title(title)
plt.axis('off')
plt.tight_layout()
plt.show()
def run_full_simulation(parcel_map, cluster_labels, n_rows, n_cols, strategy="moderate"):
parcel_dict = initialize_parcels(parcel_map, cluster_labels)
land_forage_rates = get_land_forage_rates()
assign_initial_forage(parcel_dict, land_forage_rates)
simulate_period(parcel_dict, grazing_strategy=strategy)
return parcel_dict
|