CoolFace
Apppublic

DarkyCodez/precision-ag-env

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
core_sim.py129 linesDownload Raw Back to root
1class GreenhouseEnv:
2    """
3    Agricultural environment simulator with continuous state variables.
4    
5    State variables:
6    - soil_moisture: 0.0-1.0
7    - nitrogen_level: 0.0-1.0
8    - crop_health: 0.0-1.0
9    - turn_count: int
10    
11    Actions:
12    - 0: Do Nothing
13    - 1: Irrigate (+0.2 moisture)
14    - 2: Fertilize (+0.2 nitrogen)
15    - 3: Harvest
16    """
17    
18    def __init__(self):
19        """Initialize the greenhouse environment."""
20        # State variables
21        self.soil_moisture = 0.5
22        self.nitrogen_level = 0.5
23        self.crop_health = 0.5
24        self.turn_count = 0
25        
26        # Action space: 4 discrete actions
27        self.action_space_n = 4
28    
29    def step(self, action):
30        """
31        Execute one step of the environment.
32        
33        Args:
34            action: int, one of [0, 1, 2, 3]
35                0: Do Nothing
36                1: Irrigate
37                2: Fertilize
38                3: Harvest
39        
40        Returns:
41            reward: float strictly between 0.0 and 1.0
42        """
43        # Increment turn counter
44        self.turn_count += 1
45        
46        # Apply natural decay every turn
47        self.soil_moisture -= 0.05
48        self.nitrogen_level -= 0.02
49        
50        # Clamp values to valid range [0.0, 1.0]
51        self.soil_moisture = max(0.0, min(1.0, self.soil_moisture))
52        self.nitrogen_level = max(0.0, min(1.0, self.nitrogen_level))
53        
54        # Apply action
55        if action == 0:  # Do Nothing
56            pass
57        elif action == 1:  # Irrigate
58            self.soil_moisture = max(0.0, min(1.0, self.soil_moisture + 0.2))
59        elif action == 2:  # Fertilize
60            self.nitrogen_level = max(0.0, min(1.0, self.nitrogen_level + 0.2))
61        elif action == 3:  # Harvest
62            # Harvest action doesn't modify state, but affects reward
63            pass
64        
65        # Reduce crop health if moisture is outside optimal range [0.4, 0.6]
66        if self.soil_moisture < 0.4 or self.soil_moisture > 0.6:
67            self.crop_health -= 0.05
68        
69        # Clamp crop health to valid range
70        self.crop_health = max(0.0, min(1.0, self.crop_health))
71        
72        # Calculate reward (strictly between 0.0 and 1.0)
73        reward = self._calculate_reward(action)
74        
75        return reward
76    
77    def _calculate_reward(self, action):
78        """
79        Calculate reward based on current state and action.
80        
81        Rewards:
82        - 0.05 for maintaining optimal soil moisture (0.4-0.6)
83        - 0.02 for maintaining adequate nitrogen (>0.3)
84        - 0.03 for good crop health (>0.5)
85        - Up to 0.8 for harvesting with high crop health
86        
87        Returns:
88            reward: float strictly between 0.0 and 1.0
89        """
90        reward = 0.0
91        
92        # Partial reward for maintaining optimal moisture (0.4-0.6)
93        if 0.4 <= self.soil_moisture <= 0.6:
94            reward += 0.05
95        
96        # Reward for maintaining adequate nitrogen levels
97        if self.nitrogen_level > 0.3:
98            reward += 0.02
99        
100        # Reward for good crop health
101        if self.crop_health > 0.5:
102            reward += 0.03
103        
104        # Large reward for harvesting when crop health is high
105        if action == 3:  # Harvest action
106            reward += self.crop_health * 0.8  # Scales from 0 to 0.8
107        
108        # Ensure reward is strictly between 0.0 and 1.0
109        # Use tight bounds to guarantee strictly between (not equal to) endpoints
110        reward = max(0.001, min(0.999, reward))
111        
112        return reward
113    
114    def reset(self):
115        """Reset the environment to initial state."""
116        self.soil_moisture = 0.5
117        self.nitrogen_level = 0.5
118        self.crop_health = 0.5
119        self.turn_count = 0
120    
121    def get_state(self):
122        """Return the current state as a dictionary."""
123        return {
124            "soil_moisture": self.soil_moisture,
125            "nitrogen_level": self.nitrogen_level,
126            "crop_health": self.crop_health,
127            "turn_count": self.turn_count
128        }
129