-
Notifications
You must be signed in to change notification settings - Fork 4
Feature/network cloning #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 13 commits
5d760f5
fba71cd
3e92e20
d12d77f
c42c48f
35b6758
393d39a
2171b31
a76b96b
1e51b36
7893e94
0f50a9b
9e92f54
244fa11
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,19 +10,22 @@ | |
# | ||
# This file is part of the Antares project. | ||
|
||
from typing import Optional | ||
from dataclasses import dataclass, field, replace | ||
from typing import Any | ||
|
||
from andromede.expression.degree import is_constant | ||
from andromede.expression.expression import ( | ||
Comparator, | ||
ComparisonNode, | ||
ExpressionNode, | ||
is_unbound, | ||
literal, | ||
) | ||
from andromede.expression.print import print_expr | ||
from andromede.model.common import ProblemContext | ||
|
||
|
||
@dataclass | ||
class Constraint: | ||
""" | ||
A constraint linking variables and parameters of a model together. | ||
|
@@ -32,55 +35,39 @@ class Constraint: | |
|
||
name: str | ||
expression: ExpressionNode | ||
lower_bound: ExpressionNode | ||
upper_bound: ExpressionNode | ||
context: ProblemContext | ||
lower_bound: ExpressionNode = field(default=literal(-float("inf"))) | ||
upper_bound: ExpressionNode = field(default=literal(float("inf"))) | ||
context: ProblemContext = field(default=ProblemContext.OPERATIONAL) | ||
|
||
def __init__( | ||
def __post_init__( | ||
self, | ||
name: str, | ||
expression: ExpressionNode, | ||
lower_bound: Optional[ExpressionNode] = None, | ||
upper_bound: Optional[ExpressionNode] = None, | ||
context: ProblemContext = ProblemContext.OPERATIONAL, | ||
) -> None: | ||
self.name = name | ||
self.context = context | ||
|
||
if isinstance(expression, ComparisonNode): | ||
if lower_bound is not None or upper_bound is not None: | ||
if isinstance(self.expression, ComparisonNode): | ||
if not is_unbound(self.lower_bound) or not is_unbound(self.upper_bound): | ||
raise ValueError( | ||
"Both comparison between two expressions and a bound are specfied, set either only a comparison between expressions or a single linear expression with bounds." | ||
) | ||
|
||
merged_expr = expression.left - expression.right | ||
self.expression = merged_expr | ||
|
||
if expression.comparator == Comparator.LESS_THAN: | ||
if self.expression.comparator == Comparator.LESS_THAN: | ||
# lhs - rhs <= 0 | ||
self.upper_bound = literal(0) | ||
self.lower_bound = literal(-float("inf")) | ||
elif expression.comparator == Comparator.GREATER_THAN: | ||
elif self.expression.comparator == Comparator.GREATER_THAN: | ||
# lhs - rhs >= 0 | ||
self.lower_bound = literal(0) | ||
self.upper_bound = literal(float("inf")) | ||
else: # lhs - rhs == 0 | ||
self.lower_bound = literal(0) | ||
self.upper_bound = literal(0) | ||
|
||
self.expression = self.expression.left - self.expression.right | ||
|
||
else: | ||
for bound in [lower_bound, upper_bound]: | ||
if bound is not None and not is_constant(bound): | ||
for bound in [self.lower_bound, self.upper_bound]: | ||
if not is_constant(bound): | ||
raise ValueError( | ||
f"The bounds of a constraint should not contain variables, {print_expr(bound)} was given." | ||
) | ||
|
||
self.expression = expression | ||
if lower_bound is not None: | ||
self.lower_bound = lower_bound | ||
else: | ||
self.lower_bound = literal(-float("inf")) | ||
|
||
if upper_bound is not None: | ||
self.upper_bound = upper_bound | ||
else: | ||
self.upper_bound = literal(float("inf")) | ||
def replicate(self, /, **changes: Any) -> "Constraint": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the backslash useful ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In terms of code, no. It's for the developers. |
||
return replace(self, **changes) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think with the definition of
is_unbound
, I am allowed to use+inf
in both lower bound and upper bound without raising an exception (idem with-inf
). I think the check should be tighter ie.self.lower_bound != -inf
andself.upper_bound != +inf
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the ComparisonNode part, it won't be a problem because some lines below we set the bounds ourselves.
However, for LiteralNodes and ParameterNodes (else statement), I agree with you. I will fix it