File size: 4,255 Bytes
3875d5c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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=500, elk_pressure=300):
    print(f"\n🟢 Running simulation using cattle grazing strategy: **{grazing_strategy.upper()}**")

    # 1. Reset all forage to simulate winter die-off
    for parcel in parcel_dict.values():
        parcel["forage"] = 0

    # 2. Count eligible parcels for cattle grazing
    total_grazed_parcels = sum(
        1 for parcel in parcel_dict.values() if parcel["cattle_grazing"][grazing_strategy]
    )

    if total_grazed_parcels == 0:
        print("⚠️ No parcels match the selected grazing strategy.")
        return

    # 3. Calculate AUM pressure per parcel
    cattle_grazing_per_parcel = cattle_stocking_rate / total_grazed_parcels
    elk_grazing_per_parcel = elk_pressure / len(parcel_dict)  # uniform elk pressure

    # 4. Simulate forage growth + grazing effects
    for parcel in parcel_dict.values():
        if not parcel["cattle_grazing"][grazing_strategy]:
            continue

        # Forage regrowth (8-month season with weather factor)
        base_growth = {
            'Productive Grass': 1.0,
            'Pasture/Desert': 0.4,
            'Riparian Sensitive Zone': 1.2,
            'Rocky Area': 0.2,
            'Water': 0.0
        }.get(parcel["land_type"], 0.0)

        weather = np.random.normal(1.0, 0.2)
        growth = base_growth * weather * 8
        parcel["forage"] = growth  # no carryover between years

        # Total grazing pressure
        total_grazing = cattle_grazing_per_parcel + elk_grazing_per_parcel

        # Degradation or recovery
        if total_grazing > parcel["forage"]:
            parcel["degraded"] = True
            parcel["health"] -= 0.1
        else:
            parcel["health"] += 0.02

        # Subtract forage
        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 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