def nonlinsolve(system, *symbols):
    "\n    Solve system of N non linear equations with M variables, which means both\n    under and overdetermined systems are supported. Positive dimensional\n    system is also supported (A system with infinitely many solutions is said\n    to be positive-dimensional). In Positive dimensional system solution will\n    be dependent on at least one symbol. Returns both real solution\n    and complex solution(If system have). The possible number of solutions\n    is zero, one or infinite.\n\n    Parameters\n    ==========\n\n    system : list of equations\n        The target system of equations\n    symbols : list of Symbols\n        symbols should be given as a sequence eg. list\n\n    Returns\n    =======\n\n    A FiniteSet of ordered tuple of values of `symbols` for which the `system`\n    has solution. Order of values in the tuple is same as symbols present in\n    the parameter `symbols`.\n\n    Please note that general FiniteSet is unordered, the solution returned\n    here is not simply a FiniteSet of solutions, rather it is a FiniteSet of\n    ordered tuple, i.e. the first & only argument to FiniteSet is a tuple of\n    solutions, which is ordered, & hence the returned solution is ordered.\n\n    Also note that solution could also have been returned as an ordered tuple,\n    FiniteSet is just a wrapper `{}` around the tuple. It has no other\n    significance except for the fact it is just used to maintain a consistent\n    output format throughout the solveset.\n\n    For the given set of Equations, the respective input types\n    are given below:\n\n    .. math:: x*y - 1 = 0\n    .. math:: 4*x**2 + y**2 - 5 = 0\n\n    `system  = [x*y - 1, 4*x**2 + y**2 - 5]`\n    `symbols = [x, y]`\n\n    Raises\n    ======\n\n    ValueError\n        The input is not valid.\n        The symbols are not given.\n    AttributeError\n        The input symbols are not `Symbol` type.\n\n    Examples\n    ========\n\n    >>> from sympy.core.symbol import symbols\n    >>> from sympy.solvers.solveset import nonlinsolve\n    >>> x, y, z = symbols('x, y, z', real=True)\n    >>> nonlinsolve([x*y - 1, 4*x**2 + y**2 - 5], [x, y])\n    {(-1, -1), (-1/2, -2), (1/2, 2), (1, 1)}\n\n    1. Positive dimensional system and complements:\n\n    >>> from sympy import pprint\n    >>> from sympy.polys.polytools import is_zero_dimensional\n    >>> a, b, c, d = symbols('a, b, c, d', real=True)\n    >>> eq1 =  a + b + c + d\n    >>> eq2 = a*b + b*c + c*d + d*a\n    >>> eq3 = a*b*c + b*c*d + c*d*a + d*a*b\n    >>> eq4 = a*b*c*d - 1\n    >>> system = [eq1, eq2, eq3, eq4]\n    >>> is_zero_dimensional(system)\n    False\n    >>> pprint(nonlinsolve(system, [a, b, c, d]), use_unicode=False)\n      -1       1               1      -1\n    {(---, -d, -, {d} \\ {0}), (-, -d, ---, {d} \\ {0})}\n       d       d               d       d\n    >>> nonlinsolve([(x+y)**2 - 4, x + y - 2], [x, y])\n    {(-y + 2, y)}\n\n    2. If some of the equations are non polynomial equation then `nonlinsolve`\n    will call `substitution` function and returns real and complex solutions,\n    if present.\n\n    >>> from sympy import exp, sin\n    >>> nonlinsolve([exp(x) - sin(y), y**2 - 4], [x, y])\n    {(log(sin(2)), 2), (ImageSet(Lambda(_n, I*(2*_n*pi + pi) +\n        log(sin(2))), Integers()), -2), (ImageSet(Lambda(_n, 2*_n*I*pi +\n        Mod(log(sin(2)), 2*I*pi)), Integers()), 2)}\n\n    3. If system is Non linear polynomial zero dimensional then it returns\n    both solution (real and complex solutions, if present using\n    `solve_poly_system`):\n\n    >>> from sympy import sqrt\n    >>> nonlinsolve([x**2 - 2*y**2 -2, x*y - 2], [x, y])\n    {(-2, -1), (2, 1), (-sqrt(2)*I, sqrt(2)*I), (sqrt(2)*I, -sqrt(2)*I)}\n\n    4. `nonlinsolve` can solve some linear(zero or positive dimensional)\n    system (because it is using `groebner` function to get the\n    groebner basis and then `substitution` function basis as the new `system`).\n    But it is not recommended to solve linear system using `nonlinsolve`,\n    because `linsolve` is better for all kind of linear system.\n\n    >>> nonlinsolve([x + 2*y -z - 3, x - y - 4*z + 9 , y + z - 4], [x, y, z])\n    {(3*z - 5, -z + 4, z)}\n\n    5. System having polynomial equations and only real solution is present\n    (will be solved using `solve_poly_system`):\n\n    >>> e1 = sqrt(x**2 + y**2) - 10\n    >>> e2 = sqrt(y**2 + (-x + 10)**2) - 3\n    >>> nonlinsolve((e1, e2), (x, y))\n    {(191/20, -3*sqrt(391)/20), (191/20, 3*sqrt(391)/20)}\n    >>> nonlinsolve([x**2 + 2/y - 2, x + y - 3], [x, y])\n    {(1, 2), (1 + sqrt(5), -sqrt(5) + 2), (-sqrt(5) + 1, 2 + sqrt(5))}\n    >>> nonlinsolve([x**2 + 2/y - 2, x + y - 3], [y, x])\n    {(2, 1), (2 + sqrt(5), -sqrt(5) + 1), (-sqrt(5) + 2, 1 + sqrt(5))}\n\n    6. It is better to use symbols instead of Trigonometric Function or\n    Function (e.g. replace `sin(x)` with symbol, replace `f(x)` with symbol\n    and so on. Get soln from `nonlinsolve` and then using `solveset` get\n    the value of `x`)\n\n    How nonlinsolve is better than old solver `_solve_system` :\n    ===========================================================\n\n    1. A positive dimensional system solver : nonlinsolve can return\n    solution for positive dimensional system. It finds the\n    Groebner Basis of the positive dimensional system(calling it as\n    basis) then we can start solving equation(having least number of\n    variable first in the basis) using solveset and substituting that\n    solved solutions into other equation(of basis) to get solution in\n    terms of minimum variables. Here the important thing is how we\n    are substituting the known values and in which equations.\n\n    2. Real and Complex both solutions : nonlinsolve returns both real\n    and complex solution. If all the equations in the system are polynomial\n    then using `solve_poly_system` both real and complex solution is returned.\n    If all the equations in the system are not polynomial equation then goes to\n    `substitution` method with this polynomial and non polynomial equation(s),\n    to solve for unsolved variables. Here to solve for particular variable\n    solveset_real and solveset_complex is used. For both real and complex\n    solution function `_solve_using_know_values` is used inside `substitution`\n    function.(`substitution` function will be called when there is any non\n    polynomial equation(s) is present). When solution is valid then add its\n    general solution in the final result.\n\n    3. Complement and Intersection will be added if any : nonlinsolve maintains\n    dict for complements and Intersections. If solveset find complements or/and\n    Intersection with any Interval or set during the execution of\n    `substitution` function ,then complement or/and Intersection for that\n    variable is added before returning final solution.\n\n    "
    from sympy.polys.polytools import is_zero_dimensional
    if (not system):
        return S.EmptySet
    if (not symbols):
        msg = 'Symbols must be given, for which solution of the system is to be found.'
        raise ValueError(filldedent(msg))
    if hasattr(symbols[0], '__iter__'):
        symbols = symbols[0]
    try:
        sym = symbols[0].is_Symbol
    except AttributeError:
        sym = False
    except IndexError:
        msg = 'Symbols must be given, for which solution of the system is to be found.'
        raise IndexError(filldedent(msg))
    if (not sym):
        msg = 'Symbols or iterable of symbols must be given as second argument, not type %s: %s'
        raise ValueError(filldedent((msg % (type(symbols[0]), symbols[0]))))
    if ((len(system) == 1) and (len(symbols) == 1)):
        return _solveset_work(system, symbols)
    (polys, polys_expr, nonpolys, denominators) = _separate_poly_nonpoly(system, symbols)
    if (len(symbols) == len(polys)):
        if is_zero_dimensional(polys, symbols):
            try:
                return _handle_zero_dimensional(polys, symbols, system)
            except NotImplementedError:
                result = substitution(polys_expr, symbols, exclude=denominators)
                return result
        return _handle_positive_dimensional(polys, symbols, denominators)
    else:
        result = substitution((polys_expr + nonpolys), symbols, exclude=denominators)
        return result
Solve system of N non linear equations with M variables, which means both
under and overdetermined systems are supported. Positive dimensional
system is also supported (A system with infinitely many solutions is said
to be positive-dimensional). In Positive dimensional system solution will
be dependent on at least one symbol. Returns both real solution
and complex solution(If system have). The possible number of solutions
is zero, one or infinite.

Parameters
==========

system : list of equations
    The target system of equations
symbols : list of Symbols
    symbols should be given as a sequence eg. list

Returns
=======

A FiniteSet of ordered tuple of values of `symbols` for which the `system`
has solution. Order of values in the tuple is same as symbols present in
the parameter `symbols`.

Please note that general FiniteSet is unordered, the solution returned
here is not simply a FiniteSet of solutions, rather it is a FiniteSet of
ordered tuple, i.e. the first & only argument to FiniteSet is a tuple of
solutions, which is ordered, & hence the returned solution is ordered.

Also note that solution could also have been returned as an ordered tuple,
FiniteSet is just a wrapper `{}` around the tuple. It has no other
significance except for the fact it is just used to maintain a consistent
output format throughout the solveset.

For the given set of Equations, the respective input types
are given below:

.. math:: x*y - 1 = 0
.. math:: 4*x**2 + y**2 - 5 = 0

`system  = [x*y - 1, 4*x**2 + y**2 - 5]`
`symbols = [x, y]`

Raises
======

ValueError
    The input is not valid.
    The symbols are not given.
AttributeError
    The input symbols are not `Symbol` type.

Examples
========

>>> from sympy.core.symbol import symbols
>>> from sympy.solvers.solveset import nonlinsolve
>>> x, y, z = symbols('x, y, z', real=True)
>>> nonlinsolve([x*y - 1, 4*x**2 + y**2 - 5], [x, y])
{(-1, -1), (-1/2, -2), (1/2, 2), (1, 1)}

1. Positive dimensional system and complements:

>>> from sympy import pprint
>>> from sympy.polys.polytools import is_zero_dimensional
>>> a, b, c, d = symbols('a, b, c, d', real=True)
>>> eq1 =  a + b + c + d
>>> eq2 = a*b + b*c + c*d + d*a
>>> eq3 = a*b*c + b*c*d + c*d*a + d*a*b
>>> eq4 = a*b*c*d - 1
>>> system = [eq1, eq2, eq3, eq4]
>>> is_zero_dimensional(system)
False
>>> pprint(nonlinsolve(system, [a, b, c, d]), use_unicode=False)
  -1       1               1      -1
{(---, -d, -, {d} \ {0}), (-, -d, ---, {d} \ {0})}
   d       d               d       d
>>> nonlinsolve([(x+y)**2 - 4, x + y - 2], [x, y])
{(-y + 2, y)}

2. If some of the equations are non polynomial equation then `nonlinsolve`
will call `substitution` function and returns real and complex solutions,
if present.

>>> from sympy import exp, sin
>>> nonlinsolve([exp(x) - sin(y), y**2 - 4], [x, y])
{(log(sin(2)), 2), (ImageSet(Lambda(_n, I*(2*_n*pi + pi) +
    log(sin(2))), Integers()), -2), (ImageSet(Lambda(_n, 2*_n*I*pi +
    Mod(log(sin(2)), 2*I*pi)), Integers()), 2)}

3. If system is Non linear polynomial zero dimensional then it returns
both solution (real and complex solutions, if present using
`solve_poly_system`):

>>> from sympy import sqrt
>>> nonlinsolve([x**2 - 2*y**2 -2, x*y - 2], [x, y])
{(-2, -1), (2, 1), (-sqrt(2)*I, sqrt(2)*I), (sqrt(2)*I, -sqrt(2)*I)}

4. `nonlinsolve` can solve some linear(zero or positive dimensional)
system (because it is using `groebner` function to get the
groebner basis and then `substitution` function basis as the new `system`).
But it is not recommended to solve linear system using `nonlinsolve`,
because `linsolve` is better for all kind of linear system.

>>> nonlinsolve([x + 2*y -z - 3, x - y - 4*z + 9 , y + z - 4], [x, y, z])
{(3*z - 5, -z + 4, z)}

5. System having polynomial equations and only real solution is present
(will be solved using `solve_poly_system`):

>>> e1 = sqrt(x**2 + y**2) - 10
>>> e2 = sqrt(y**2 + (-x + 10)**2) - 3
>>> nonlinsolve((e1, e2), (x, y))
{(191/20, -3*sqrt(391)/20), (191/20, 3*sqrt(391)/20)}
>>> nonlinsolve([x**2 + 2/y - 2, x + y - 3], [x, y])
{(1, 2), (1 + sqrt(5), -sqrt(5) + 2), (-sqrt(5) + 1, 2 + sqrt(5))}
>>> nonlinsolve([x**2 + 2/y - 2, x + y - 3], [y, x])
{(2, 1), (2 + sqrt(5), -sqrt(5) + 1), (-sqrt(5) + 2, 1 + sqrt(5))}

6. It is better to use symbols instead of Trigonometric Function or
Function (e.g. replace `sin(x)` with symbol, replace `f(x)` with symbol
and so on. Get soln from `nonlinsolve` and then using `solveset` get
the value of `x`)

How nonlinsolve is better than old solver `_solve_system` :
===========================================================

1. A positive dimensional system solver : nonlinsolve can return
solution for positive dimensional system. It finds the
Groebner Basis of the positive dimensional system(calling it as
basis) then we can start solving equation(having least number of
variable first in the basis) using solveset and substituting that
solved solutions into other equation(of basis) to get solution in
terms of minimum variables. Here the important thing is how we
are substituting the known values and in which equations.

2. Real and Complex both solutions : nonlinsolve returns both real
and complex solution. If all the equations in the system are polynomial
then using `solve_poly_system` both real and complex solution is returned.
If all the equations in the system are not polynomial equation then goes to
`substitution` method with this polynomial and non polynomial equation(s),
to solve for unsolved variables. Here to solve for particular variable
solveset_real and solveset_complex is used. For both real and complex
solution function `_solve_using_know_values` is used inside `substitution`
function.(`substitution` function will be called when there is any non
polynomial equation(s) is present). When solution is valid then add its
general solution in the final result.

3. Complement and Intersection will be added if any : nonlinsolve maintains
dict for complements and Intersections. If solveset find complements or/and
Intersection with any Interval or set during the execution of
`substitution` function ,then complement or/and Intersection for that
variable is added before returning final solution.
def nonlinsolve(system, *symbols):
    "\n    Solve system of N non linear equations with M variables, which means both\n    under and overdetermined systems are supported. Positive dimensional\n    system is also supported (A system with infinitely many solutions is said\n    to be positive-dimensional). In Positive dimensional system solution will\n    be dependent on at least one symbol. Returns both real solution\n    and complex solution(If system have). The possible number of solutions\n    is zero, one or infinite.\n\n    Parameters\n    ==========\n\n    system : list of equations\n        The target system of equations\n    symbols : list of Symbols\n        symbols should be given as a sequence eg. list\n\n    Returns\n    =======\n\n    A FiniteSet of ordered tuple of values of `symbols` for which the `system`\n    has solution. Order of values in the tuple is same as symbols present in\n    the parameter `symbols`.\n\n    Please note that general FiniteSet is unordered, the solution returned\n    here is not simply a FiniteSet of solutions, rather it is a FiniteSet of\n    ordered tuple, i.e. the first & only argument to FiniteSet is a tuple of\n    solutions, which is ordered, & hence the returned solution is ordered.\n\n    Also note that solution could also have been returned as an ordered tuple,\n    FiniteSet is just a wrapper `{}` around the tuple. It has no other\n    significance except for the fact it is just used to maintain a consistent\n    output format throughout the solveset.\n\n    For the given set of Equations, the respective input types\n    are given below:\n\n    .. math:: x*y - 1 = 0\n    .. math:: 4*x**2 + y**2 - 5 = 0\n\n    `system  = [x*y - 1, 4*x**2 + y**2 - 5]`\n    `symbols = [x, y]`\n\n    Raises\n    ======\n\n    ValueError\n        The input is not valid.\n        The symbols are not given.\n    AttributeError\n        The input symbols are not `Symbol` type.\n\n    Examples\n    ========\n\n    >>> from sympy.core.symbol import symbols\n    >>> from sympy.solvers.solveset import nonlinsolve\n    >>> x, y, z = symbols('x, y, z', real=True)\n    >>> nonlinsolve([x*y - 1, 4*x**2 + y**2 - 5], [x, y])\n    {(-1, -1), (-1/2, -2), (1/2, 2), (1, 1)}\n\n    1. Positive dimensional system and complements:\n\n    >>> from sympy import pprint\n    >>> from sympy.polys.polytools import is_zero_dimensional\n    >>> a, b, c, d = symbols('a, b, c, d', real=True)\n    >>> eq1 =  a + b + c + d\n    >>> eq2 = a*b + b*c + c*d + d*a\n    >>> eq3 = a*b*c + b*c*d + c*d*a + d*a*b\n    >>> eq4 = a*b*c*d - 1\n    >>> system = [eq1, eq2, eq3, eq4]\n    >>> is_zero_dimensional(system)\n    False\n    >>> pprint(nonlinsolve(system, [a, b, c, d]), use_unicode=False)\n      -1       1               1      -1\n    {(---, -d, -, {d} \\ {0}), (-, -d, ---, {d} \\ {0})}\n       d       d               d       d\n    >>> nonlinsolve([(x+y)**2 - 4, x + y - 2], [x, y])\n    {(-y + 2, y)}\n\n    2. If some of the equations are non polynomial equation then `nonlinsolve`\n    will call `substitution` function and returns real and complex solutions,\n    if present.\n\n    >>> from sympy import exp, sin\n    >>> nonlinsolve([exp(x) - sin(y), y**2 - 4], [x, y])\n    {(log(sin(2)), 2), (ImageSet(Lambda(_n, I*(2*_n*pi + pi) +\n        log(sin(2))), Integers()), -2), (ImageSet(Lambda(_n, 2*_n*I*pi +\n        Mod(log(sin(2)), 2*I*pi)), Integers()), 2)}\n\n    3. If system is Non linear polynomial zero dimensional then it returns\n    both solution (real and complex solutions, if present using\n    `solve_poly_system`):\n\n    >>> from sympy import sqrt\n    >>> nonlinsolve([x**2 - 2*y**2 -2, x*y - 2], [x, y])\n    {(-2, -1), (2, 1), (-sqrt(2)*I, sqrt(2)*I), (sqrt(2)*I, -sqrt(2)*I)}\n\n    4. `nonlinsolve` can solve some linear(zero or positive dimensional)\n    system (because it is using `groebner` function to get the\n    groebner basis and then `substitution` function basis as the new `system`).\n    But it is not recommended to solve linear system using `nonlinsolve`,\n    because `linsolve` is better for all kind of linear system.\n\n    >>> nonlinsolve([x + 2*y -z - 3, x - y - 4*z + 9 , y + z - 4], [x, y, z])\n    {(3*z - 5, -z + 4, z)}\n\n    5. System having polynomial equations and only real solution is present\n    (will be solved using `solve_poly_system`):\n\n    >>> e1 = sqrt(x**2 + y**2) - 10\n    >>> e2 = sqrt(y**2 + (-x + 10)**2) - 3\n    >>> nonlinsolve((e1, e2), (x, y))\n    {(191/20, -3*sqrt(391)/20), (191/20, 3*sqrt(391)/20)}\n    >>> nonlinsolve([x**2 + 2/y - 2, x + y - 3], [x, y])\n    {(1, 2), (1 + sqrt(5), -sqrt(5) + 2), (-sqrt(5) + 1, 2 + sqrt(5))}\n    >>> nonlinsolve([x**2 + 2/y - 2, x + y - 3], [y, x])\n    {(2, 1), (2 + sqrt(5), -sqrt(5) + 1), (-sqrt(5) + 2, 1 + sqrt(5))}\n\n    6. It is better to use symbols instead of Trigonometric Function or\n    Function (e.g. replace `sin(x)` with symbol, replace `f(x)` with symbol\n    and so on. Get soln from `nonlinsolve` and then using `solveset` get\n    the value of `x`)\n\n    How nonlinsolve is better than old solver `_solve_system` :\n    ===========================================================\n\n    1. A positive dimensional system solver : nonlinsolve can return\n    solution for positive dimensional system. It finds the\n    Groebner Basis of the positive dimensional system(calling it as\n    basis) then we can start solving equation(having least number of\n    variable first in the basis) using solveset and substituting that\n    solved solutions into other equation(of basis) to get solution in\n    terms of minimum variables. Here the important thing is how we\n    are substituting the known values and in which equations.\n\n    2. Real and Complex both solutions : nonlinsolve returns both real\n    and complex solution. If all the equations in the system are polynomial\n    then using `solve_poly_system` both real and complex solution is returned.\n    If all the equations in the system are not polynomial equation then goes to\n    `substitution` method with this polynomial and non polynomial equation(s),\n    to solve for unsolved variables. Here to solve for particular variable\n    solveset_real and solveset_complex is used. For both real and complex\n    solution function `_solve_using_know_values` is used inside `substitution`\n    function.(`substitution` function will be called when there is any non\n    polynomial equation(s) is present). When solution is valid then add its\n    general solution in the final result.\n\n    3. Complement and Intersection will be added if any : nonlinsolve maintains\n    dict for complements and Intersections. If solveset find complements or/and\n    Intersection with any Interval or set during the execution of\n    `substitution` function ,then complement or/and Intersection for that\n    variable is added before returning final solution.\n\n    "
    from sympy.polys.polytools import is_zero_dimensional
    if (not system):
        return S.EmptySet
    if (not symbols):
        msg = 'Symbols must be given, for which solution of the system is to be found.'
        raise ValueError(filldedent(msg))
    if hasattr(symbols[0], '__iter__'):
        symbols = symbols[0]
    try:
        sym = symbols[0].is_Symbol
    except AttributeError:
        sym = False
    except IndexError:
        msg = 'Symbols must be given, for which solution of the system is to be found.'
        raise IndexError(filldedent(msg))
    if (not sym):
        msg = 'Symbols or iterable of symbols must be given as second argument, not type %s: %s'
        raise ValueError(filldedent((msg % (type(symbols[0]), symbols[0]))))
    if ((len(system) == 1) and (len(symbols) == 1)):
        return _solveset_work(system, symbols)
    (polys, polys_expr, nonpolys, denominators) = _separate_poly_nonpoly(system, symbols)
    if (len(symbols) == len(polys)):
        if is_zero_dimensional(polys, symbols):
            try:
                return _handle_zero_dimensional(polys, symbols, system)
            except NotImplementedError:
                result = substitution(polys_expr, symbols, exclude=denominators)
                return result
        return _handle_positive_dimensional(polys, symbols, denominators)
    else:
        result = substitution((polys_expr + nonpolys), symbols, exclude=denominators)
        return result