feat(constraint.py): Auto-convert hard to soft constraints through soften method - #904
Draft
isanchez-ng wants to merge 6 commits into
Draft
feat(constraint.py): Auto-convert hard to soft constraints through soften method#904isanchez-ng wants to merge 6 commits into
soften method#904isanchez-ng wants to merge 6 commits into
Conversation
…oid alternating between a bare Variable and a tuple of Variables depending on the constraint's sign. Negative is now None for inequality constraints instead of being absent from the return.
… a scalar operand) to accept ConstantLike. The narrow annotation caused mypy to flag valid code
for more information, see https://pre-commit.ci
Merging this PR will degrade performance by 1.2%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Memory | test_to_lp[milp-n=50] |
2 MB | 2.6 MB | -23.08% |
| ❌ | Memory | test_to_lp[merge_balance-severity=0] |
2.6 MB | 3.2 MB | -17.85% |
| ❌ | Memory | test_to_lp[nodal_balance-severity=50] |
2.8 MB | 3.3 MB | -16.1% |
| ⚡ | Memory | test_to_lp[rolling-severity=50] |
429.7 MB | 305.6 MB | +40.61% |
| ⚡ | Memory | test_to_lp[knapsack-n=10000] |
2.8 MB | 2.2 MB | +26.3% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing isanchez-ng:master (f094077) with master (09c34dd)
Footnotes
-
175 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #782
Hi! This is my first contribution. I created a draft just to let you know that I'm working on this. I'll try to complete this code the next weekend 🤓
Changes proposed in this Pull Request
Building soft constraints requires a lot of manual work that can be avoided through a method that modifies both the variables (to add the slacks) and the objective function (to add the penalty term).
Implementation
I followed the proposed structure for the method, but changed some details that I mention on the next section.
Also, I changed slightly the typehints for
objective.__add__. to avoid some mypy errors that weren't actually errors.How did I test this new feature?
For now this is just a draft, so the test has been mainly by code written on a notebook. At some point I'll add unit tests and maybe a notebook. On the mean time, I'll leave the testing code here:
Open questions/discussions
isinstance(var_name, tuple)through their own codes. Instead of that, I proposed a NamedTuple.soften()if the model's objective hasn't been defined yet, sincesoften()adds a penalty term to the existing objective rather than replacing it.soften()run beforeadd_objective(). But doing so creates a weird condition where the linemodel.objective += penalty thingsasserts the objective is still empty, so calling a secondmodel.add_objectiveaftersoften()would raise an error telling the user to passoverwrite=True. Doing that, however, replaces the whole objective expression, and silently discards the penalty termsoften()had already added.soften()also relies onmodel.senseto pick the correct sign for the penalty term. Sincesensedefaults to"min"untilmodel.add_objective()is called with a different value, callingsoften()first risks silently penalizing in the wrong direction if the user later setssense="max".I'm open to discussion on both bullet points if someone else has a better proposal.
To-Dos:
.softenmethodsofteninsidemodel.add_constraintChecklist
AGENTS.md).doc.doc/release_notes.rstof the upcoming release is included.