From a738c8de30c99d30f0e59f91583fe741b4b26e8b Mon Sep 17 00:00:00 2001 From: Kakodkar Date: Mon, 17 Nov 2025 16:02:55 -0600 Subject: [PATCH 1/4] geq 0 treated as eq == True --- src/energia/modeling/constraints/bind.py | 1 + src/energia/modeling/indices/sample.py | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/energia/modeling/constraints/bind.py b/src/energia/modeling/constraints/bind.py index 652650db..4dd278bf 100644 --- a/src/energia/modeling/constraints/bind.py +++ b/src/energia/modeling/constraints/bind.py @@ -5,6 +5,7 @@ import logging from functools import cached_property from typing import TYPE_CHECKING + from gana import V from gana.sets.function import F diff --git a/src/energia/modeling/indices/sample.py b/src/energia/modeling/indices/sample.py index 3ab3b415..af48c2be 100644 --- a/src/energia/modeling/indices/sample.py +++ b/src/energia/modeling/indices/sample.py @@ -659,7 +659,15 @@ def __le__(self, other): Bind(sample=self, parameter=other, leq=True, forall=self._forall) def __ge__(self, other): - Bind(sample=self, parameter=other, geq=True, forall=self._forall) + + if isinstance(other, (int, float)) and other == 0: + # if a zero lower bound is given + # just declare the variable + # it will be non-negative by default + # and will begin a commodity balance + self.V() + else: + Bind(sample=self, parameter=other, geq=True, forall=self._forall) def __eq__(self, other): From 206ed15c81b8a5a6e1675759c8f184e1a8c6505e Mon Sep 17 00:00:00 2001 From: Kakodkar Date: Mon, 17 Nov 2025 16:05:02 -0600 Subject: [PATCH 2/4] replaced eq True by geq 0 if nn --- src/energia/components/operations/operation.py | 2 +- src/energia/components/operations/storage.py | 4 ++-- src/energia/modeling/constraints/balance.py | 2 +- src/energia/modeling/indices/sample.py | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/energia/components/operations/operation.py b/src/energia/components/operations/operation.py index 46c3b5b6..c7a43cea 100644 --- a/src/energia/components/operations/operation.py +++ b/src/energia/components/operations/operation.py @@ -147,7 +147,7 @@ def _check_capacity_bound(self, space: Location | Linkage): if space not in self.capacity_aspect.bound_spaces[self]["ub"]: # check if operational capacity has been bound # this is not a check, this generates a constraint - _ = self.capacity_sample(space, self.horizon) == True + _ = self.capacity_sample(space, self.horizon) > 0 return self, space, self.horizon diff --git a/src/energia/components/operations/storage.py b/src/energia/components/operations/storage.py index ec8cc629..f7885261 100644 --- a/src/energia/components/operations/storage.py +++ b/src/energia/components/operations/storage.py @@ -193,7 +193,7 @@ def _check_capacity_bound(self, space: Location) -> bool: if space not in self.capacity_aspect.bound_spaces[self.stored]["ub"]: # check if the storage capacity has been bound at that location # Note: this is not a check, this generates a constraint - _ = self.capacity(space, self.horizon) == True + _ = self.capacity(space, self.horizon) > 0 return self, space, self.horizon @@ -203,7 +203,7 @@ def _init_inventory_aspect(self): """Initializes the inventory aspect bound spaces for the stored resource""" if self.stored not in self.inventory_aspect.bound_spaces: - _ = self.inventory_aspect(self.stored) == True + _ = self.inventory_aspect(self.stored) > 0 def _get_times(self, space: Location) -> list[Periods]: """Gets times where inventory is defined""" diff --git a/src/energia/modeling/constraints/balance.py b/src/energia/modeling/constraints/balance.py index eec3fdfc..a51d027a 100644 --- a/src/energia/modeling/constraints/balance.py +++ b/src/energia/modeling/constraints/balance.py @@ -228,7 +228,7 @@ def _init_sample(self): lower_times = [t for t in _balances if t > self.time] if _balances else False if lower_times: - _ = self.aspect(self.commodity, self.space, lower_times[0]) == True + _ = self.aspect(self.commodity, self.space, lower_times[0]) > 0 def __eq__(self, other: Self): return is_(self.aspect, other.aspect) and self.domain == other.domain diff --git a/src/energia/modeling/indices/sample.py b/src/energia/modeling/indices/sample.py index af48c2be..a51b4d5f 100644 --- a/src/energia/modeling/indices/sample.py +++ b/src/energia/modeling/indices/sample.py @@ -481,7 +481,7 @@ def Vlag(self): return getattr(self.program, self.aspect.name)(*self.domain.I) except AttributeError: - _ = self == True + _ = self > 0 return getattr(self.program, self.aspect.name)(*self.domain.I) except KeyError: @@ -660,7 +660,7 @@ def __le__(self, other): def __ge__(self, other): - if isinstance(other, (int, float)) and other == 0: + if self.aspect.nn and isinstance(other, (int, float)) and other == 0: # if a zero lower bound is given # just declare the variable # it will be non-negative by default @@ -686,7 +686,7 @@ def __eq__(self, other): else: if callable(self.of): - _ = self.of(*self.domain.index_primary[1:]) == True + _ = self.of(*self.domain.index_primary[1:]) > 0 Bind(sample=self, parameter=other, eq=True, forall=self._forall) def __gt__(self, other): From 4f6c555a2fae7c8bae087e35b0491c706e5dd3bf Mon Sep 17 00:00:00 2001 From: Kakodkar Date: Mon, 17 Nov 2025 16:12:58 -0600 Subject: [PATCH 3/4] replaced eq True by geq 0 if nn --- src/energia/components/operations/operation.py | 2 +- src/energia/components/operations/storage.py | 4 ++-- src/energia/library/examples/energy.py | 2 +- src/energia/modeling/constraints/balance.py | 2 +- src/energia/modeling/indices/sample.py | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/energia/components/operations/operation.py b/src/energia/components/operations/operation.py index c7a43cea..b73d55a5 100644 --- a/src/energia/components/operations/operation.py +++ b/src/energia/components/operations/operation.py @@ -147,7 +147,7 @@ def _check_capacity_bound(self, space: Location | Linkage): if space not in self.capacity_aspect.bound_spaces[self]["ub"]: # check if operational capacity has been bound # this is not a check, this generates a constraint - _ = self.capacity_sample(space, self.horizon) > 0 + _ = self.capacity_sample(space, self.horizon) >= 0 return self, space, self.horizon diff --git a/src/energia/components/operations/storage.py b/src/energia/components/operations/storage.py index f7885261..b21c71a5 100644 --- a/src/energia/components/operations/storage.py +++ b/src/energia/components/operations/storage.py @@ -193,7 +193,7 @@ def _check_capacity_bound(self, space: Location) -> bool: if space not in self.capacity_aspect.bound_spaces[self.stored]["ub"]: # check if the storage capacity has been bound at that location # Note: this is not a check, this generates a constraint - _ = self.capacity(space, self.horizon) > 0 + _ = self.capacity(space, self.horizon) >= 0 return self, space, self.horizon @@ -203,7 +203,7 @@ def _init_inventory_aspect(self): """Initializes the inventory aspect bound spaces for the stored resource""" if self.stored not in self.inventory_aspect.bound_spaces: - _ = self.inventory_aspect(self.stored) > 0 + _ = self.inventory_aspect(self.stored) >= 0 def _get_times(self, space: Location) -> list[Periods]: """Gets times where inventory is defined""" diff --git a/src/energia/library/examples/energy.py b/src/energia/library/examples/energy.py index 2352f138..697b1d76 100644 --- a/src/energia/library/examples/energy.py +++ b/src/energia/library/examples/energy.py @@ -266,7 +266,7 @@ def design_scheduling_material_modes(): m.declare(Resource, ["power", "wind", "solar"]) _ = m.solar.consume == True - _ = m.wind.consume == True + _ = m.wind.consume >= 0 _ = m.power.release.prep(180) >= [0.6, 0.7, 0.8, 0.3] _ = m.gwp.emit(m.lir.consume) == 9600 diff --git a/src/energia/modeling/constraints/balance.py b/src/energia/modeling/constraints/balance.py index a51d027a..3949964b 100644 --- a/src/energia/modeling/constraints/balance.py +++ b/src/energia/modeling/constraints/balance.py @@ -228,7 +228,7 @@ def _init_sample(self): lower_times = [t for t in _balances if t > self.time] if _balances else False if lower_times: - _ = self.aspect(self.commodity, self.space, lower_times[0]) > 0 + _ = self.aspect(self.commodity, self.space, lower_times[0]) >= 0 def __eq__(self, other: Self): return is_(self.aspect, other.aspect) and self.domain == other.domain diff --git a/src/energia/modeling/indices/sample.py b/src/energia/modeling/indices/sample.py index a51b4d5f..11911b53 100644 --- a/src/energia/modeling/indices/sample.py +++ b/src/energia/modeling/indices/sample.py @@ -481,7 +481,7 @@ def Vlag(self): return getattr(self.program, self.aspect.name)(*self.domain.I) except AttributeError: - _ = self > 0 + _ = self >= 0 return getattr(self.program, self.aspect.name)(*self.domain.I) except KeyError: @@ -686,7 +686,7 @@ def __eq__(self, other): else: if callable(self.of): - _ = self.of(*self.domain.index_primary[1:]) > 0 + _ = self.of(*self.domain.index_primary[1:]) >= 0 Bind(sample=self, parameter=other, eq=True, forall=self._forall) def __gt__(self, other): From 4c00d1d6a6984f4a4418e5754401f9a4617ef94f Mon Sep 17 00:00:00 2001 From: Kakodkar Date: Mon, 17 Nov 2025 16:15:37 -0600 Subject: [PATCH 4/4] replaced eq True by geq 0 if nn --- src/energia/library/examples/energy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/energia/library/examples/energy.py b/src/energia/library/examples/energy.py index 697b1d76..9b8b6dd4 100644 --- a/src/energia/library/examples/energy.py +++ b/src/energia/library/examples/energy.py @@ -265,7 +265,7 @@ def design_scheduling_material_modes(): ) m.declare(Resource, ["power", "wind", "solar"]) - _ = m.solar.consume == True + _ = m.solar.consume >= 0 _ = m.wind.consume >= 0 _ = m.power.release.prep(180) >= [0.6, 0.7, 0.8, 0.3]