-
Notifications
You must be signed in to change notification settings - Fork 284
Speed up sol[UnaryExpr] via C-level math and refactor UnaryExpr
#1224
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
Open
Zeroto521
wants to merge
8
commits into
scipopt:master
Choose a base branch
from
Zeroto521:UnaryExpr
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+80
−30
Open
Changes from 7 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
0988f86
refactor: replace Python math with C-level math functions and refacto…
Zeroto521 3c7a981
feat(type stubs): add specific unary expression types
Zeroto521 166dc21
Update CHANGELOG.md
Zeroto521 647f8ac
style(scip): condense UnaryExpr subclass definitions to single lines
Zeroto521 fadf4e1
Remove extra blank line
Zeroto521 c27fe01
Remove extra blank lines
Zeroto521 e5bdabc
Simplify via `ExprLike.__abs__`
Zeroto521 8294d8a
test C-level math functions
Zeroto521 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,7 +42,6 @@ | |
| # which should, in princple, modify the expr. However, since we do not implement __isub__, __sub__ | ||
| # gets called (I guess) and so a copy is returned. | ||
| # Modifying the expression directly would be a bug, given that the expression might be re-used by the user. </pre> | ||
| import math | ||
| from typing import TYPE_CHECKING, Literal, Union | ||
|
|
||
| import numpy as np | ||
|
|
@@ -54,6 +53,12 @@ from cpython.number cimport PyNumber_Check | |
| from cpython.object cimport Py_LE, Py_EQ, Py_GE, Py_TYPE | ||
| from cpython.ref cimport PyObject | ||
| from cpython.tuple cimport PyTuple_GET_ITEM | ||
| from libc.math cimport cos as c_cos | ||
| from libc.math cimport exp as c_exp | ||
| from libc.math cimport fabs as c_fabs | ||
| from libc.math cimport log as c_log | ||
| from libc.math cimport sqrt as c_sqrt | ||
| from libc.math cimport sin as c_sin | ||
|
|
||
| cimport numpy as cnp | ||
| from pyscipopt.scip cimport Variable, Solution | ||
|
|
@@ -278,23 +283,23 @@ cdef class ExprLike: | |
| def __neg__(self, /) -> Union[Expr, GenExpr]: | ||
| return self * -1.0 | ||
|
|
||
| def __abs__(self) -> GenExpr: | ||
| return UnaryExpr(Operator.fabs, buildGenExprObj(self)) | ||
| def __abs__(self, /) -> AbsExpr: | ||
| return AbsExpr(Operator.fabs, buildGenExprObj(self)) | ||
|
|
||
| def exp(self) -> GenExpr: | ||
| return UnaryExpr(Operator.exp, buildGenExprObj(self)) | ||
| def exp(self, /) -> ExpExpr: | ||
| return ExpExpr(Operator.exp, buildGenExprObj(self)) | ||
|
|
||
| def log(self) -> GenExpr: | ||
| return UnaryExpr(Operator.log, buildGenExprObj(self)) | ||
| def log(self, /) -> LogExpr: | ||
| return LogExpr(Operator.log, buildGenExprObj(self)) | ||
|
|
||
| def sqrt(self) -> GenExpr: | ||
| return UnaryExpr(Operator.sqrt, buildGenExprObj(self)) | ||
| def sqrt(self, /) -> SqrtExpr: | ||
| return SqrtExpr(Operator.sqrt, buildGenExprObj(self)) | ||
|
|
||
| def sin(self) -> GenExpr: | ||
| return UnaryExpr(Operator.sin, buildGenExprObj(self)) | ||
| def sin(self, /) -> SinExpr: | ||
| return SinExpr(Operator.sin, buildGenExprObj(self)) | ||
|
|
||
| def cos(self) -> GenExpr: | ||
| return UnaryExpr(Operator.cos, buildGenExprObj(self)) | ||
| def cos(self, /) -> CosExpr: | ||
| return CosExpr(Operator.cos, buildGenExprObj(self)) | ||
|
|
||
|
|
||
| ##@details Polynomial expressions of variables with operator overloading. \n | ||
|
|
@@ -799,24 +804,54 @@ cdef class PowExpr(GenExpr): | |
| return (<GenExpr>self.children[0])._evaluate(sol) ** self.expo | ||
|
|
||
|
|
||
| # Exp, Log, Sqrt, Sin, Cos Expressions | ||
| cdef class UnaryExpr(GenExpr): | ||
|
|
||
| def __init__(self, op, expr): | ||
| self.children = [] | ||
| self.children.append(expr) | ||
| self._op = op | ||
|
|
||
| def __abs__(self) -> UnaryExpr: | ||
| if self._op == "abs": | ||
| return <UnaryExpr>self.copy() | ||
| return UnaryExpr(Operator.fabs, self) | ||
|
|
||
| def __repr__(self): | ||
| def __repr__(self) -> str: | ||
| return self._op + "(" + self.children[0].__repr__() + ")" | ||
|
|
||
|
|
||
| cdef class AbsExpr(UnaryExpr): | ||
|
|
||
| def __abs__(self) -> AbsExpr: | ||
| return <AbsExpr>self.copy() | ||
|
|
||
| cpdef double _evaluate(self, Solution sol) except *: | ||
| return c_fabs((<GenExpr>self.children[0])._evaluate(sol)) | ||
|
|
||
|
Zeroto521 marked this conversation as resolved.
|
||
|
|
||
| cdef class ExpExpr(UnaryExpr): | ||
|
|
||
| cpdef double _evaluate(self, Solution sol) except *: | ||
| return c_exp((<GenExpr>self.children[0])._evaluate(sol)) | ||
|
|
||
|
|
||
| cdef class LogExpr(UnaryExpr): | ||
|
|
||
| cpdef double _evaluate(self, Solution sol) except *: | ||
| return c_log((<GenExpr>self.children[0])._evaluate(sol)) | ||
|
Member
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. Now, things like |
||
|
|
||
|
|
||
| cdef class SqrtExpr(UnaryExpr): | ||
|
|
||
| cpdef double _evaluate(self, Solution sol) except *: | ||
| return c_sqrt((<GenExpr>self.children[0])._evaluate(sol)) | ||
|
|
||
|
|
||
| cdef class SinExpr(UnaryExpr): | ||
|
|
||
| cpdef double _evaluate(self, Solution sol) except *: | ||
| return c_sin((<GenExpr>self.children[0])._evaluate(sol)) | ||
|
|
||
|
|
||
| cdef class CosExpr(UnaryExpr): | ||
|
|
||
| cpdef double _evaluate(self, Solution sol) except *: | ||
| cdef double res = (<GenExpr>self.children[0])._evaluate(sol) | ||
| return math.fabs(res) if self._op == "abs" else getattr(math, self._op)(res) | ||
| return c_cos((<GenExpr>self.children[0])._evaluate(sol)) | ||
|
|
||
|
|
||
| # class for constant expressions | ||
|
|
||
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
Oops, something went wrong.
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.
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.
ExprLike.__abs__can replaceUnaryExpr(Operator.fabs, self)