Exemple #1
0
    def add_variables_and_ranges(plot):
        """make sure all limits are in the form (symbol, a, b)"""

        # find where the limits begin and expressions end
        for i in range(len(plot)):
            if isinstance(plot[i], Tuple):
                break
        else:
            i = len(plot) + 1
        exprs = list(plot[:i])
        assert all(isinstance(e, Expr) for e in exprs)
        assert all(isinstance(t, Tuple) for t in plot[i:])

        ranges = set([i for i in plot[i:] if isinstance(i, Tuple) and len(i) > 1])
        range_variables = set([t[0] for t in ranges if len(t) == 3])
        expr_free = set_union(*[e.free_symbols for e in exprs if isinstance(e, Expr)])

        default_range = Tuple(-10, 10)

        # unambiguous cases for limits
        #   no ranges
        if not ranges:
            plot = exprs + [Tuple(e) + default_range for e in expr_free or [Dummy()]]

        #   all limits of length 3
        elif all(len(i) == 3 for i in ranges):
            pass

        #   all ranges the same
        elif len(ranges) == 1:
            range1 = ranges.pop()
            if len(range1) == 2:
                plot = exprs + [Tuple(x) + range1 for x in expr_free]

        #   ranges cover free variables of expression
        elif expr_free < range_variables:
            plot = exprs + [i if len(i) == 3 else Tuple(Dummy()) + i for i in ranges]

        #   ranges cover all but 1 free variable
        elif len(expr_free - range_variables) == 1:
            x = (expr_free - range_variables).pop()
            ranges = list(ranges)
            for i, ri in enumerate(ranges):
                if len(ri) == 2:
                    ranges[i] = Tuple(x) + ri
                    break
            else:
                ranges.append(Tuple(x) + default_range)
            for i, ri in enumerate(ranges):
                if len(ri) == 2:
                    ranges[i] = Tuple(Dummy()) + ri
            plot = exprs + ranges

        #   all implicit ranges
        elif all(len(i) == 2 for i in ranges):
            more = len(ranges) - len(expr_free)
            all_free = list(expr_free) + [Dummy() for i in range(more)]
            ranges = list(ranges)
            ranges.extend(-more*[default_range])
            plot = exprs + [Tuple(all_free[i]) + ri for i, ri in enumerate(ranges)]

        else:
            raise ValueError('erroneous or unanticipated range input')

        return plot
Exemple #2
0
def plot_implicit(expr, *args, **kwargs):
    """A plot function to plot implicit equations / inequalities.

    Arguments
    =========

    - ``expr`` : The equation / inequality that is to be plotted.
    - ``(x, xmin, xmax)`` optional, 3-tuple denoting the range of symbol
      ``x``
    - ``(y, ymin, ymax)`` optional, 3-tuple denoting the range of symbol
      ``y``

    The following arguments can be passed as named parameters.

    - ``adaptive``. Boolean. The default value is set to True. It has to be
        set to False if you want to use a mesh grid.

    - ``depth`` integer. The depth of recursion for adaptive mesh grid.
        Default value is 0. Takes value in the range (0, 4).

    - ``points`` integer. The number of points if adaptive mesh grid is not
        used. Default value is 200.

    - ``title`` string .The title for the plot.

    - ``xlabel`` string. The label for the x - axis

    - ``ylabel`` string. The label for the y - axis

    plot_implicit, by default, uses interval arithmetic to plot functions. If
    the expression cannot be plotted using interval arithmetic, it defaults to
    a generating a contour using a mesh grid of fixed number of points. By
    setting adaptive to False, you can force plot_implicit to use the mesh
    grid. The mesh grid method can be effective when adaptive plotting using
    interval arithmetic, fails to plot with small line width.

    Examples:
    =========

    Plot expressions:

    >>> from sympy import plot_implicit, cos, sin, symbols, Eq
    >>> x, y = symbols('x y')

    Without any ranges for the symbols in the expression

    >>> p1 = plot_implicit(Eq(x**2 + y**2, 5)) #doctest: +SKIP

    With the range for the symbols

    >>> p2 = plot_implicit(Eq(x**2 + y**2, 3), (x, -3, 3), (y, -3, 3)) #doctest: +SKIP

    With depth of recursion as argument.

    >>> p3 = plot_implicit(Eq(x**2 + y**2, 5), (x, -4, 4), (y, -4, 4), depth = 2) #doctest: +SKIP

    Using mesh grid and not using adaptive meshing.

    >>> p4 = plot_implicit(Eq(x**2 + y**2, 5), (x, -5, 5), (y, -2, 2), adaptive=False) #doctest: +SKIP

    Using mesh grid with number of points as input.

    >>> p5 = plot_implicit(Eq(x**2 + y**2, 5), (x, -5, 5), (y, -2, 2), adaptive=False, points=400) #doctest: +SKIP

    Plotting regions.

    >>> p6 = plot_implicit(y > x**2) #doctest: +SKIP

    Plotting Using boolean conjunctions.

    >>> p7 = plot_implicit(And(y > x, y > -x)) #doctest: +SKIP
    """

    assert isinstance(expr, Expr)
    has_equality = False #Represents whether the expression contains an Equality,
                     #GreaterThan or LessThan

    def arg_expand(bool_expr):
        """
        Recursively expands the arguments of an Boolean Function
        """
        for arg in bool_expr.args:
            if isinstance(arg, BooleanFunction):
                arg_expand(arg)
            elif isinstance(arg, Relational):
                arg_list.append(arg)

    arg_list = []
    if isinstance(expr, BooleanFunction):
        arg_expand(expr)

    #Check whether there is an equality in the expression provided.
        if any(isinstance(e, (Equality, GreaterThan, LessThan))
                            for e in arg_list):
            has_equality = True

    elif not isinstance(expr, Relational):
        expr = Eq(expr, 0)
        has_equality = True
    elif isinstance(expr, (Equality, GreaterThan, LessThan)):
        has_equality = True

    free_symbols = set(expr.free_symbols)
    range_symbols = set([t[0] for t in args])
    symbols = set_union(free_symbols, range_symbols)
    if len(symbols) > 2:
        raise NotImplementedError("Implicit plotting is not implemented for "
                                    "more than 2 variables")

    #Create default ranges if the range is not provided.
    default_range = Tuple(-5, 5)
    if len(args) == 2:
        var_start_end_x = args[0]
        var_start_end_y = args[1]
    elif len(args) == 1:
        if len(free_symbols) == 2:
            var_start_end_x = args[0]
            var_start_end_y, = (Tuple(e) + default_range
                                for e in (free_symbols - range_symbols))
        else:
            var_start_end_x, = (Tuple(e) + default_range for e in free_symbols)
            #Create a random symbol
            var_start_end_y = Tuple(Dummy()) + default_range

    elif len(args) == 0:
        if len(free_symbols) == 1:
            var_start_end_x, = (Tuple(e) + default_range for e in free_symbols)
            #create a random symbol
            var_start_end_y = Tuple(Dummy()) + default_range
        else:
            var_start_end_x, var_start_end_y = (Tuple(e) + default_range
                                                for e in free_symbols)

    use_interval = kwargs.pop('adaptive', True)
    nb_of_points = kwargs.pop('points', 300)
    depth = kwargs.pop('depth', 0)
    #Check whether the depth is greater than 4 or less than 0.
    if depth > 4:
        depth = 4
    elif depth < 0:
        depth = 0

    series_argument = ImplicitSeries(expr, var_start_end_x, var_start_end_y,
                                    has_equality, use_interval, depth,
                                    nb_of_points)
    show = kwargs.pop('show', True)

    #set the x and y limits
    kwargs['xlim'] = tuple(float(x) for x in var_start_end_x[1:])
    kwargs['ylim'] = tuple(float(y) for y in var_start_end_y[1:])
    p = Plot(series_argument, **kwargs)
    if show:
        p.show()
    return p
Exemple #3
0
def _preprocess(expr, func=None, hint='_Integral'):
    """Prepare expr for solving by making sure that differentiation
    is done so that only func remains in unevaluated derivatives and
    (if hint doesn't end with _Integral) that doit is applied to all
    other derivatives. If hint is None, don't do any differentiation.
    (Currently this may cause some simple differential equations to
    fail.)

    In case func is None, an attempt will be made to autodetect the
    function to be solved for.

    >>> from sympy.solvers.deutils import _preprocess
    >>> from sympy import Derivative, Function, Integral, sin
    >>> from sympy.abc import x, y, z
    >>> f, g = map(Function, 'fg')

    Apply doit to derivatives that contain more than the function
    of interest:

    >>> _preprocess(Derivative(f(x) + x, x))
    (Derivative(f(x), x) + 1, f(x))

    Do others if the differentiation variable(s) intersect with those
    of the function of interest or contain the function of interest:

    >>> _preprocess(Derivative(g(x), y, z), f(y))
    (0, f(y))
    >>> _preprocess(Derivative(f(y), z), f(y))
    (0, f(y))

    Do others if the hint doesn't end in '_Integral' (the default
    assumes that it does):

    >>> _preprocess(Derivative(g(x), y), f(x))
    (Derivative(g(x), y), f(x))
    >>> _preprocess(Derivative(f(x), y), f(x), hint='')
    (0, f(x))

    Don't do any derivatives if hint is None:

    >>> eq = Derivative(f(x) + 1, x) + Derivative(f(x), y)
    >>> _preprocess(eq, f(x), hint=None)
    (Derivative(f(x) + 1, x) + Derivative(f(x), y), f(x))

    If it's not clear what the function of interest is, it must be given:

    >>> eq = Derivative(f(x) + g(x), x)
    >>> _preprocess(eq, g(x))
    (Derivative(f(x), x) + Derivative(g(x), x), g(x))
    >>> try: _preprocess(eq)
    ... except ValueError: print "A ValueError was raised."
    A ValueError was raised.

    """

    derivs = expr.atoms(Derivative)
    if not func:
        funcs = set_union(*[d.atoms(AppliedUndef) for d in derivs])
        if len(funcs) != 1:
            raise ValueError('The function cannot be '
                'automatically detected for %s.' % expr)
        func = funcs.pop()
    fvars = set(func.args)
    if hint is None:
        return expr, func
    reps = [(d, d.doit()) for d in derivs if not hint.endswith('_Integral') or
            d.has(func) or set(d.variables) & fvars]
    eq = expr.subs(reps)
    return eq, func
Exemple #4
0
    def add_variables_and_ranges(plot):
        """make sure all limits are in the form (symbol, a, b)"""

        # find where the limits begin and expressions end
        for i in range(len(plot)):
            if isinstance(plot[i], Tuple):
                break
        else:
            i = len(plot) + 1
        exprs = list(plot[:i])
        assert all(isinstance(e, Expr) for e in exprs)
        assert all(isinstance(t, Tuple) for t in plot[i:])

        ranges = set([i for i in plot[i:] if isinstance(i, Tuple) and len(i) > 1])
        range_variables = set([t[0] for t in ranges if len(t) == 3])
        expr_free = set_union(*[e.free_symbols for e in exprs if isinstance(e, Expr)])

        default_range = Tuple(-10, 10)

        # unambiguous cases for limits
        #   no ranges
        if not ranges:
            plot = exprs + [Tuple(e) + default_range for e in expr_free or [Dummy()]]

        #   all limits of length 3
        elif all(len(i) == 3 for i in ranges):
            pass

        #   all ranges the same
        elif len(ranges) == 1:
            range1 = ranges.pop()
            if len(range1) == 2:
                plot = exprs + [Tuple(x) + range1 for x in expr_free]

        #   ranges cover free variables of expression
        elif expr_free < range_variables:
            plot = exprs + [i if len(i) == 3 else Tuple(Dummy()) + i for i in ranges]

        #   ranges cover all but 1 free variable
        elif len(expr_free - range_variables) == 1:
            x = (expr_free - range_variables).pop()
            ranges = list(ranges)
            for i, ri in enumerate(ranges):
                if len(ri) == 2:
                    ranges[i] = Tuple(x) + ri
                    break
            else:
                ranges.append(Tuple(x) + default_range)
            for i, ri in enumerate(ranges):
                if len(ri) == 2:
                    ranges[i] = Tuple(Dummy()) + ri
            plot = exprs + ranges

        #   all implicit ranges
        elif all(len(i) == 2 for i in ranges):
            more = len(ranges) - len(expr_free)
            all_free = list(expr_free) + [Dummy() for i in range(more)]
            ranges = list(ranges)
            ranges.extend(-more*[default_range])
            plot = exprs + [Tuple(all_free[i]) + ri for i, ri in enumerate(ranges)]

        else:
            raise ValueError('erroneous or unanticipated range input')

        return plot
Exemple #5
0
def _preprocess(expr, func=None, hint='_Integral'):
    """Prepare expr for solving by making sure that differentiation
    is done so that only func remains in unevaluated derivatives and
    (if hint doesn't end with _Integral) that doit is applied to all
    other derivatives. If hint is None, don't do any differentiation.
    (Currently this may cause some simple differential equations to
    fail.)

    In case func is None, an attempt will be made to autodetect the
    function to be solved for.

    >>> from sympy.solvers.deutils import _preprocess
    >>> from sympy import Derivative, Function, Integral, sin
    >>> from sympy.abc import x, y, z
    >>> f, g = map(Function, 'fg')

    Apply doit to derivatives that contain more than the function
    of interest:

    >>> _preprocess(Derivative(f(x) + x, x))
    (Derivative(f(x), x) + 1, f(x))

    Do others if the differentiation variable(s) intersect with those
    of the function of interest or contain the function of interest:

    >>> _preprocess(Derivative(g(x), y, z), f(y))
    (0, f(y))
    >>> _preprocess(Derivative(f(y), z), f(y))
    (0, f(y))

    Do others if the hint doesn't end in '_Integral' (the default
    assumes that it does):

    >>> _preprocess(Derivative(g(x), y), f(x))
    (Derivative(g(x), y), f(x))
    >>> _preprocess(Derivative(f(x), y), f(x), hint='')
    (0, f(x))

    Don't do any derivatives if hint is None:

    >>> eq = Derivative(f(x) + 1, x) + Derivative(f(x), y)
    >>> _preprocess(eq, f(x), hint=None)
    (Derivative(f(x) + 1, x) + Derivative(f(x), y), f(x))

    If it's not clear what the function of interest is, it must be given:

    >>> eq = Derivative(f(x) + g(x), x)
    >>> _preprocess(eq, g(x))
    (Derivative(f(x), x) + Derivative(g(x), x), g(x))
    >>> try: _preprocess(eq)
    ... except ValueError: print "A ValueError was raised."
    A ValueError was raised.

    """

    derivs = expr.atoms(Derivative)
    if not func:
        funcs = set_union(*[d.atoms(AppliedUndef) for d in derivs])
        if len(funcs) != 1:
            raise ValueError('The function cannot be '
                             'automatically detected for %s.' % expr)
        func = funcs.pop()
    fvars = set(func.args)
    if hint is None:
        return expr, func
    reps = [
        (d, d.doit()) for d in derivs
        if not hint.endswith('_Integral') or d.has(func) or set(d.variables)
        & fvars
    ]
    eq = expr.subs(reps)
    return eq, func