Hello everyone,
I've been successful in writing the symbolic cholesky decomposition
for sparse matrices in O(n * c**2) time. This is a reasonable order
for sparse systems, but still the performance is not very good. Using
python bulitins, It factors a 100 * 100 Matrix with sparsity 0.57 in
961 milli-seconds. Using Sympy's numbers, it takes forever or is pain-
stakingly slow for matrices larger than 20 * 20.
I understand why we must integrate groundtypes in matrices to make it
usable. But I don't know how exactly to do it.
I see that the Matrix constructor currently employs sympify, so it
changes regular ints to Sympy's Integer. I had removed this when I
wanted to test for the python builtins in my DOKMatrix implementation.
Here's an idea that we can build on. Add a kwarg argument in the
Matrix constructor called dtype, which could takes values like 'gmpy',
'python', 'sympy', etc. or more detailed, 'int', 'expr', 'poly' etc..
So that, before putting the element in the matrix, we convert it to
the required dtype. eg. val = gmpy.mpz(val)
Is it as simple as this, or am I missing something ?
I would like Mateusz especially to comment on this, and also guide me
and help me learn about the Polys structure.
Regards,
Sherjil Ozair
--
You received this message because you are subscribed to the Google Groups "sympy" group.
To post to this group, send email to sy...@googlegroups.com.
To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
I think having such a class would be advantageous. My project deals with
(very small) matrices of rational functions, and I currently convert
them to polys and cancel by hand in intermediate steps. I think working
with a dedicated rational function class all the time might be advantageous.
However I'm not sure RationalFunction should store a pair of Polys, but
rather wrap DMFs. OTOH Mateusz surely knows better whether/how to do this.
Tom
How small ? Numbers would be helpful. Thank you.
On May 29, 4:15 pm, Tom Bachmann <e_mc...@web.de> wrote:
> > What does the community think about this class, the RationalFunction ?
> > Do add ideas from your knowledge and experience also.
>
> I think having such a class would be advantageous. My project deals with
> (very small) matrices of rational functions, and I currently convert
> them to polys and cancel by hand in intermediate steps. I think working
> with a dedicated rational function class all the time might be advantageous.
>
What is a DMF, in detail ? It is mentioned in the thesis only once.
> However I'm not sure RationalFunction should store a pair of Polys, but
> rather wrap DMFs. OTOH Mateusz surely knows better whether/how to do this.
>
"DMF for dense multivariate fractions".
But that is not descriptive enough.
@everyone: Is there more resource available to learn about Polys other
than the thesis ?
> Tom
--
You received this message because you are subscribed to the Google Groups "sympy" group.
To post to this group, send email to sy...@googlegroups.com.
To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
Tom
--You received this message because you are subscribed to the Google Groups "sympy" group.
To post to this group, send email to sy...@googlegroups.com.
To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
Thanks for the pointers. I'm working on what you said.
Here are a few questions.
1. Poly(123) should not give an error, why not treat it as a constant
polynomial?
2. I used construct_domain on the list of elements of the Matrix, It
returned DMP type, which does *not* allow coercion. What to do if one
of my algorithms involve a square root ?
3. Even when I tried operating on DMPs using an algorithm which did
not have a square root, an "unsupported operand type(s) for /: 'int'
and 'DMP'" TypeError was returned.
4. Should I write different code for the algorithms for each
groundtype ? For example, when using Sympy's type, using Add(*(...))
adds efficiency, but it doesn't make sense for other types. I can use
sum(...) but that will sacrifice performance slightly.
5. I think coercion is important for matrix algorithms. Other than
Poly, which other lower-level classes allow coercion ?
Could you explain why normal multiplication/addition operations on
Poly is slower than on Muls and Adds, when Poly is supposed to be
lower level than Mul, Add ?
Smaller than 5x5. And I'm only multiplying them, not doing any fancy
algorithms. So I suppose I'm not really a use case.
Sent on my BlackBerry® from Vodafone
On 29.05.2011 22:10, sherji...@gmail.com wrote:
> Oh. I understand. And how does one turn off cahe ?
>
> Sent on my BlackBerry® from Vodafone
>
> ------------------------------------------------------------------------
> *From: * Mateusz Paprocki <mat...@gmail.com>
> *Sender: * sy...@googlegroups.com
> *Date: *Sun, 29 May 2011 22:37:30 +0200
> *To: *<sy...@googlegroups.com>
> *ReplyTo: * sy...@googlegroups.com
> *Subject: *Re: [sympy] Re: Borrowing ideas from Polys to Matrix
>
> Hi,
>
> On 29 May 2011 12:49, SherjilOzair <sherji...@gmail.com
> <mailto:sherjiloz...@gmail.com>> wrote:
> > Thanks for the pointers. I'm working on what you said.
> >
> > Here are a few questions.
> >
> > 1. Poly(123) should not give an error, why not treat it as a constant
> > polynomial ?
> >
> > 2. I used construct_domain on the list of elements of the Matrix, It
> > returned DMP type, which does *not* allow coercion. What to do if one
> > of my algorithms involve a square root ?
> >
> > 3. Even when I tried operating on DMPs using an algorithm which did
> > not have a square root, an "unsupported operand type(s) for /: 'int'
> > and 'DMP'" TypeError was returned.
> >
> > 4. Should I write different code for the algorithms for each
> > groundtype ? For example, when using Sympy's type, using Add(*(...))
> > adds efficiency, but it doesn't make sense for other types. I can use
> > sum(...) but that will sacrifice performance slightly.
> >
> > 5. I think coercion is important for matrix algorithms. Other than
> > Poly, which other lower-level classes allow coercion ?
> >
> > - Sherjil Ozair
> >
> > On May 28, 11:34 pm, Mateusz Paprocki <matt...@gmail.com
> <mailto:matt...@gmail.com>> wrote:
> >
> >
> >
> >
> >
> >
> >
> > > Hi,
> >
> > > On 28 May 2011 15:30, SherjilOzair <sherjiloz...@gmail.com
> <mailto:sy...@googlegroups.com>.
> > > > To unsubscribe from this group, send email to
> > > > sympy+un...@googlegroups.com
> <mailto:sympy%2Bunsu...@googlegroups.com>.
> > > > For more options, visit this group at
> > > >http://groups.google.com/group/sympy?hl=en.
> >
> > > Mateusz
>
> --
> You received this message because you are subscribed to the Google
> Groups "sympy" group.
> To post to this group, send email to sy...@googlegroups.com
> <mailto:sy...@googlegroups.com>.
> To unsubscribe from this group, send email to
> sympy+un...@googlegroups.com
> <mailto:sympy%2Bunsu...@googlegroups.com>.
Pass SYMPY_USE_CACHE=no on the environment.
Vinzent
--
You received this message because you are subscribed to the Google Groups "sympy" group.
To post to this group, send email to sy...@googlegroups.com.
To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
But do we really need lots of different sum() functions? Is there a
difference between ZZ.sum([1, 2, 3]) and EX.sum([1, 2, 3])?
This hasn't been implemented yet. Should I go ahead and add it ?
sums for QQ, etc also needed.
See [1] for the types I need.
[1] http://groups.google.com/group/sympy/browse_thread/thread/c793f7030853f3da
On May 31, 9:43 pm, Vinzent Steinberg
<vinzent.steinb...@googlemail.com> wrote:
> On May 30, 9:52 pm, Mateusz Paprocki <matt...@gmail.com> wrote:
>
> > That could work:
>
> > ZZ.sum([1, 2, 3]) -> sum([1, 2, 3])
> > RR.sum([1.0, 2.0]) -> mpmath.fsum([1.0, 2.0])
> > EX.sum([x, y, z]) -> Add(*[x, y, z])
>
> > etc.
>
> This is exactly what I have been thinking of.
>
> Vinzent
--
You received this message because you are subscribed to the Google Groups "sympy" group.
To post to this group, send email to sy...@googlegroups.com.
To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
Well, if Domain.sum(...) is significantly faster than sum(elements of
Domain), then its pretty reasonable that it should be implemented. sum
is almost as important as +, -, * and /. sum is used in many
algorithms. Matrix algorithms particularly use sum for dot products.
If you see my code for the cholesky and LDL decomposition in [1], I
have used the Add(*(...)) construct freely, as Matrix currently
converts its elements to Sympy objects. So Add works as a good
summation.
But if I want to abstractify this, and make Matrix work for XYZ dtype,
then the sum has to be an abstract one. Python's builtin sum suffices
as an abstract sum, but is slow. If I have the 'domain' variable
storing the domain type in the Matrix object, I can use
domain.sum(...), and the appropriate sum would be called by the
algorithm, Add for Sympy, fsum for mpmath and so on.
[1] https://github.com/sympy/sympy/pull/184/files (lines 534, 536,
573, 575, 599, etc.)
Yes. You can sum integers perfectly efficiently just by passing them to the built-in sum() (also remember that ZZ(1) != S(1) in general because of the ground types, but EX(1) == S(1) always). But something like Add(*(x, -x, x, x, −x)) is almost two times faster than sum((x, -x, x, x, -x)):
In [1]: Add(*(x, -x, x, x, -x))
Out[1]: x
In [2]: %timeit Add(*(x, -x, x, x, -x))
1000 loops, best of 3: 170 us per loop
In [3]: sum((x, -x, x, x, -x))
Out[3]: x
In [4]: %timeit sum((x, -x, x, x, -x))
1000 loops, best of 3: 313 us per loop
In [16]: b = map(S, range(100))
In [24]: %timeit Add(*b)
1000 loops, best of 3: 546 us per loop
In [25]: %timeit sum(b)
1000 loops, best of 3: 268 us per loop
(all run without the cache, as suggested above). Note that [16] ensures that sum(b) goes through Add. Otherwise, you get
In [26]: %timeit Add(*range(100))
1000 loops, best of 3: 1.45 ms per loop
In [27]: %timeit sum(range(100))
100000 loops, best of 3: 2.7 us per loop
which just proves what we already know, which is that Python ints are (apparently 10x) faster than SymPy Integers.
Aaron Meurer
Did you make those graphs manually, or do you have some program that automates it? It would be nice to have something that can make timing graphs like that with very little work.
Aaron Meurer
> In [1] you will find a very simple comparison of Integer, int and mpz. This applies to the rational case as well, just the difference is even bigger.Did you make those graphs manually, or do you have some program that automates it? It would be nice to have something that can make timing graphs like that with very little work.
Aaron Meurer
--
You received this message because you are subscribed to the Google Groups "sympy" group.
To post to this group, send email to sy...@googlegroups.com.
To unsubscribe from this group, send email to sympy+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
ZZ(1) != S(1), but only some times, is rather counter-intuitive. I don't
understand what ZZ is really supposed to mean anyway. If it's the ring
of integers, why can its value change? And why is it instantiable?
> But something
> like Add(*(x, -x, x, x, -x)) is almost two times faster than sum((x,
> -x, x, x, -x)):
That's rather an implementation detail, and using Add(*[...]) is wrong
anyway, if we want to allow extensions of sympy. Besides, it doesn't
explain why EX.sum([n, -n, n, n]) should be different from ZZ.sum([n,
-n, n, n]).
> Le jeudi 02 juin 2011 à 17:07 -0600, Aaron S. Meurer a écrit :
>> On May 31, 2011, at 11:11 AM, Ronan Lamy wrote:
>>
>>> Le mardi 31 mai 2011 à 09:43 -0700, Vinzent Steinberg a écrit :
>>>> On May 30, 9:52 pm, Mateusz Paprocki <matt...@gmail.com> wrote:
>>>>> That could work:
>>>>>
>>>>> ZZ.sum([1, 2, 3]) -> sum([1, 2, 3])
>>>>> RR.sum([1.0, 2.0]) -> mpmath.fsum([1.0, 2.0])
>>>>> EX.sum([x, y, z]) -> Add(*[x, y, z])
>>>>>
>>>>> etc.
>>>>
>>>> This is exactly what I have been thinking of.
>>>
>>> But do we really need lots of different sum() functions? Is there a
>>> difference between ZZ.sum([1, 2, 3]) and EX.sum([1, 2, 3])?
>>
>> Yes. You can sum integers perfectly efficiently just by passing them
>> to the built-in sum() (also remember that ZZ(1) != S(1) in general
>> because of the ground types, but EX(1) == S(1) always).
>
> ZZ(1) != S(1), but only some times, is rather counter-intuitive. I don't
> understand what ZZ is really supposed to mean anyway. If it's the ring
> of integers, why can its value change? And why is it instantiable?
ZZ(1) means 1 in the current ground type. If the ground type is Python, it returns int(1). If it's gmpy, it returns mpz(1). Actually, ZZ(1) == S(1) only if you manually choose the sympy ground types. Note that I am using "==" here to mean actually something more like "is". I should really have said "type(ZZ(1)) != type(S(1))". __eq__ itself works as expected regardless of the underlying type.
In general, ZZ stands for the domain of integers, and you can pass it to Poly under the domain option (you can also do stuff like ZZ[x] to create the domain of polynomials in x with integer coefficients). ZZ(1) is just syntactic sugar that makes it easy to coerce elements to that domain.
>
>> But something
>> like Add(*(x, -x, x, x, -x)) is almost two times faster than sum((x,
>> -x, x, x, -x)):
>
> That's rather an implementation detail, and using Add(*[...]) is wrong
> anyway, if we want to allow extensions of sympy. Besides, it doesn't
> explain why EX.sum([n, -n, n, n]) should be different from ZZ.sum([n,
> -n, n, n]).
Do you mean that n is symbolic? If so, then ZZ.sum([n, -n, n, n]) doesn't make sense.
Aaron Meurer
>
>>
>> In [1]: Add(*(x, -x, x, x, -x))
>> Out[1]: x
>>
>> In [2]: %timeit Add(*(x, -x, x, x, -x))
>> 1000 loops, best of 3: 170 us per loop
>>
>> In [3]: sum((x, -x, x, x, -x))
>> Out[3]: x
>>
>> In [4]: %timeit sum((x, -x, x, x, -x))
>> 1000 loops, best of 3: 313 us per loop
>>
>> In [16]: b = map(S, range(100))
>>
>> In [24]: %timeit Add(*b)
>> 1000 loops, best of 3: 546 us per loop
>>
>> In [25]: %timeit sum(b)
>> 1000 loops, best of 3: 268 us per loop
>>
>> (all run without the cache, as suggested above). Note that [16]
>> ensures that sum(b) goes through Add. Otherwise, you get
>>
>> In [26]: %timeit Add(*range(100))
>> 1000 loops, best of 3: 1.45 ms per loop
>>
>> In [27]: %timeit sum(range(100))
>> 100000 loops, best of 3: 2.7 us per loop
>>
>> which just proves what we already know, which is that Python ints are
>> (apparently 10x) faster than SymPy Integers.
>>
>> Aaron Meurer
>>
>
>
> In general, ZZ stands for the domain of integers, and you can pass it
> to Poly under the domain option (you can also do stuff like ZZ[x] to
> create the domain of polynomials in x with integer coefficients).
> ZZ(1) is just syntactic sugar that makes it easy to coerce elements to
> that domain.
OK. By domain, you mean type, right? (That 'ZZ[x]' is a rather confusing
bit of syntactic sugar that seems to suggest a mathematical meaning it
doesn't really have and looks weird when you replace ZZ with any of its
possible values)
> >
> >> But something
> >> like Add(*(x, -x, x, x, -x)) is almost two times faster than sum((x,
> >> -x, x, x, -x)):
> >
> > That's rather an implementation detail, and using Add(*[...]) is wrong
> > anyway, if we want to allow extensions of sympy. Besides, it doesn't
> > explain why EX.sum([n, -n, n, n]) should be different from ZZ.sum([n,
> > -n, n, n]).
>
> Do you mean that n is symbolic? If so, then ZZ.sum([n, -n, n, n])
> doesn't make sense.
>
It would make sense if 'ZZ' meant 'the ring of integers'. Actually, even
though that's not the case, it works anyway because ZZ.sum is always
just sum.
Yeah, ZZ, QQ, etc. are all just about syntactic sugar that makes things much shorter to type. You can do all of the stuff equivalently in much longer forms. And by the way, the ZZ[x] syntax just exists because that's the mathematical notation (the square brackets). The real confusing thing is that ZZ(x) is not the field of rational functions in x with integer coefficients (for that you need ZZ.frac_field(x)).
>
>>>
>>>> But something
>>>> like Add(*(x, -x, x, x, -x)) is almost two times faster than sum((x,
>>>> -x, x, x, -x)):
>>>
>>> That's rather an implementation detail, and using Add(*[...]) is wrong
>>> anyway, if we want to allow extensions of sympy. Besides, it doesn't
>>> explain why EX.sum([n, -n, n, n]) should be different from ZZ.sum([n,
>>> -n, n, n]).
>>
>> Do you mean that n is symbolic? If so, then ZZ.sum([n, -n, n, n])
>> doesn't make sense.
>>
> It would make sense if 'ZZ' meant 'the ring of integers'. Actually, even
> though that's not the case, it works anyway because ZZ.sum is always
> just sum.
That depends on if type checking happens on this level or not (and if it does work, it's only by accident).
Aaron Meurer
No, it shouldn't, because ZZ isn't a set. That's indeed the problem with
using the name of an abstract mathematical set to designate a concrete
type. "Symbol('n', integer=True) in ZZ" looks like something that should
obviously be True, but actually it doesn't make sense. So 'isinstance(a,
int_type)' isn't just more readable, it also prevents dangerous
misunderstandings.
BTW, ZZ.__contains__ does exist and does something different from
ZZ.of_type.
> > "Symbol('n', integer=True) in ZZ" looks like something that should
> > obviously be True, but actually it doesn't make sense.
>
> Well, in polys this would be rather ZZ[n], because ZZ means concrete
> integers and not symbolic ones.
But we need symbolic integers if we want to do any symbolic manipulation
on integers. In the main core, there's .is_integer and .is_Integer, they
are different and we need both. Why change the rules in the polynomial
core?
Because you can't really work with symbolic integers, or at least not
in the way that you can work with actual ones. It would be awesome if
you could. But what is quo(x**n - 1, x - 1)? Or factor(x**n - 1)?
(these are actually a nice questions because it's not to difficult to
represent the answer using a summation, but you can imagine how
difficult it can be in general)?
That's symbolic powers, but the same thing applies to symbolic
coefficients. For example, what is quo(x**2 + n*x + m, x - 1)? Maybe
you could generate a general answer, but how that's actually
relatively simple. How about determining if x**3 + n*x**2 + m*x + k
is irreducible over the rationals, where n, m, and k are all
rationals. If n, m, and k are given, it can be determined, but for
symbolic n, m, and k an answer would involve all kinds of crazy number
theory functions, if an answer can even be expressed at all.
Aaron Meurer
>
>> > So 'isinstance(a,
>> > int_type)' isn't just more readable, it also prevents dangerous
>> > misunderstandings.
>>
>> > BTW, ZZ.__contains__ does exist and does something different from
>> > ZZ.of_type.
>>
>> The difference is subtle, ZZ.__contains__ tries to convert the type,
>> but ZZ.of_type only checks the type. It is like '==' vs. 'is'.
>>
>> Vinzent
>>
>
>
Yes, I understand why the polynomials are implemented the way they are.
What I'm trying to understand is, given this implementation, why claim
that "domains" have a symbolic meaning they don't have? If domains are
to be extracted from sympy.polys and used elsewhere, this needs to be
clarified.
Anywhere that uses the polys domains (like the matrices) should use
them in the same way that the polys uses them. But I do agree that it
would be useful to have some kind of "set of integers" object, and
that it would be convenient to give it the name ZZ. I wonder what the
best way around this would be.
Aaron Meurer