Here is the performance for three suggestions. Suggestion 3 is the fastest, 
and for me it looks cleaner than the others.

[image: suggestions.PNG]

2021년 3월 31일 수요일 오후 3시 24분 38초 UTC+9에 JSS95님이 작성:

> In SymPy, we have two ways to get the mathematical property of an object : 
> the old assumptions system and the new assumptions system.
> With old assumptions system, the property is accessed by `.is_[...]` 
> attribute. Here, property of the object is intrinsic.
> ```
> In [1]: x = Symbol('x', positive=True)
> In [2]: x.is_positive
> Out[2]: True
> ```
> With new assumption system, the property is accessed by assumption 
> predicate and `ask()` function. Here, property of the object can be 
> extrinsically assumed.
> ```
> In [1]: x = Symbol('x')
> In [2]: ask(Q.integer(x), Q.even(x))
> Out[2]: True
> ```
>
> Old assumption system is used in evaluation logic because it is faster. In 
> refinement logic where user can pass local assumptions, new assumption 
> system is used.
> This results the duplication in two methods. For example, evaluation logic 
> of `Abs` is vaguely like this:
> ```
> def eval_Abs(x):
>     if x.is_nonnegative:
>         return x
>     ...
> ```
> And refinement logic of `Abs` is like this:
> ```
> def eval_Abs(x, assumptions=True):
>     if ask(Q.nonnegative(x), assumptions):
>         return x
>     ...
> ```
>
> As you can see, two codes are mostly identical and the only difference is 
> old assumptions vs new assumptions. By introducing a function which can 
> switch between two behaviors, we can remove this duplication.
>
> The first suggestion is to pass a getter function.
> ```
> def eval_Abs(x, getter):
>     if getter(x, 'nonnegative'):
>         return x
>     ...
> ```
> Here, we can pass `lambda x, key : getattr(x, "is_%s" % key)` to getter 
> for evaluation, and `lambda x, key : ask(getattr(Q, key)(x), assumptions)` 
> for refinement.
> Pros :
> - Easy to implement
> Cons:
> - `getattr(x, "is_%s" % "positive")` is slower than `x.is_positive`.
> - `getter(x, '...')` everywhere looks ugly.
>
> The second suggestion is proposed by oscarbenjamin in 
> https://github.com/sympy/sympy/pull/21203#issuecomment-810134012.
> If I understood correctly, the idea is to introduce `AssumptionsWrapper` 
> class like this:
> ```
> class AssumptionsWrapper(Basic):
>     def __new__(cls, expr, assumptions=True):
>         if assumptions == True:
>             return expr
>         obj = super().__new__(cls, expr, assumptions)
>         obj.expr = expr
>         obj.assumptions = assumptions
>         return obj
>     def _eval_is_positive(self):
>         return ask(Q.positive(self.expr), self.assumptions)
> ```
> And `eval_Abs` will be like this:
> ```
> def eval_Abs(x, assumptions=True):
>     _x = AssumptionsWrapper(x, assumptions)
>     if _x.is_positive:
>         return x
>     ...
> ```
> Pros :
> - No slowdown for retrieving `.is_positive` attribute with old assumptions
> Cons:
> - Generating wrapper objects is slow.
> - Having wrapped objects everywhere makes the code messy
>
> And here is the third suggestion, which is to modify `ManagedProperties` 
> (metaclass for `Basic`) to automatically define `check_[...]` methods for 
> every keys.
> The design will be like this:
> ```
> ...
>     # This method will be automatically generated by metaclass
>     def check_positive(self, assumptions=True):
>         if assumptions is True:
>             return self.is_positive
>         else:
>             return ask(Q.positive(self), assumptions)
> ```
> And `eval_Abs` will be:
> ```
> def eval_Abs(x, assumptions=True):
>     if x.check_nonnegative(assumptions):
>         return x
>     ...
> ```
> Pros:
> - Easy to implement. I tried this, and it required only <20 more lines in 
> core/assumptions file
> - Fastest
> - Cleaner code
> Cons:
> - Basic will be cluttered up with more methods
>

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sympy/06d5c762-9445-4861-b3c0-9d548cfa38f9n%40googlegroups.com.

Reply via email to