Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added orthogonalize and project functions to the vector module #10474

Merged
merged 12 commits into from
Feb 9, 2016

Conversation

megh1241
Copy link
Contributor

I noticed that the sympy vector module didn't have a function to orthogonalize a given set of linearly independent vectors using the Gram - Schmidt process. This function is present in many other CASs. (Such a function seems to exist in the linear algebra module but it works only with matrix inputs and doesn't seem to work with vector inputs ). I added a function orthogonalize to compute this. The functions vec_project and scalar_project compute the vector and scalar projections of two vectors respectively.
Ping @asmeurer @srjoglekar246 @aktech @moorepants

@@ -474,3 +474,54 @@ def _path(from_object, to_object):
from_path.append(other_path[i])
i -= 1
return index, from_path

def orthogonalize(vlist, orthonormal=False):
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a fan of using the more pythonic notation here:

def orthogonalize(*vlist, orthonormal=False):

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@moorepants . AFAIK, python doesn't allow something like
def orthogonalize(*vlist, orthonormal=False):
(I am getting a syntax error).
It allows
def orthogonalize(vlist, orthonormal=False): and
def orthogonalize(*vlist, **kwargs):.
I may be mistaken however.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah this only works in Python 3. You'll have to just the **kwargs way to make ti Py 2 compatible.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry. I still prefer the *vlist. It makes for a much clearer api, no?

@moorepants
Copy link
Member

This looks good but maybe my mentioned design changes would be preferred. Let me know what you think.

@megh1241
Copy link
Contributor Author

megh1241 commented Feb 5, 2016

@moorepants , I've made the changes that you have suggested above. I agree with you on all of the above points. Let me know if there is anything that needs to be changed.

raise TypeError('Each element must be of Type Vector')

ortho_vlist = []
for i in range(len(vlist)):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This it typically considered an anti-pattern in python. Instead using:

for i, term in enumerate(vlist):

is more typical.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes you are right. I've made the change.


ortho_vlist = []
for i, term in enumerate(vlist):
term = vlist[i]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to do this since you are already enumerating.

@megh1241
Copy link
Contributor Author

megh1241 commented Feb 7, 2016

@srjoglekar246 , I've made the changes that you have suggested. Thanks for the feedback.

@srjoglekar246
Copy link
Member

Apart from the slight issue with the definition of orthogonalize (reverting to your orignal parameters vlist and orthonormal), I am +1 to this if all tests pass.

for i, term in enumerate(vlist):
for j in range(i):
term -= ortho_vlist[j].projection(vlist[i])
if simplify(term).equals(Vector.zero):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment here saying something like:

# TODO : The following line introduces a performance issue and needs to be changed once a good solution for issue #XXXX is found.

@megh1241
Copy link
Contributor Author

megh1241 commented Feb 7, 2016

@moorepants , I've added the todo line as you suggested.

@megh1241
Copy link
Contributor Author

megh1241 commented Feb 8, 2016

@moorepants I've changed it back to _vlist and *_kwargs

vlist : list of independent vectors to be made orthogonal.

orthonormal : Optional parameter
Set to True if the the vectors returned should be orthonormal.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be indented.

@moorepants
Copy link
Member

Please fix the last two minor issues and then I'm +1 to merge if the tests pass.

@megh1241
Copy link
Contributor Author

megh1241 commented Feb 9, 2016

@moorepants , I have fixed the issues.

moorepants added a commit that referenced this pull request Feb 9, 2016
Added orthogonalize and project functions to the vector module
@moorepants moorepants merged commit b0fced4 into sympy:master Feb 9, 2016
@moorepants
Copy link
Member

Thanks! Please add a note to the release notes.

@megh1241
Copy link
Contributor Author

megh1241 commented Feb 9, 2016

Thank you @moorepants

Please add a note to the release notes.

Not sure I quite understood.

@srjoglekar246
Copy link
Member

@meghana1995 , add a note about the change you made here: https://github.com/sympy/sympy/wiki/Release-Notes-for-1.0 . Also, you might want to update the documentation for the vector module, to reflect the new functions. Thanks for the contribution!

jsonn pushed a commit to jsonn/pkgsrc that referenced this pull request Aug 16, 2016
Release Notes for 1.0

Major changes

As a 1.0 release, there are some major changes, many of which are breaking. See also the "backwards compatibility breaks and deprecations" section below.

    mpmath is now a hard external dependency for SymPy. sympy.mpmath will no longer work (use import mpmath). See http://docs.sympy.org/latest/install.html#mpmath for more information on how to install mpmath.

    The galgebra Geometric Algebra module has been removed. The module is now maintained separately at https://github.com/brombo/galgebra.

    The new solveset function is a planned replacement for solve. solve is not yet deprecated, since solveset hasn't yet fully replicated all the functionality of solve. solveset offers an improved interface to solve. See http://docs.sympy.org/latest/modules/solvers/solveset.html for more information on solveset vs. solve.

    This will be the last version of SymPy to support Python 2.6 and 3.2. Both of these Python versions have reached end-of-life. Support for other Python versions will continue at least until they have reached end-of-life.

Backwards compatibility breaks and deprecations

    In sympy.geometry, Line.equal() has been deprecated in favor of Line.equals().
    The dup_inner_subresultants and dmp_inner_subresultants now only return 2 arguments instead of 3. Only those building their own routines from these very low-level functions need to be aware of this.
    This release doesn't include copy of the mpmath library, see PR #2192. Please see new installation instructions for SymPy.

    The release no longer includes the galgebra subumodule. This module is now maintained separately at https://github.com/brombo/galgebra. See PR #10046.

    ClassRegistry is deprecated. It's unlikely that anybody ever used it; it is scheduled for removal for the next version of SymPy after 1.0.
    sympy.C is deprecated and scheduled for removal after 1.0, too. For those users who followed some erroneous SymPy documentation and used C as in C.log, just import sympy and use sympy.log instead: this is compatible with SymPy before and after we remove C.
    Q.bounded has been deprecated. Use Q.finite instead.
    Q.infinity has been deprecated. Use Q.infinite instead.
    Q.infinitesimal has been deprecated. Use Q.zero instead.
    ask(Q.nonzero(non-real)) now returns False. Note that Q.nonzero is equivalent to ~Q.zero & Q.real. If you intend to find whether x is a non-zero number irrespective of the fact that x is real or not, you should use ask(~Q.zero(x)).
    x.is_nonzero now returns True iff x is real and has a non-zero value. If you intend to find whether x is a non-zero number irrespective of the fact that x is real or not, you should use fuzzy_not(x.is_zero).
    isprime(Float) now returns False.
    ask(Q.integer(Float)) now returns False.
    ask(Q.prime(Float)) now returns False.
    ask(Q.composite(Float)) now returns False.
    ask(Q.even(Float)) now returns False.
    ask(Q.odd(Float)) now returns False.

New features

    The module sympy.series.ring_series has been updated. New methods for series inversion, expansion of hyperbolic and inverse functions, etc have been added. PR #9262

    New module sympy.series.sequences for generating finite/infinite lazily evaluated lists. [PR #9435]

    The string representation function srepr() now displays the assumptions used to create a Symbol. For example, srepr(Symbol('x', real=True)) now returns the string "Symbol('x', real=True)" instead of merely "Symbol('x')".

    not_empty_in function added to util.py in calculus module which finds the domain for which the FiniteSet is not-empty for a given Union of Sets. [PR #9779]

    A new and fast method rs_series has been added for calculating series expansions. It can handle multivariate Puiseux series with symbolic coefficients. It is especially optimized for large series, with speedup over the older series method being in the range 20-1000 times. PR #9775

In [37]: %timeit rs_series(cos(a+b*a**QQ(3,2)), a, 10)
100 loops, best of 3: 5.59 ms per loop

In [38]: %timeit cos(a+b*a**QQ(3,2)).series(a, 0, 10)
1 loops, best of 3: 997 ms per loop

    Complex Sets has been added here: sympy.sets.fancysets, use S.Complexes for singleton ComplexRegion class. PR #9463

    GeometryEntity now subclasses from sets.Set, so sets.Intersection and sets.Union can be used with GeometryEntitys. For example Intersection(Line((-1,-1),(1,1)), Line((-1,1), (1,-1))) == FiniteSet(Point2D(0,0)).

    New module sympy.series.fourier for computing fourier sine/cosine series. [PR #9523]

    Linsolve: General Linear System Solver in sympy.solvers.solveset, use linsolve() for solving all types of linear systems. PR #9438

    New assumption system is now able to read the assumptions set over Symbol object. For e.g.:

In [7]: x = Symbol('x', positive=True)

In [8]: ask(Q.positive(x))
Out[8]: True

    A new handler system has been added as sympy.assumptions.satask which uses satisfiable to answer queries related to assumptions. In case the legacy ask doesn't know the answer, it falls back on satask.

For e.g.

Earlier

>>> ask(Q.zero(x) | Q.zero(y), Q.zero(x*y))
>>> ask(Implies(Q.zero(x), Q.zero(x*y)))
>>> ask(Q.zero(x) | Q.zero(y), Q.nonzero(x*y))

Now

>>> ask(Q.zero(x) | Q.zero(y), Q.zero(x*y))
True
>>> ask(Implies(Q.zero(x), Q.zero(x*y)))
True
>>> ask(Q.zero(x) | Q.zero(y), Q.nonzero(x*y))
False

    New module sympy.series.formal for computing formal power series. [PR #9639]

    New set class ConditionSet was implemented. [PR #9696]

    Differential calculus Methods, like is_increasing, is_monotonic, etc were implemented in sympy.calculus.singularities in [PR #9820]

    New module sympy.series.limitseq for finding limits of terms containing sequences. [PR #9836]

    New module sympy/polys/subresultants_qq_zz.py :: contains various functions for computing Euclidean, Sturmian and (modified) subresultant polynomial remainder sequences in Q[x] or Z[x]. All methods are based on the recently discovered theorem by Pell and Gordon of 1917 and an extension/generalization of it of 2015. [PR #10374]

Minor changes

    limit(sin(x), x, oo) now returns AccumulationBound object instead of un-evaluated sin(oo). Implemented in [PR #10051].

    Point is now an n-dimensional point and subclassed to Point2D and Poin3D where appropriate. Point is also now enumerable and can be indexed (e.g., x=Point(1,2,3); x[0])

    roots_cubic will no longer raise an error when the sign of certain expressions is unknown. It will return a generally valid solution instead.

    Relational.canonical will put a Relational into canonical form which is useful for testing whether two Relationals are trivially the same.

    Relational.reversed gives the Relational with lhs and rhs reversed and the symbol updated accordingly (e.g. (x < 1).reversed -> 1 > x

    Simplification of Relationals will, if the threshold for simplification is met, also return the Relational in canonical form. One of the criteria of being in canonical form is that the Number will be on the rhs. This makes writing tests a little easier so S(1) > x can be entered as 1 > x or x < 1 (the former being turned into the latter by Python).

    boolalg functions And, Or, Implies, Xor, Equivalent are aware of Relational complements and trivial equalities, so, for example, And(x=1) will reduce to False while And(S(1)>x,x<1) reduces to x < 1. This leads to some simplifications in statistical expressions.

    Polynomials created using ring now accept negative and fractional exponents. For e.g,

In [1]: R, x, y = ring('x, y', QQ)

In [2]: x**(-2) + y**Rational(2,3)
Out[2]: y**(2/3) + x**(-2)

    The function used to test connectivity in Min and Max has been altered to use the weaker form of a relationship since this applies to arguments like floor(x) and x: though, in generally, we cannot say that floor(x) < x, if x is real we do know that floor(x) <= x. This allows Min(x, floor(x)) -> floor(x) without loss of generality when x is real.

    Float has changed its default behaviour on string/int/long to use at least 15 digits of precision and to increase the precision automatically. This enables sympify('1.23456789012345678901234567890') to return a high-precision Float. It also means N('1.23456789012345678901234567890', 20) does the right thing (where it previously lost precision because an intermediate calculation had only precision 15). See Issue #8821

    The unicode pretty printer now uses a compact single-character square root symbol for simple expressions like sqrt(x) and sqrt(17). You can disable this new behaviour with pprint(sqrt(2), use_unicode_sqrt_char=False).

    ask(Q.finite(x), Q.infinite(x)) now returns False.

    You can now read the definition of assumption predicates in the docs.

    ask(Q.composite(1)) now returns False.

    exp(expr) won't simplify automatically based on assumptions on expr. Autosimplification works for numbers and Symbol, though. You'll have to call refine on exp for simplification.

    Idx objects can now be summation variables of Sum and Product.

    The keyword argument of GramSchmidt was renamed from "orthog" to "orthonormal". This is because GramSchmidt always returns an orthogonal set of vectors but only if that argument is True does it return an orthonormal set of vectors.

    RootOf now has a new subclass ComplexRootOf (abbreviated CRootOf). All currently defined functionality is in the subclass. There is a new function rootof with the same call interface as that of RootOf. It will create objects of CRootOf. New code should use rootof instead of RootOf which is planned to become an abstract class.

    The vector module has a new function orthogonalize which applies the Gram Schmidt orthogonalization on a sequence of linearly independent vectors and returns a sequence of orthogonal (or orthonormal) vectors. The projection method has been added to compute the vector (or scalar) projection of one vector on another vector. (See sympy/sympy#10474)

Update by K.I.A.Derouiche in PR pkg/51270
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants