Opened 11 years ago

Closed 5 months ago

#12070 closed defect (invalid)

Unavoidable DeprecationWarnings when calling piecewise functions

Reported by: mjo Owned by: burcin
Priority: minor Milestone: sage-duplicate/invalid/wontfix
Component: symbolics Keywords:
Cc: kcrisman Merged in:
Authors: Reviewers: Michael Orlitzky, Samuel Lelièvre
Report Upstream: N/A Work issues:
Branch: Commit:
Dependencies: Stopgaps:

Status badges

Description

When using piecewise functions across modules, you can find yourself unable to avoid the DeprecationWarning? resulting from positional arguments, e.g. f(0).

A small example:

some_library.py

from sage.all import *

def make_f():
    x = SR.symbol('x', domain='real')
    f = piecewise([[(-1,1), x**2]])
    return f

some_script.py

from some_library import *

my_f = make_f()
my_f(0)

There is no obvious (or un-obvious, as far as I know) way to avoid the warning here.

The output, for reference:

$ sage some_script.py 
some_script.py:4: DeprecationWarning: Substitution using function-call syntax and unnamed arguments is deprecated and will be removed from a future release of Sage; you can use named arguments instead, like EXPR(x=..., y=...)
  my_f(0)

Change History (18)

comment:1 Changed 11 years ago by kini

This produces the same output in the Sage console (directly after starting it) so I doubt it has anything to do with modules or .py / .sage files in particular.

Indeed something is screwed up here, though.

comment:2 Changed 11 years ago by mjo

Well, in a sage prompt there's an easy workaround: write f(x) = piecewise(...) instead of just f = ...

That doesn't work outside of a prompt, though, and the preprocessor breaks some imports if you try to rename the *.py files to *.sage.

comment:3 Changed 11 years ago by kini

Actually that doesn't work - I get a TypeError with no message, which is pretty strange. I also saw this same TypeError when trying to coerce a PiecewisePolynomial into SR (the Symbolic Ring) so that I could write .function(x) inside your definition of make_f, which I originally thought should be the correct way to do this.

comment:4 Changed 11 years ago by mjo

Oh, sorry. This is how to make it work in the prompt:

sage: f1(x) = 2*x
sage: f = piecewise([[(-1,1), f1]])

I was planning an "easy" patch for this too, but it turns out to be harder than it looks. You can supply a variable to piecewise() to fix my simple example, but that causes other problems by turning everything into a callable expression.

comment:5 Changed 10 years ago by kcrisman

  • Cc kcrisman added

comment:6 Changed 9 years ago by jdemeyer

  • Milestone changed from sage-5.11 to sage-5.12

comment:7 Changed 8 years ago by vbraun_spam

  • Milestone changed from sage-6.1 to sage-6.2

comment:8 Changed 8 years ago by vbraun_spam

  • Milestone changed from sage-6.2 to sage-6.3

comment:9 Changed 8 years ago by vbraun_spam

  • Milestone changed from sage-6.3 to sage-6.4

comment:10 follow-up: Changed 6 years ago by nbruin

The example in this ticket is just misuse. piecewise takes functions, not expressions. Oneliner solution is

f = piecewise([[(-1,1), (x**2).function(x)]])

It's essential to be explicit about the variable name. See:

var('foo,bar')
f = piecewise([[(-1,1), (foo+bar).function(foo)]])

Close as invalid or resolve by updating documentation?

comment:11 Changed 6 years ago by slelievre

I vote to update the documentation. Maybe we also need a thematic tutorial about piecewise-defined functions. Questions about them are quite frequent in the various help channels.

comment:12 Changed 6 years ago by kcrisman

Or to use Volker's new piecewise functions, #14801. But there are some things that no longer work with those, I guess (the oooold stuff about fourier or whatever) and there are some other roadblocks. But probably in the long run that might be better unless we can somehow integrate piecewise.mac in Maxima, but I'm not even sure those are well-debugged.

comment:13 in reply to: ↑ 10 Changed 6 years ago by mjo

Replying to nbruin:

The example in this ticket is just misuse. piecewise takes functions, not expressions.

Ok, but the existing doctests and examples (mis)use that same format (I never knew I could/should change an expression into a function). The ones that don't, rely on the preparsing of f(x) = ... that isn't helpful to people using piecewise() in python code. What do we do with f(x) = 1, change it to f = SR(1).function(x)?

I think f = SR(1).function(x) is stupid, but having examples that only work when preparsed isn't great either. How about we just fix this for symbolic expressions of one variable?

if is_Expression(f):
    if len(f.variables()) == 1:
        f = f.function(f.variables()[0]) # We know what you meant bro.
    else:
        raise Whatever()

If there's a good reason not to do that, then the examples illustrating e.g. (x**2).function(x) should at least be prominent.

comment:14 Changed 6 years ago by slelievre

About f(x) = 1 vs f = SR(1).function(x), maybe we could introduce constant_function and use f = constant_function(1).

comment:15 Changed 5 months ago by mjo

  • Milestone changed from sage-6.4 to sage-duplicate/invalid/wontfix

This got fixed somewhere along the way:

sage: f = piecewise([[(-1,1), SR(1)]])
sage: f(0)
1

comment:16 Changed 5 months ago by mjo

  • Status changed from new to needs_review

comment:17 Changed 5 months ago by slelievre

  • Reviewers set to Michael Orlitzky, Samuel Lelièvre
  • Status changed from needs_review to positive_review

Tried it in Sage 9.5.beta9, seems indeed fixed.

comment:18 Changed 5 months ago by mkoeppe

  • Resolution set to invalid
  • Status changed from positive_review to closed
Note: See TracTickets for help on using tickets.