Repository: sympy/sympy

Issue:
Make settings kwargs explicit in `latex()`
See this comment: https://github.com/sympy/sympy/pull/15040#issuecomment-410574636

The documentation is much clearer and useful if we do:

`def my_func(a, b, c=None, d=True, f='leibowitz')`

versus:

`def my_func(a, b, **kwargs)`

because Sphinx will parse it and when viewing docstrings the kwargs are self documented. Many functions in SymPy could be improved like this. `latex()` is one of them.

Discussion:
sympy-bot: :white_check_mark:

Hi, I am the [SymPy bot](https://github.com/sympy/sympy-bot) (v127). I'm here to make sure this pull request has a release notes entry. Please read the [guide on how to write release notes](https://github.com/sympy/sympy/wiki/Writing-Release-Notes). <details><summary>Click here to see the pull request description that was parsed.</summary>

    Replaced **kwargs in latex function with explicit argument names, for better documentation purpose.

    Fixes #15042 

    <!-- BEGIN RELEASE NOTES -->
    * printing
      * replaced **kwargs with explicit variable name
    <!-- END RELEASE NOTES -->





</details><p>



Your release notes are in good order.

Here is what the release notes will look like:
* printing
  * replaced **kwargs with explicit variable name ([#15080](https://github.com/sympy/sympy/pull/15080) by [@yatna](https://github.com/yatna))

This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.2.1.

Note: This comment will be updated with the latest check if you edit the pull request. You need to reload the page to see it.



Patch:
diff --git a/.travis.yml b/.travis.yml
index 9ab2d5cde0..73ece9ff9d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -249,7 +249,7 @@ before_install:
             conda install matchpy;
         fi
     elif [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then
-        pip list | grep "numpy" && pip uninstall -y numpy;
+        pip list --format=legacy | grep "numpy" && pip uninstall -y numpy;
     fi
 
 install:
@@ -267,9 +267,7 @@ install:
     # The install cycle below is to test installation on systems without setuptools.
       pip uninstall -y setuptools;
       python -We:invalid setup.py install;
-      pip install --upgrade --force-reinstall pip==9.0.3;
       pip uninstall -y sympy;
-      pip install --upgrade pip;
       pip install --upgrade setuptools;
     fi
     python -We:invalid -m compileall -f sympy/;
diff --git a/doc/src/modules/physics/mechanics/autolev_parser.rst b/doc/src/modules/physics/mechanics/autolev_parser.rst
index 252f64e598..3f7edd3e64 100644
--- a/doc/src/modules/physics/mechanics/autolev_parser.rst
+++ b/doc/src/modules/physics/mechanics/autolev_parser.rst
@@ -153,447 +153,3 @@ and manipulations like ``trigsimp()``, ``expand()``, ``evalf()`` etc for
 getting outputs similar to Autolev.
 Refer to the `SymPy Tutorial <http://docs.sympy.org/latest/tutorial/index.html>`_
 to know more about these.
-
-.. _gotchas_autolev:
-
-Gotchas
-=======
-
-- Don't use variable names that conflict with Python's reserved words.
-  This is one example where this is violated:
-
-  .. code-block:: none
-
-     Autolev Code
-     ------------
-     LAMBDA = EIG(M)
-
-  .. code-block:: python
-
-     SymPy Code
-     ----------
-     lambda = sm.Matrix([i.evalf() for i in (m).eigenvals().keys()])
-
-------------------------------------------------------------------------
-
-- Make sure that the names of vectors and scalars are different.
-  Autolev treats these differently but these will get overwritten in Python.
-  The parser currently allows the names of bodies and scalars/vectors to
-  coincide but doesn't do this between scalars and vectors.
-  This should probably be changed in the future.
-
-  .. code-block:: none
-
-     Autolev Code
-     ------------
-     VARIABLES X,Y
-     FRAMES A
-     A> = X*A1> + Y*A2>
-     A = X+Y
-
-  .. code-block:: python
-
-     SymPy Code
-     ----------
-     x, y = me.dynamicsymbols('x y')
-     frame_a = me.ReferenceFrame('a')
-     a = x*frame_a.x + y*frame_a.y
-     a = x + y
-     # Note how frame_a is named differently so it doesn't cause a problem.
-     # On the other hand, 'a' gets rewritten from a scalar to a vector.
-     # This should be changed in the future.
-
-
-------------------------------------------------------------------------
-
-- When dealing with Matrices returned by functions, one must check the
-  order of the values as they may not be the same as in Autolev. This is
-  especially the case for eigenvalues and eigenvetors.
-  
-  .. code-block:: none
-
-     Autolev Code
-     ------------
-     EIG(M, E1, E2)
-     % -> [5; 14; 13]
-     E2ROW = ROWS(E2, 1)
-     EIGVEC> = VECTOR(A, E2ROW)
-
-  .. code-block:: python
-
-     SymPy Code
-     ---------- 
-     e1 = sm.Matrix([i.evalf() for i in m.eigenvals().keys()])
-     # sm.Matrix([5;13;14]) different order
-     e2 = sm.Matrix([i[2][0].evalf() for i in m.eigenvects()]).reshape(m.shape[0], m.shape[1])
-     e2row = e2.row(0)
-     # This result depends on the order of the vectors in the eigenvecs.
-     eigenvec = e2row[0]*a.x + e2row[1]*a.y + e2row[2]*a.y
-
-------------------------------------------------------------------------
-
-- When using ``EVALUATE``, use something like ``90*UNITS(deg,rad)`` for 
-  angle substitutions as radians are the default in SymPy.
-  You could also add ``np.deg2rad()`` directly in the SymPy code.
-  
-  This need not be done for the output code (generated on parsing the
-  ``CODE`` commands) as the parser takes care of this when ``deg`` units
-  are given in the ``INPUT`` declarations. 
-  
-  The ``DEGREES`` setting, on the other hand, works only in some cases like 
-  in ``SIMPROT`` where an angle is expected.
-
-  .. code-block:: none
-
-     Autolev Code
-     ------------
-     A> = Q1*A1> + Q2*A2>
-     B> = EVALUATE(A>, Q1:30*UNITS(DEG,RAD))
-
-  .. code-block:: python
-  
-     SymPy Code
-     ----------
-     a = q1*a.frame_a.x + q2*frame_a.y
-     b = a.subs({q1:30*0.0174533})
-     # b = a.subs({q1:np.deg2rad(30)}
-
-------------------------------------------------------------------------
-
-- Most of the Autolev settings have not been parsed and have no effect on the parser.
-  The only ones that work somewhat are ``COMPLEX`` and ``DEGREES``.
-  It is advised to look into alternatives to these in SymPy and Python.
-
-------------------------------------------------------------------------
-
-- The ``REPRESENT`` command is not supported.
-  Use the ``MATRIX``, ``VECTOR`` or ``DYADIC`` commands instead.
-  Autolev 4.1 suggests these over ``REPRESENT`` as well while still allowing
-  it but the parser doesn't parse it.
-
-------------------------------------------------------------------------
-
-- Do not use variables declarations of the type ``WO{3}RD{2,4}``.
-  The parser can only handle one variable name followed by one pair
-  of curly braces and any number of ``'`` s.
-  You would have to declare all the cases manually if you want to achieve
-  something like ``WO{3}RD{2,4}``.
-
-------------------------------------------------------------------------
-
-- The parser can handle normal versions of most commands but it may not
-  parse functions with Matrix arguments properly in most cases.
-  Eg:
-
-  ``M=COEF([E1;E2],[U1,U2,U3])``
-
-  This would compute the coefficients of ``U1``, ``U2`` and ``U3`` in ``E1``
-  and ``E2``. It is preferable to manually construct a Matrix using the 
-  regular versions of these commands.
-
-  .. code-block:: none
-
-     Autolev Code
-     ------------
-     % COEF([E1;E2],[U1,U2,U3])
-     M = [COEF(E1,U1),COEF(E1,U2),COEF(E1,U3) &
-         ;COEF(E2,U1),COEF(E2,U2),COEF(E2,U3)]    
-
-------------------------------------------------------------------------
-
-- ``MOTIONVARIABLE`` declarations must be used for the generalized coordinates
-  and speeds and all other variables must be declared in regular
-  ``VARIABLE`` declarations.
-  The parser requires this to distinguish between them to pass the correct
-  parameters to the Kane's method object.
-  
-  It is also preferred to always declare the speeds corresponding to the
-  coordinates and to pass in the kinematic differential equations.
-  The parser is able to handle some cases where this isn't the case by
-  introducing some dummy variables of its own but SymPy on its own
-  does require them.
-  
-  Also note that older Autolev declarations like ``VARIABLES U{3}'`` are not
-  supported either.
-
-  .. code-block:: none
-
-     Autolev Code
-     ------------
-     MOTIONVARIABLES' Q{2}', U{2}'
-     % ----- OTHER LINES ----
-     Q1' = U1
-     Q2' = U2
-     ----- OTHER LINES ----
-     ZERO = FR() + FRSTAR()
-
-  .. code-block:: python
-
-     SymPy Code
-     ----------
-     q1, q2, u1, u2 = me.dynamicsymbols('q1 q2 u1 u2')
-     q1d, q2d, u1d, u2d = me.dynamicsymbols('q1 q2 u1 u2', 1)
-     
-     # ------- other lines -------
-     
-     kd_eqs = [q1d - u1, q2d - u2]
-     kane = me.KanesMethod(frame_n, q_ind=[q1,q2], u_ind=[u1, u2], kd_eqs = kd_eqs)
-     fr, frstar = kane.kanes_equations([particle_p, particle_r], forceList)
-     zero = fr+frstar
-
-------------------------------------------------------------------------
-
-- Need to change ``me.dynamicsymbols._t`` to ``me.dynamicsymbols('t')`` for
-  all occurences of it in the Kane's equations. For example have a look at
-  line 10 of this `spring damper example <https://github.com/sympy/sympy/blob/master/sympy/parsing/autolev/test_examples/mass_spring_damper.py>`_.
-  This equation is used in forming the Kane's equations so we need to
-  change ``me.dynamicsymbols._t`` to ``me.dynamicsymbols('t')`` in this case.
-  
-  The main reason that this needs to be done is because PyDy
-  requires time dependent specifieds to be explicitly laid out while
-  Autolev simply takes care of the stray time variables in the equations
-  by itself.
-  
-  The problem is that PyDy's System class does not accept
-  ``dynamicsymbols._t`` as a specified. 
-  This change is not actually ideal so a better solution should be figured
-  out in the future.
-
-------------------------------------------------------------------------
-
-- The parser creates SymPy ``symbols`` and ``dynamicsymbols`` by parsing
-  variable declarations in the Autolev Code.
-  
-  For intermediate expressions which are directly initialized the parser
-  does not create SymPy symbols. It just assigns them to the expression.
-  
-  On the other hand, when a declared variable is assigned to an expression,
-  the parser stores the expression against the variable in a dictionary so 
-  as to not reassign it to a completely different entity. This constraint 
-  is due to the inherent nature of Python and how it differs from a language
-  like Autolev.
-  
-  Also, Autolev seems to be able to assume whether to use a variable or the
-  rhs expression that variable has been assigned to in equations even
-  without an explicit ``RHS()`` call in some cases.
-  For the parser to work correctly however, it is better to use ``RHS()``
-  wherever a variable's rhs expression is meant to be used.
-
-  .. code-block:: none
-
-     Autolev Code
-     ------------
-     VARIABLES X, Y
-     E = X + Y
-     X = 2*Y
-     
-     RHS_X = RHS(X)
-     
-     I1 = X
-     I2 = Y
-     I3 = X + Y
-     
-     INERTIA B,I1,I2,I3
-     % -> I_B_BO>> = I1*B1>*B1> + I2*B2>*B2> + I3*B3>*B3>
-
-  .. code-block:: python
-
-     SymPy Code
-     ----------
-     x,y = me.dynamicsymbols('x y')
-     e = x + y  # No symbol is made out of 'e'
-     
-     # an entry like {x:2*y} is stored in an rhs dictionary
-     
-     rhs_x = 2*y
-     
-     i1 = x  # again these are not made into SymPy symbols
-     i2 = y
-     i3 = x + y
-     
-     body_b.inertia = (me.inertia(body_b_f, i1, i2, i3), b_cm)
-     # This prints as:
-     # x*b_f.x*b_f.x + y*b_f.y*b_f.y + (x+y)*b_f.z*b_f.z
-     # while Autolev's output has I1,I2 and I3 in it.
-     # Autolev however seems to know when to use the RHS of I1,I2 and I3
-     # based on the context.
-  
-------------------------------------------------------------------------
-
-- This is how the ``SOLVE`` command is parsed:
-
-  .. code-block:: none
-
-     Autolev Code
-     ------------
-     SOLVE(ZERO,X,Y)
-     A = RHS(X)*2 + RHS(Y)
-
-  .. code-block:: python
-
-     SymPy Code
-     ----------
-     print(sm.solve(zero,x,y))
-     # Behind the scenes the rhs of x
-     # is set to sm.solve(zero,x,y)[x].
-     a = sm.solve(zero,x,y)[x]*2 + sm.solve(zero,x,y)[y]
-     
-  The indexing like ``[x]`` and ``[y]`` doesn't always work so you might want to
-  look at the underlying dictionary that solve returns and index it correctly.
-  
-------------------------------------------------------------------------
-
-- Inertia declarations and Inertia functions work somewhat differently in
-  the context of the parser. This might be hard to understand at first
-  but this had to be done to bridge the gap due to the differences in
-  SymPy and Autolev. Here are some points about them:
-
-  1. Inertia declarations (``INERTIA B,I1,I2,I3``) set the inertias of rigid
-  bodies.
-  
-  2. Inertia setters of the form ``I_C_D>> = expr`` however, set the inertias
-  only when C is a body. If C is a particle then ``I_C_D>> = expr``
-  simply parses to ``i_c_d = expr`` and ``i_c_d`` acts like a regular variable.
-  
-  3. When it comes to inertia getters (``I_C_D>>`` used in an expression or
-  ``INERTIA`` commands), these MUST be used with the ``EXPRESS`` command
-  to specify the frame as SymPy needs this information to compute the
-  inertia dyadic.
-
-  .. code-block:: none
-
-     Autolev Code
-     ------------
-     INERTIA B,I1,I2,I3
-     I_B_BO>> = X*A1>*A1> + Y*A2>*A2>  % Parser will set the inertia of B
-     I_P_Q>> = X*A1>*A1> + Y^2*A2>*A2> % Parser just parses it as i_p_q = expr
-     
-     E1 = 2*EXPRESS(I_B_O>>,A)
-     E2 =  I_P_Q>>
-     E3 = EXPRESS(I_P_O>>,A)
-     E4 = EXPRESS(INERTIA(O),A)
-     
-     % In E1 we are using the EXPRESS command with I_B_O>> which makes
-     % the parser and SymPy compute the inertia of Body B about point O.
-     
-     % In E2 we are just using the dyadic object I_P_Q>> (as I_P_Q>> = expr
-     % doesn't act as a setter) defined above and not asking the parser 
-     % or SymPy to compute anything.
-     
-     % E3 asks the parser to compute the inertia of P about point O.
-     
-     % E4 asks the parser to compute the inertias of all bodies wrt about O.
-
-------------------------------------------------------------------------
-
-- In an inertia declaration of a body, if the inertia is being set about
-  a point other than the center of mass, one needs to make sure that
-  the position vector setter for that point and the center of mass appears
-  before the inertia declaration as SymPy will throw an error otherwise.
-
-  .. code-block:: none
-
-     Autolev Code
-     ------------
-     P_SO_O> = X*A1>
-     INERTIA S_(O) I1,I2,I3
-
-------------------------------------------------------------------------
-
-- Note that all Autolev commands have not been implemented. The parser
-  now covers the important ones in their basic forms. If you are doubtful
-  whether a command is included or not, please have a look at `this file <https://github.com/sympy/sympy/blob/master/sympy/parsing/autolev/_listener_autolev_antlr.py>`_
-  in the source code. Search for "<command>" to verify this. Looking at the
-  code for the specific command will also give an idea about what form it
-  is expected to work in.
-
-.. _issues:
-
-Limitations and Issues
-======================
-
-- A lot of the issues have already been discussed in the Gotchas section.
-  Some of these are:
-
-  - Vector names coinciding with scalar names are overwritten in Python.
-  - Some convenient variable declarations aren't parsed.
-  - Some convenient forms of functions to return matrices aren't parsed.
-  - Settings aren't parsed.
-  - symbols and rhs expressions work very differently in Python which might
-    cause undesirable results.
-  - Dictionary indexing for the parsed code of the ``SOLVE`` command is 
-    not proper in many cases.
-  - Need to change ``dynamicsymbols._t`` to ``dynamicsymbols('t')`` for the
-    PyDy simulation code to work properly.
-
-Here are some other ones:
-
-- Eigenvectors do not seem to work as expected. The values in Autolev and SymPy
-  are not the same in many cases.
-
-- Block matrices aren't parsed by the parser. It would actually be easier
-  to make a change in SymPy to allow matrices to accept other matrices for
-  arguments.
-
-- The SymPy equivalent of the ``TAYLOR`` command ``.series()`` does not work
-  with ``dynamicsymbols()``.
-
-- Only ``DEPENDENT`` constraints are currently parsed. Need to parse
-  ``AUXILIARY`` constraints as well. This should be done soon as it isn't
-  very difficult.
-
-- None of the energy and momentum functions are parsed right now. It would
-  be nice to get these working as well. Some changes should probably be made
-  to SymPy. For instance, SymPy doesn't have a function equivalent to ``NICHECK()``.
-
-- The numerical integration parts work properly only in the case of the
-  ``KANE`` command with no arguments. Things like ``KANE(F1,F2)`` do not currently
-  work.
-
-- Also, the PyDy numerical simulation code works only for cases where the
-  matrix say ``ZERO = FR() + FRSTAR()`` is solved for. It doesn't work well when the
-  matrix has some other equations plugged in as well. One hurdle
-  faced in achieving this was that PyDy's System class automatically takes
-  in the ``forcing_full`` and ``mass_matrix_full`` and solves them without giving the
-  user the flexibility to specify the equations. It would be nice to add
-  this functionality to the System class.
-
-
-.. _future_improvements:
-
-Future Improvements
-===================
-
-1. Completing Dynamics Online
------------------------------
-The parser has been built by referring to and parsing codes from the
-`Autolev Tutorial <http://web.mae.ufl.edu/~fregly/PDFs/autolev_tutorial.pdf>`_
-and the book *Dynamics Online: Theory and Implementation Using Autolev*.
-Basically, the process involved going through each of these codes,
-validating the parser results and improving the rules if required
-to make sure the codes parsed well.
-
-The parsed codes of these are available on GitLab `here <https://gitlab.com/sympy/autolev-test-examples>`_.
-The repo is private so access needs to be requested.
-As of now, most codes till Chapter 4 of *Dynamics Online* have been parsed. 
-
-Completing all the remaining codes of the book (namely, *2-10*, *2-11*, *rest
-of Ch4*, *Ch5* and *Ch6* (less important) ) would make the parser more complete.
-
-
-2. Fixing Issues
-----------------
-The second thing to do would be to go about fixing the problems described 
-above in the :ref:`Gotchas <gotchas_autolev>` and :ref:`Limitations and Issues <issues>` 
-sections in order of priority and ease. Many of these require changes
-in the parser code while some of these are better fixed by adding some
-functionality to SymPy.
-
-
-3. Switching to an AST
-----------------------
-The parser is currently built using a kind of Concrete Syntax Tree (CST) 
-using the `ANTLR <http://www.antlr.org/>`_ framework. It would be ideal to switch from a CST to an
-Abstract Syntax Tree (AST). This way, the parser code will be independent
-of the ANTLR grammar which makes it a lot more flexible. It would also be
-easier to make changes to the grammar and the rules of the parser.
diff --git a/sympy/functions/elementary/piecewise.py b/sympy/functions/elementary/piecewise.py
index d46ab050da..6c9230c6d5 100644
--- a/sympy/functions/elementary/piecewise.py
+++ b/sympy/functions/elementary/piecewise.py
@@ -71,7 +71,7 @@ class Piecewise(Function):
           If any of the evaluated conds are not determined explicitly False,
           e.g. x < 1, the function is returned in symbolic form.
         - If the function is evaluated at a place where all conditions are False,
-          nan will be returned.
+          a ValueError exception will be raised.
         - Pairs where the cond is explicitly False, will be removed.
 
     Examples
@@ -120,8 +120,6 @@ class Piecewise(Function):
     is_Piecewise = True
 
     def __new__(cls, *args, **options):
-        if len(args) == 0:
-            raise TypeError("At least one (expr, cond) pair expected.")
         # (Try to) sympify args first
         newargs = []
         for ec in args:
@@ -155,13 +153,13 @@ def eval(cls, *_args):
         3) any repeat of a previous condition is ignored
         3) any args past one with a true condition are dropped
 
-        If there are no args left, nan will be returned.
+        If there are no args left, an empty Piecewise will be returned.
         If there is a single arg with a True condition, its
         corresponding expression will be returned.
         """
 
         if not _args:
-            return Undefined
+            return
 
         if len(_args) == 1 and _args[0][-1] == True:
             return _args[0][0]
@@ -799,17 +797,13 @@ def _eval_subs(self, old, new):
         # and avoiding invalid conditions that appear after a
         # True condition
         args = list(self.args)
-        args_exist = False
         for i, (e, c) in enumerate(args):
             c = c._subs(old, new)
             if c != False:
-                args_exist = True
                 e = e._subs(old, new)
             args[i] = (e, c)
             if c == True:
                 break
-        if not args_exist:
-            args = ((Undefined, True),)
         return self.func(*args)
 
     def _eval_transpose(self):
diff --git a/sympy/physics/continuum_mechanics/beam.py b/sympy/physics/continuum_mechanics/beam.py
index 01aef6d4da..47363580aa 100644
--- a/sympy/physics/continuum_mechanics/beam.py
+++ b/sympy/physics/continuum_mechanics/beam.py
@@ -12,9 +12,6 @@
 from sympy.core import sympify
 from sympy.integrals import integrate
 from sympy.series import limit
-from sympy.plotting import plot
-from sympy.external import import_module
-from sympy.utilities.decorator import doctest_depends_on
 
 
 class Beam(object):
@@ -1128,297 +1125,6 @@ def max_deflection(self):
         else:
             return None
 
-    def plot_shear_force(self, subs=None):
-        """
-        Returns a plot for Shear force present in the Beam object.
-
-        Parameters
-        ==========
-        subs : dictionary
-            Python dictionary containing Symbols as key and their
-            corresponding values.
-
-        Examples
-        ========
-        There is a beam of length 8 meters. A constant distributed load of 10 KN/m
-        is applied from half of the beam till the end. There are two simple supports
-        below the beam, one at the starting point and another at the ending point
-        of the beam. A pointload of magnitude 5 KN is also applied from top of the
-        beam, at a distance of 4 meters from the starting point.
-        Take E = 200 GPa and I = 400*(10**-6) meter**4.
-
-        Using the sign convention of downwards forces being positive.
-
-        >>> from sympy.physics.continuum_mechanics.beam import Beam
-        >>> from sympy import symbols
-        >>> R1, R2 = symbols('R1, R2')
-        >>> b = Beam(8, 200*(10**9), 400*(10**-6))
-        >>> b.apply_load(5000, 2, -1)
-        >>> b.apply_load(R1, 0, -1)
-        >>> b.apply_load(R2, 8, -1)
-        >>> b.apply_load(10000, 4, 0, end=8)
-        >>> b.bc_deflection = [(0, 0), (8, 0)]
-        >>> b.solve_for_reaction_loads(R1, R2)
-        >>> b.plot_shear_force()
-        Plot object containing:
-        [0]: cartesian line: -13750*SingularityFunction(x, 0, 0) + 5000*SingularityFunction(x, 2, 0)
-        + 10000*SingularityFunction(x, 4, 1) - 31250*SingularityFunction(x, 8, 0)
-        - 10000*SingularityFunction(x, 8, 1) for x over (0.0, 8.0)
-        """
-        shear_force = self.shear_force()
-        if subs is None:
-            subs = {}
-        for sym in shear_force.atoms(Symbol):
-            if sym == self.variable:
-                continue
-            if sym not in subs:
-                raise ValueError('Value of %s was not passed.' %sym)
-        if self.length in subs:
-            length = subs[self.length]
-        else:
-            length = self.length
-        return plot(shear_force.subs(subs), (self.variable, 0, length), title='Shear Force',
-                xlabel='position', ylabel='Value', line_color='g')
-
-    def plot_bending_moment(self, subs=None):
-        """
-        Returns a plot for Bending moment present in the Beam object.
-
-        Parameters
-        ==========
-        subs : dictionary
-            Python dictionary containing Symbols as key and their
-            corresponding values.
-
-        Examples
-        ========
-        There is a beam of length 8 meters. A constant distributed load of 10 KN/m
-        is applied from half of the beam till the end. There are two simple supports
-        below the beam, one at the starting point and another at the ending point
-        of the beam. A pointload of magnitude 5 KN is also applied from top of the
-        beam, at a distance of 4 meters from the starting point.
-        Take E = 200 GPa and I = 400*(10**-6) meter**4.
-
-        Using the sign convention of downwards forces being positive.
-
-        >>> from sympy.physics.continuum_mechanics.beam import Beam
-        >>> from sympy import symbols
-        >>> R1, R2 = symbols('R1, R2')
-        >>> b = Beam(8, 200*(10**9), 400*(10**-6))
-        >>> b.apply_load(5000, 2, -1)
-        >>> b.apply_load(R1, 0, -1)
-        >>> b.apply_load(R2, 8, -1)
-        >>> b.apply_load(10000, 4, 0, end=8)
-        >>> b.bc_deflection = [(0, 0), (8, 0)]
-        >>> b.solve_for_reaction_loads(R1, R2)
-        >>> b.plot_bending_moment()
-        Plot object containing:
-        [0]: cartesian line: -13750*SingularityFunction(x, 0, 1) + 5000*SingularityFunction(x, 2, 1)
-        + 5000*SingularityFunction(x, 4, 2) - 31250*SingularityFunction(x, 8, 1)
-        - 5000*SingularityFunction(x, 8, 2) for x over (0.0, 8.0)
-        """
-        bending_moment = self.bending_moment()
-        if subs is None:
-            subs = {}
-        for sym in bending_moment.atoms(Symbol):
-            if sym == self.variable:
-                continue
-            if sym not in subs:
-                raise ValueError('Value of %s was not passed.' %sym)
-        if self.length in subs:
-            length = subs[self.length]
-        else:
-            length = self.length
-        return plot(bending_moment.subs(subs), (self.variable, 0, length), title='Bending Moment',
-                xlabel='position', ylabel='Value', line_color='b')
-
-    def plot_slope(self, subs=None):
-        """
-        Returns a plot for slope of deflection curve of the Beam object.
-
-        Parameters
-        ==========
-        subs : dictionary
-            Python dictionary containing Symbols as key and their
-            corresponding values.
-
-        Examples
-        ========
-        There is a beam of length 8 meters. A constant distributed load of 10 KN/m
-        is applied from half of the beam till the end. There are two simple supports
-        below the beam, one at the starting point and another at the ending point
-        of the beam. A pointload of magnitude 5 KN is also applied from top of the
-        beam, at a distance of 4 meters from the starting point.
-        Take E = 200 GPa and I = 400*(10**-6) meter**4.
-
-        Using the sign convention of downwards forces being positive.
-
-        >>> from sympy.physics.continuum_mechanics.beam import Beam
-        >>> from sympy import symbols
-        >>> R1, R2 = symbols('R1, R2')
-        >>> b = Beam(8, 200*(10**9), 400*(10**-6))
-        >>> b.apply_load(5000, 2, -1)
-        >>> b.apply_load(R1, 0, -1)
-        >>> b.apply_load(R2, 8, -1)
-        >>> b.apply_load(10000, 4, 0, end=8)
-        >>> b.bc_deflection = [(0, 0), (8, 0)]
-        >>> b.solve_for_reaction_loads(R1, R2)
-        >>> b.plot_slope()
-        Plot object containing:
-        [0]: cartesian line: -8.59375e-5*SingularityFunction(x, 0, 2) + 3.125e-5*SingularityFunction(x, 2, 2)
-        + 2.08333333333333e-5*SingularityFunction(x, 4, 3) - 0.0001953125*SingularityFunction(x, 8, 2)
-        - 2.08333333333333e-5*SingularityFunction(x, 8, 3) + 0.00138541666666667 for x over (0.0, 8.0)
-        """
-        slope = self.slope()
-        if subs is None:
-            subs = {}
-        for sym in slope.atoms(Symbol):
-            if sym == self.variable:
-                continue
-            if sym not in subs:
-                raise ValueError('Value of %s was not passed.' %sym)
-        if self.length in subs:
-            length = subs[self.length]
-        else:
-            length = self.length
-        return plot(slope.subs(subs), (self.variable, 0, length), title='Slope',
-                xlabel='position', ylabel='Value', line_color='m')
-
-    def plot_deflection(self, subs=None):
-        """
-        Returns a plot for deflection curve of the Beam object.
-
-        Parameters
-        ==========
-        subs : dictionary
-            Python dictionary containing Symbols as key and their
-            corresponding values.
-
-        Examples
-        ========
-        There is a beam of length 8 meters. A constant distributed load of 10 KN/m
-        is applied from half of the beam till the end. There are two simple supports
-        below the beam, one at the starting point and another at the ending point
-        of the beam. A pointload of magnitude 5 KN is also applied from top of the
-        beam, at a distance of 4 meters from the starting point.
-        Take E = 200 GPa and I = 400*(10**-6) meter**4.
-
-        Using the sign convention of downwards forces being positive.
-
-        >>> from sympy.physics.continuum_mechanics.beam import Beam
-        >>> from sympy import symbols
-        >>> R1, R2 = symbols('R1, R2')
-        >>> b = Beam(8, 200*(10**9), 400*(10**-6))
-        >>> b.apply_load(5000, 2, -1)
-        >>> b.apply_load(R1, 0, -1)
-        >>> b.apply_load(R2, 8, -1)
-        >>> b.apply_load(10000, 4, 0, end=8)
-        >>> b.bc_deflection = [(0, 0), (8, 0)]
-        >>> b.solve_for_reaction_loads(R1, R2)
-        >>> b.plot_deflection()
-        Plot object containing:
-        [0]: cartesian line: 0.00138541666666667*x - 2.86458333333333e-5*SingularityFunction(x, 0, 3)
-        + 1.04166666666667e-5*SingularityFunction(x, 2, 3) + 5.20833333333333e-6*SingularityFunction(x, 4, 4)
-        - 6.51041666666667e-5*SingularityFunction(x, 8, 3) - 5.20833333333333e-6*SingularityFunction(x, 8, 4)
-        for x over (0.0, 8.0)
-        """
-        deflection = self.deflection()
-        if subs is None:
-            subs = {}
-        for sym in deflection.atoms(Symbol):
-            if sym == self.variable:
-                continue
-            if sym not in subs:
-                raise ValueError('Value of %s was not passed.' %sym)
-        if self.length in subs:
-            length = subs[self.length]
-        else:
-            length = self.length
-        return plot(deflection.subs(subs), (self.variable, 0, length), title='Deflection',
-                xlabel='position', ylabel='Value', line_color='r')
-
-    @doctest_depends_on(modules=('numpy', 'matplotlib',))
-    def plot_loading_results(self, subs=None):
-        """
-        Returns Axes object containing subplots of Shear Force, Bending Moment,
-        Slope and Deflection of the Beam object.
-
-        Parameters
-        ==========
-        subs : dictionary
-            Python dictionary containing Symbols as key and their
-            corresponding values.
-
-        .. note::
-           This method only works if numpy and matplotlib libraries
-           are installed on the system.
-
-        Examples
-        ========
-        There is a beam of length 8 meters. A constant distributed load of 10 KN/m
-        is applied from half of the beam till the end. There are two simple supports
-        below the beam, one at the starting point and another at the ending point
-        of the beam. A pointload of magnitude 5 KN is also applied from top of the
-        beam, at a distance of 4 meters from the starting point.
-        Take E = 200 GPa and I = 400*(10**-6) meter**4.
-
-        Using the sign convention of downwards forces being positive.
-
-        >>> from sympy.physics.continuum_mechanics.beam import Beam
-        >>> from sympy import symbols
-        >>> R1, R2 = symbols('R1, R2')
-        >>> b = Beam(8, 200*(10**9), 400*(10**-6))
-        >>> b.apply_load(5000, 2, -1)
-        >>> b.apply_load(R1, 0, -1)
-        >>> b.apply_load(R2, 8, -1)
-        >>> b.apply_load(10000, 4, 0, end=8)
-        >>> b.bc_deflection = [(0, 0), (8, 0)]
-        >>> b.solve_for_reaction_loads(R1, R2)
-        >>> axes = b.plot_loading_results()
-        """
-        from sympy import lambdify
-        matplotlib = import_module('matplotlib', __import__kwargs={'fromlist':['pyplot']})
-        plt = matplotlib.pyplot
-        numpy = import_module('numpy', __import__kwargs={'fromlist':['linspace']})
-        linspace = numpy.linspace
-
-        length = self.length
-        variable = self.variable
-        if subs is None:
-            subs = {}
-        for sym in self.deflection().atoms(Symbol):
-            if sym == self.variable:
-                continue
-            if sym not in subs:
-                raise ValueError('Value of %s was not passed.' %sym)
-        if self.length in subs:
-            length = subs[self.length]
-        else:
-            length = self.length
-
-        # As we are using matplotlib directly in this method, we need to change SymPy methods
-        # to numpy functions.
-        shear = lambdify(variable, self.shear_force().subs(subs).rewrite(Piecewise), 'numpy')
-        moment = lambdify(variable, self.bending_moment().subs(subs).rewrite(Piecewise), 'numpy')
-        slope = lambdify(variable, self.slope().subs(subs).rewrite(Piecewise), 'numpy')
-        deflection = lambdify(variable, self.deflection().subs(subs).rewrite(Piecewise), 'numpy')
-
-        points = linspace(0, float(length), num=5*length)
-
-        # Creating a grid for subplots with 2 rows and 2 columns
-        fig, axs = plt.subplots(4, 1)
-        # axs is a 2D-numpy array containing axes
-        axs[0].plot(points, shear(points))
-        axs[0].set_title("Shear Force")
-        axs[1].plot(points, moment(points))
-        axs[1].set_title("Bending Moment")
-        axs[2].plot(points, slope(points))
-        axs[2].set_title("Slope")
-        axs[3].plot(points, deflection(points))
-        axs[3].set_title("Deflection")
-
-        fig.tight_layout()    # For better spacing between subplots
-        return axs
 
 
 class Beam_3d(Beam):
diff --git a/sympy/printing/latex.py b/sympy/printing/latex.py
index 2c3e1979c6..6a4acd9d3b 100644
--- a/sympy/printing/latex.py
+++ b/sympy/printing/latex.py
@@ -2199,7 +2199,11 @@ def translate(s):
         return s
 
 
-def latex(expr, **settings):
+def latex(expr, fold_frac_powers=False, fold_func_brackets=False,
+    fold_short_frac=None, inv_trig_style="abbreviated",
+    itex=False, ln_notation=False, long_frac_ratio=None,
+    mat_delim="[", mat_str=None, mode="plain", mul_symbol=None,
+    order=None, symbol_names=None):
     r"""Convert the given expression to LaTeX string representation.
 
     Parameters
@@ -2359,6 +2363,24 @@ def latex(expr, **settings):
     $\left [ 2 / x, \quad y\right ]$
 
     """
+    if symbol_names is None:
+        symbol_names = {}
+
+    settings = {
+        'fold_frac_powers' : fold_frac_powers,
+        'fold_func_brackets' : fold_func_brackets,
+        'fold_short_frac' : fold_short_frac,
+        'inv_trig_style' : inv_trig_style,
+        'itex' : itex,
+        'ln_notation' : ln_notation,
+        'long_frac_ratio' : long_frac_ratio,
+        'mat_delim' : mat_delim,
+        'mat_str' : mat_str,
+        'mode' : mode,
+        'mul_symbol' : mul_symbol,
+        'order' : order,
+        'symbol_names' : symbol_names,
+    }
 
     return LatexPrinter(settings).doprint(expr)
 
diff --git a/sympy/solvers/solveset.py b/sympy/solvers/solveset.py
index c0a243b3d9..5ac6781a0f 100644
--- a/sympy/solvers/solveset.py
+++ b/sympy/solvers/solveset.py
@@ -246,15 +246,10 @@ def _invert_real(f, g_ys, symbol):
                 s, b = integer_log(rhs, base)
                 if b:
                     return _invert_real(expo, FiniteSet(s), symbol)
-                else:
-                    return _invert_real(expo, S.EmptySet, symbol)
-            elif base.is_zero:
-                one = Eq(rhs, 1)
-                if one == S.true:
-                    # special case: 0**x - 1
-                    return _invert_real(expo, FiniteSet(0), symbol)
-                elif one == S.false:
-                    return _invert_real(expo, S.EmptySet, symbol)
+            elif rhs is S.One:
+                # special case: 0**x - 1
+                return (expo, FiniteSet(0))
+            return (expo, S.EmptySet)
 
 
     if isinstance(f, TrigonometricFunction):
@@ -1128,8 +1123,8 @@ def _solve_exponential(lhs, rhs, symbol, domain):
             Ne(a_base, 0),
             Ne(b_base, 0))
 
-    L, R = map(lambda i: expand_log(log(i), force=True), (a, -b))
-    solutions = _solveset(L - R, symbol, domain)
+    log_type_equation = expand_log(log(a), force=True) - expand_log(log(-b), force=True)
+    solutions = _solveset(log_type_equation, symbol, domain)
 
     return ConditionSet(symbol, conditions, solutions)
 
diff --git a/sympy/stats/joint_rv.py b/sympy/stats/joint_rv.py
index 25e898a0cc..b6884cee44 100644
--- a/sympy/stats/joint_rv.py
+++ b/sympy/stats/joint_rv.py
@@ -23,7 +23,6 @@
     SingleContinuousDistribution, SingleContinuousPSpace)
 from sympy.stats.drv import (DiscreteDistribution,
     SingleDiscreteDistribution, SingleDiscretePSpace)
-from sympy.core.compatibility import string_types
 from sympy.matrices import ImmutableMatrix
 from sympy.core.containers import Tuple
 from sympy.utilities.misc import filldedent
@@ -35,14 +34,11 @@ class JointPSpace(ProductPSpace):
     each component and a distribution.
     """
     def __new__(cls, sym, dist):
+        sym = sympify(sym)
         if isinstance(dist, SingleContinuousDistribution):
             return SingleContinuousPSpace(sym, dist)
         if isinstance(dist, SingleDiscreteDistribution):
             return SingleDiscretePSpace(sym, dist)
-        if isinstance(sym, string_types):
-            sym = Symbol(sym)
-        if not isinstance(sym, Symbol):
-            raise TypeError("s should have been string or Symbol")
         return Basic.__new__(cls, sym, dist)
 
     @property
@@ -105,25 +101,6 @@ def marginal_distribution(self, *indices):
             f = Lambda(sym, summation(self.distribution(all_syms), limits))
         return f.xreplace(replace_dict)
 
-    def integrate(self, expr, rvs=None, evaluate=False, **kwargs):
-        syms = tuple(self.value[i] for i in range(self.component_count))
-        rvs = rvs or syms
-        if not any([i in rvs for i in syms]):
-            return expr
-        expr = expr*self.pdf
-        for rv in rvs:
-            if isinstance(rv, Indexed):
-                expr = expr.xreplace({rv: Indexed(str(rv.base), rv.args[1])})
-            elif isinstance(rv, RandomSymbol):
-                expr = expr.xreplace({rv: rv.symbol})
-        if self.value in random_symbols(expr):
-            raise NotImplementedError(filldedent('''
-            Expectations of expression with unindexed joint random symbols
-            cannot be calculated yet.'''))
-        limits = tuple((Indexed(str(rv.base),rv.args[1]),
-            self.distribution.set.args[rv.args[1]]) for rv in syms)
-        return Integral(expr, *limits)
-
     def where(self, condition):
         raise NotImplementedError()
 
@@ -184,9 +161,6 @@ class JointRandomSymbol(RandomSymbol):
     def __getitem__(self, key):
         from sympy.stats.joint_rv import JointPSpace
         if isinstance(self.pspace, JointPSpace):
-            if self.pspace.component_count <= key:
-                raise ValueError("Index keys for %s can only up to %s." %
-                    (self.name, self.pspace.component_count - 1))
             return Indexed(self, key)
 
 class JointDistributionHandmade(JointDistribution, NamedArgsMixin):
diff --git a/sympy/stats/joint_rv_types.py b/sympy/stats/joint_rv_types.py
index 490a4cc729..d1e1b7fd18 100644
--- a/sympy/stats/joint_rv_types.py
+++ b/sympy/stats/joint_rv_types.py
@@ -13,6 +13,7 @@
 # ]
 
 def multivariate_rv(cls, sym, *args):
+    sym = sympify(sym)
     args = list(map(sympify, args))
     dist = cls(*args)
     args = dist.args


Test patch:
diff --git a/sympy/functions/elementary/tests/test_piecewise.py b/sympy/functions/elementary/tests/test_piecewise.py
index c49adace2e..07f2bdf659 100644
--- a/sympy/functions/elementary/tests/test_piecewise.py
+++ b/sympy/functions/elementary/tests/test_piecewise.py
@@ -30,13 +30,9 @@ def test_piecewise():
         Piecewise((x, Or(x < 1, x < 2)), (0, True))
     assert Piecewise((x, x < 1), (x, x < 2), (x, True)) == x
     assert Piecewise((x, True)) == x
-    # Explicitly constructed empty Piecewise not accepted
-    raises(TypeError, lambda: Piecewise())
     # False condition is never retained
-    assert Piecewise((2*x, x < 0), (x, False)) == \
-        Piecewise((2*x, x < 0), (x, False), evaluate=False) == \
-        Piecewise((2*x, x < 0))
-    assert Piecewise((x, False)) == Undefined
+    assert Piecewise((x, False)) == Piecewise(
+        (x, False), evaluate=False) == Piecewise()
     raises(TypeError, lambda: Piecewise(x))
     assert Piecewise((x, 1)) == x  # 1 and 0 are accepted as True/False
     raises(TypeError, lambda: Piecewise((x, 2)))
@@ -88,16 +84,11 @@ def test_piecewise():
         ).subs(x, 1) == Piecewise((-1, y < 1), (2, True))
     assert Piecewise((1, Eq(x**2, -1)), (2, x < 0)).subs(x, I) == 1
 
-    p6 = Piecewise((x, x > 0))
-    n = symbols('n', negative=True)
-    assert p6.subs(x, n) == Undefined
-
     # Test evalf
     assert p.evalf() == p
     assert p.evalf(subs={x: -2}) == -1
     assert p.evalf(subs={x: -1}) == 1
     assert p.evalf(subs={x: 1}) == log(1)
-    assert p6.evalf(subs={x: -5}) == Undefined
 
     # Test doit
     f_int = Piecewise((Integral(x, (x, 0, 1)), x < 1))
diff --git a/sympy/solvers/tests/test_solveset.py b/sympy/solvers/tests/test_solveset.py
index 3785645add..2b37104a79 100644
--- a/sympy/solvers/tests/test_solveset.py
+++ b/sympy/solvers/tests/test_solveset.py
@@ -962,9 +962,6 @@ def test_conditionset():
     assert solveset(Eq(sin(Abs(x)), x), x, domain=S.Reals
         ) == ConditionSet(x, Eq(-x + sin(Abs(x)), 0), S.Reals)
 
-    assert solveset(y**x-z, x, S.Reals) == \
-        ConditionSet(x, Eq(y**x - z, 0), S.Reals)
-
 
 @XFAIL
 def test_conditionset_equality():
@@ -1960,9 +1957,7 @@ def test_is_logarithmic():
 
 
 def test_solve_logarithm():
-    y = Symbol('y')
     assert _solve_logarithm(log(x**y) - y*log(x), 0, x, S.Reals) == S.Reals
-    y = Symbol('y', positive=True)
     assert _solve_logarithm(log(x)*log(y), 0, x, S.Reals) == FiniteSet(1)
 
 # end of logarithmic tests
diff --git a/sympy/stats/tests/test_joint_rv.py b/sympy/stats/tests/test_joint_rv.py
index d4b1cb2977..0af7b30b4f 100644
--- a/sympy/stats/tests/test_joint_rv.py
+++ b/sympy/stats/tests/test_joint_rv.py
@@ -3,7 +3,7 @@
 from sympy.stats.joint_rv import marginal_distribution
 from sympy.stats.joint_rv_types import JointRV
 from sympy.stats.crv_types import Normal
-from sympy.utilities.pytest import raises, XFAIL
+from sympy.utilities.pytest import raises
 from sympy.integrals.integrals import integrate
 from sympy.matrices import Matrix
 x, y, z, a, b = symbols('x y z a b')
@@ -11,7 +11,6 @@
 def test_Normal():
     m = Normal('A', [1, 2], [[1, 0], [0, 1]])
     assert density(m)(1, 2) == 1/(2*pi)
-    raises (ValueError, lambda:m[2])
     raises (ValueError,\
         lambda: Normal('M',[1, 2], [[0, 0], [0, 1]]))
     n = Normal('B', [1, 2, 3], [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
@@ -19,8 +18,8 @@ def test_Normal():
     assert density(m)(x, y) == density(p)(x, y)
     assert marginal_distribution(n, 0, 1)(1, 2) == 1/(2*pi)
     assert integrate(density(m)(x, y), (x, -oo, oo), (y, -oo, oo)).evalf() == 1
-    N = Normal('N', [1, 2], [[x, 0], [0, y]])
-    assert density(N)(0, 0) == exp(-2/y - 1/(2*x))/(2*pi*sqrt(x*y))
+    N1 = Normal('N1', [1, 2], [[x, 0], [0, y]])
+    assert density(N1)(0, 0) == exp(-2/y - 1/(2*x))/(2*pi*sqrt(x*y))
 
     raises (ValueError, lambda: Normal('M', [1, 2], [[1, 1], [1, -1]]))
 
@@ -69,15 +68,3 @@ def test_JointRV():
     assert density(X)(1, 2) == exp(-2)/(2*pi)
     assert isinstance(X.pspace.distribution, JointDistributionHandmade)
     assert marginal_distribution(X, 0)(2) == sqrt(2)*exp(-S(1)/2)/(2*sqrt(pi))
-
-def test_expectation():
-    from sympy import simplify
-    from sympy.stats import E
-    m = Normal('A', [x, y], [[1, 0], [0, 1]])
-    assert simplify(E(m[1])) == y
-
-@XFAIL
-def test_joint_vector_expectation():
-    from sympy.stats import E
-    m = Normal('A', [x, y], [[1, 0], [0, 1]])
-    assert E(m) == (x, y)