jeffrey1963 commited on
Commit
a33c002
·
verified ·
1 Parent(s): 6053c52

Upload Sim_Engine.py

Browse files
Files changed (1) hide show
  1. Sim_Engine.py +117 -0
Sim_Engine.py ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def initialize_parcels(parcel_map, cluster_labels):
2
+ parcel_dict = {}
3
+ for i in range(parcel_map.shape[0]):
4
+ for j in range(parcel_map.shape[1]):
5
+ cluster_id = parcel_map[i, j]
6
+ land_type = cluster_labels.get(cluster_id, "Unknown")
7
+
8
+ parcel_dict[(i, j)] = {
9
+ "land_type": land_type,
10
+ "forage": None,
11
+ "health": 1.0,
12
+ "degraded": False,
13
+ "cattle_grazing": {
14
+ "conservative": land_type == "Productive Grass",
15
+ "moderate": land_type in ["Productive Grass", "Pasture/Desert"],
16
+ "aggressive": land_type not in ["Water"]
17
+ },
18
+ "elk_grazing": {
19
+ "default": land_type in ["Riparian Sensitive Zone", "Productive Grass"]
20
+ }
21
+ }
22
+ return parcel_dict
23
+
24
+ def get_land_forage_rates():
25
+ return {
26
+ 'Productive Grass': 1.0,
27
+ 'Pasture/Desert': 0.4,
28
+ 'Riparian Sensitive Zone': 1.2,
29
+ 'Rocky Area': 0.2,
30
+ 'Water': 0.0
31
+ }
32
+
33
+
34
+ def assign_initial_forage(parcel_dict, land_forage_rates):
35
+ for parcel in parcel_dict.values():
36
+ rate = land_forage_rates.get(parcel["land_type"], 0.0)
37
+ parcel["forage"] = rate * 100 # initial AUMs
38
+
39
+ import numpy as np
40
+ import numpy as np
41
+ import matplotlib.pyplot as plt
42
+ from collections import Counter
43
+ from matplotlib.colors import ListedColormap
44
+ import matplotlib.patches as mpatches
45
+
46
+ def simulate_period(parcel_dict, grazing_strategy="moderate", cattle_stocking_rate=500, elk_pressure=300):
47
+ print(f"\n🟢 Running simulation using cattle grazing strategy: **{grazing_strategy.upper()}**")
48
+
49
+ # 1. Reset all forage to simulate winter die-off
50
+ for parcel in parcel_dict.values():
51
+ parcel["forage"] = 0
52
+
53
+ # 2. Count eligible parcels for cattle grazing
54
+ total_grazed_parcels = sum(
55
+ 1 for parcel in parcel_dict.values() if parcel["cattle_grazing"][grazing_strategy]
56
+ )
57
+
58
+ if total_grazed_parcels == 0:
59
+ print("⚠️ No parcels match the selected grazing strategy.")
60
+ return
61
+
62
+ # 3. Calculate AUM pressure per parcel
63
+ cattle_grazing_per_parcel = cattle_stocking_rate / total_grazed_parcels
64
+ elk_grazing_per_parcel = elk_pressure / len(parcel_dict) # uniform elk pressure
65
+
66
+ # 4. Simulate forage growth + grazing effects
67
+ for parcel in parcel_dict.values():
68
+ if not parcel["cattle_grazing"][grazing_strategy]:
69
+ continue
70
+
71
+ # Forage regrowth (8-month season with weather factor)
72
+ base_growth = {
73
+ 'Productive Grass': 1.0,
74
+ 'Pasture/Desert': 0.4,
75
+ 'Riparian Sensitive Zone': 1.2,
76
+ 'Rocky Area': 0.2,
77
+ 'Water': 0.0
78
+ }.get(parcel["land_type"], 0.0)
79
+
80
+ weather = np.random.normal(1.0, 0.2)
81
+ growth = base_growth * weather * 8
82
+ parcel["forage"] = growth # no carryover between years
83
+
84
+ # Total grazing pressure
85
+ total_grazing = cattle_grazing_per_parcel + elk_grazing_per_parcel
86
+
87
+ # Degradation or recovery
88
+ if total_grazing > parcel["forage"]:
89
+ parcel["degraded"] = True
90
+ parcel["health"] -= 0.1
91
+ else:
92
+ parcel["health"] += 0.02
93
+
94
+ # Subtract forage
95
+ parcel["forage"] = max(parcel["forage"] - total_grazing, 0)
96
+
97
+
98
+ def get_forage_map(parcel_dict, n_rows, n_cols):
99
+ return np.array([[parcel_dict[(i, j)]["forage"] for j in range(n_cols)] for i in range(n_rows)])
100
+
101
+
102
+ def plot_forage_map(forage_map, title="Parcel Forage Levels"):
103
+ plt.figure(figsize=(8, 6))
104
+ plt.imshow(forage_map, cmap='YlGn', origin='upper')
105
+ plt.colorbar(label="Forage AUMs")
106
+ plt.title(title)
107
+ plt.axis('off')
108
+ plt.tight_layout()
109
+ plt.show()
110
+
111
+ def run_full_simulation(parcel_map, cluster_labels, n_rows, n_cols, strategy="moderate"):
112
+ parcel_dict = initialize_parcels(parcel_map, cluster_labels)
113
+ land_forage_rates = get_land_forage_rates()
114
+ assign_initial_forage(parcel_dict, land_forage_rates)
115
+ simulate_period(parcel_dict, grazing_strategy=strategy)
116
+ return parcel_dict
117
+