Hi Alexei, would you accept this patch to make creation of non-commutative symbols easier? Problem: The GiNaC info documentation claims: "Both symbols and user-defined functions can be specified as being non-commutative" Currently this is only possible by defining a new subclass of symbol and overloading return_type(). Solution: Added unsigned rtype to class symbol Overloaded return_type() Modified constructors (including realsymbol and possymbol), printing and archiving accordingly ------------ Now my next question is (after applying the above patch) whether there is a bug in ncmul::eval(). I created this test program #include <ginac/ginac.h> using namespace GiNaC; int main() { symbol M1("M1", "M1", return_types::noncommutative); symbol x("x"), y("y"); matrix M2(2,2); M2 = x, 0, y, 0; symbol M3("M3", "M3", return_types::noncommutative); ex nc; nc = M1 * M2; // Produces a mul !! nc = M1 * M1; // Produces a ncmul nc = M1 * M3; // Produces a ncmul nc = nc.subs(M1 == M2); // Produces a mul !! } As you can see, the assignment sometimes creates a mul when a ncmul should be created. Best regards, Jan
Hello, Jan,
would you accept this patch to make creation of non-commutative symbols easier?
I'm afraid no, for several reasons: 1. I don't think GiNaC really can handle non-commutative symbols. As far as I can see collect() and friends assumes symbols to be commutative. Also, I don't think GiNaC can handle objects which might be both commutative and non-commutative depending on some flag. 2. The patch is a bit mathematically inconsistent: - Non-commutative realsymbol and possymbol hardly make any sense. - symbol::domain() still says domain::complex. This is very confusing. Non-commutative complex numbers? What's that? 3. Adding extra 8 bytes for every symbol is not really welcome. All in all, just because making symbols non-commutative is technically possible doesn't mean it's a good idea. If you really need something like a non-commutative symbol, it's much safer (and in fact easier) to write a proper class (which inherits from basic).
Problem: The GiNaC info documentation claims:
"Both symbols and user-defined functions can be specified as being non-commutative"
Documentation has bugs, too, and you've found one.
------------ Now my next question is (after applying the above patch) whether there is a bug in ncmul::eval(). I created this test program
#include <ginac/ginac.h>
using namespace GiNaC;
int main() { symbol M1("M1", "M1", return_types::noncommutative);
symbol x("x"), y("y"); matrix M2(2,2); M2 = x, 0, y, 0;
symbol M3("M3", "M3", return_types::noncommutative);
ex nc; nc = M1 * M2; // Produces a mul !!
First of all, this is the expected (and documented) behavior. Say, x*M1*M3 is a commutative product, too. It consists of two terms, x and M1*M3 (where M1*M3 is a non-commutative product). See the manual (specifically, the section titled `Non-commutative objects') for more examples. Secondly, (as far as I remember) we assume matrices to commute with "scalars". Non-commutative symbols can make this assumption invalid.
nc = M1 * M1; // Produces a ncmul nc = M1 * M3; // Produces a ncmul
Again, this is the expected behavior.
nc = nc.subs(M1 == M2); // Produces a mul !!
Ditto. Best regards, Alexei
Hello Alexei, maybe I should explain why I need non-commutative symbols. Without them, this code: #include <ginac/ginac.h> using namespace GiNaC; int main() { symbol M1("M1"); symbol x("x"), y("y"); matrix M2(2,2); M2 = x, 0, y, 0; matrix M3(2,2); M3 = 0, x, x, 0; symbol M4("M3"); ex nc; nc = M1 * M4; nc = nc.subs(M1 == M2); nc = nc.subs(M4 == M3); nc.evalm(); } throws matrix::mul_scalar(): non-commutative scalar Is that the expected behaviour?
2. The patch is a bit mathematically inconsistent: - Non-commutative realsymbol and possymbol hardly make any sense. - symbol::domain() still says domain::complex. This is very confusing. Non-commutative complex numbers? What's that? sorry, I am a mechanical engineer :-)
All in all, just because making symbols non-commutative is technically possible doesn't mean it's a good idea. If you really need something like a non-commutative symbol, it's much safer (and in fact easier) to write a proper class (which inherits from basic). OK, I will do that. But if I read your other explanations correctly, even a separate class will not really solve the problem I described above?
Best regards, Jan
Jan wrote:
Non-commutative complex numbers? What's that?
sorry, I am a mechanical engineer :-)
Quaternions. Invented by Hamilton, and surprisingly useful to represent rotations in three dimensions. I believe that the 3D graphics community use them quite a lot - google "dual quaternions".
On Wed, Feb 16, 2011 at 07:34:55AM -0600, Stephen Montgomery-Smith wrote:
Non-commutative complex numbers? What's that? sorry, I am a mechanical engineer :-)
Quaternions.
Also known as (3-dimensional spin 1/2) spinors. I think calling them 'complex numbers' is a bit confusing.
Invented by Hamilton
Re-invented by Ehrenfest, Pauli, Dirac, and others. Extensively used in quantum mechanics. Best regards, Alexei
Alexei Sheplyakov wrote:
On Wed, Feb 16, 2011 at 07:34:55AM -0600, Stephen Montgomery-Smith wrote:
Non-commutative complex numbers? What's that? sorry, I am a mechanical engineer :-)
Quaternions.
Also known as (3-dimensional spin 1/2) spinors. I think calling them 'complex numbers' is a bit confusing.
Yes - I was giving the poster a lot of the benefit of the doubt.
Invented by Hamilton
Re-invented by Ehrenfest, Pauli, Dirac, and others. Extensively used in quantum mechanics.
I didn't know they were reinvented! They were some very smart people.
Hi again,
maybe I should explain why I need non-commutative symbols. Without them, this code:
#include <ginac/ginac.h>
using namespace GiNaC;
int main() { symbol M1("M1");
symbol x("x"), y("y"); matrix M2(2,2); M2 = x, 0, y, 0;
matrix M3(2,2); M3 = 0, x, x, 0;
symbol M4("M3");
ex nc; nc = M1 * M4;
nc = nc.subs(M1 == M2); nc = nc.subs(M4 == M3); nc.evalm();
Perhaps you meant nc = nc.evalm();
}
throws matrix::mul_scalar(): non-commutative scalar
Is that the expected behaviour?
Yes, sort of. Substituting a commutative object with a non-commutative one is ill defined. I.e. the order of terms in the expression `x*y' does not matter, and GiNaC can (and does) shuffle terms to canonicalize the expression (in order to make the internal representation of `x*y' and 'y*x' exactly the same, so the check for equality x*y == y*x is very fast, as it boils down to comparing two pointers). Now if one substitutes both x and y with non-commutative objects (say, X, and Y, respectively), the result is undefined: it can be either X*Y or Y*X (and it might change from run to run).
OK, I will do that. But if I read your other explanations correctly, even a separate class will not really solve the problem I described above?
I guess explaining GiNaC that those symbols does not commute with matrices would help (override return_type_tinfo()). I haven't checked it (yet), though. Best regards, Alexei
participants (3)
-
Alexei Sheplyakov
-
Jan
-
Stephen Montgomery-Smith