Hi, I am adding a light weight support for vector algebra in ginac. I am aware that it can be done through Clifford algebra, but the output is almost incomprehensible to debug. My problem is this. When a request like inner_product(lhs, rhs) is made, where one of lhs and rhs is not a vector, I would like to replace the inner_product with a regular product. How can I achieve this? I am planning to do it as follows 1) extend a symbol to a vector 2) determine if both lhs and rhs have a hanging vector by traversing the expressions in lhs and rhs and by testing for is_a<vector> Is there a better way to test if a symbol is a vector? If not what is the simplest way to extend symbol? thanks, Krishna.
Hi,
Is there a better way to test if a symbol is a vector? If not what is the simplest way to extend symbol?
I looked at the implementation of realsymb and have come to the conclusion that the current implementation of symbol is not extensible. Should we change domain to be a type_info class (or a lighter version if required)? This we we can make symbol extensible. For example class symbol_base : class basic { ... symbol_base(const std::string & initname, type_info* ti); ... type_info const& get_domain_type() const { return *pti; } ... private: type_info const* pti; ... }; template<class domain_type> class domain_symbol : public symbol_base { public: domain_symbol(const std::string & initname) : symbol_base(initname, typeid(domain_type)) { } }; struct real_domain {}; struct complex_domain {}; struct vector_domain {}; typedef domain_symbol<real_domain> real_symbol; typedef domain_symbol<complex_domain> complex_symbol; typedef domain_symbol<vector_domain> vector_symbol; typedef complex_symbol symbol; template<class domain_type> bool is_domain_a(const basic& obj) { if (obj.tinfo() != &symbol::tinfo_static) return false; return type_info(domain_type) == static_cast<const symbol &>(obj).get_domain_type(); } Now things like is_domain_a<real_domain>(e) is_domain_a<vector_domain>(e) makes sense. There is one thing I did not understand though. symbol definition has friend class realsymbol; If this is required my approach (so is any other solution) is doomed, as friend cannot be a template. Let me know if you think of any simpler alternatives. cheers, Krishna.
Hello, On Sat, Oct 04, 2008 at 09:58:25PM -0400, Krishna Mohan Gundu wrote:
Is there a better way to test if a symbol is a vector?
1. I don't think subclassing symbol is a good idea. 2. `vector' is a bad name (because there is std::vector) 3. What's wrong with schoolbook method: typeid(blah) == typeid(YourVector)
class symbol_base : class basic { ... symbol_base(const std::string & initname, type_info* ti); ... type_info const& get_domain_type() const { return *pti; } ... private: type_info const* pti;
symbol is a bit performance (and memory) critical. Adding yet another 8 bytes is not appreciated at all.
Now things like is_domain_a<real_domain>(e) is_domain_a<vector_domain>(e) makes sense.
What's wrong with typeid(e) == typeid(vector_symbol)
as friend cannot be a template.
Sure it can. See the example code in the paragraph 14.5.3.1 of the standard, and this silly program: $ cat test.cc template<typename T> class A; template<typename T> class B; template<typename T> class A { T i; template<typename T1> friend class B; public: A() : i(0) { } A(const T& i_) : i(i_) { } }; template<typename T> class B { T j; public: B() : j(0) { } B(const T& j_) : j(j_) { } template<typename T1> B& operator=(const A<T1>& a) { j = T(a.i); return *this; } T get_j() const { return j; } }; int main() { A<int> a(0); B<long> b(-1); b = a; return b.get_j(); } $ g++ -Wall test.cc $ ./a.out $ echo $? 0
Let me know if you think of any simpler alternatives.
Use already existing code (i.e. clifford class), add whatever functionality you need. Don't hesitate to ask questions if something goes wrong and/or you don't understand something, etc. Best regards, Alexei -- All science is either physics or stamp collecting.
Alexei Sheplyakov-2 wrote:
as friend cannot be a template.
Sure it can. See the example code in the paragraph 14.5.3.1 of the standard,
Sorry, my memory failed me here. I had it confused with "you cannot limit a friend to a partial specialization of a template". -- View this message in context: http://www.nabble.com/extending-the-symbol-tp19818944p19849422.html Sent from the Ginac - General mailing list archive at Nabble.com.
Hello, On Sat, Oct 04, 2008 at 07:09:59PM -0400, Krishna Mohan Gundu wrote:
I am adding a light weight support for vector algebra in ginac. I am aware that it can be done through Clifford algebra, but the output is almost incomprehensible to debug.
I don't quite understand what is exactly wrong. Could you elaborate, please?
My problem is this. When a request like inner_product(lhs, rhs) is made, where one of lhs and rhs is not a vector, I would like to replace the inner_product with a regular product. How can I achieve this?
if (typeid(ex_to<basic>(lhs)) != typeid(your_class)) { // do the replacement } else if (typeid(ex_to<basic>(rhs)) != typeid(your_class)) { // same here } else { // do something nontrivial }
I am planning to do it as follows 1) extend a symbol to a vector
I don't think it's a good idea. Symbol is something simple and in a sense "atomic". Also it's quite performance and memory critical. You'd better use the clifford class. Best regards, Alexei -- All science is either physics or stamp collecting.
Hi Alexei, Can you please attach a copy of your replies to my email address? I disable email delivery whenever I subscribe to forums as most of the times I post infrequently. Alexei Sheplyakov-2 wrote:
I am adding a light weight support for vector algebra in ginac. I am aware that it can be done through Clifford algebra, but the output is almost incomprehensible to debug.
I don't quite understand what is exactly wrong. Could you elaborate, please?
If vector and scalar products of vectors are not given their own identities but are implemented using the clifford algebra as in the post http://www.ginac.de/pipermail/ginac-list/2005-June/000671.html then the output no longer bears any resemblance to the original definition. For example the consider the following output "-C.0*B.2*A.1-C.1*A.2*B.0+C.2*B.0*A.1+C.0*A.2*B.1+C.1*B.2*A.0-C.2*B.1*A.0" There is no resemblance to the original definition which could be printed nicely "A . (B x C)" To emphasize my point, I dont really care how the triple product is represented inside. But when things go wrong (due to bugs) I would like to easily debug the code. For example, if I was expecting A . (C x B), the second output will immediately point out that to me. On the other hand if scalar and vector products of vectors are given their own identities, then there is no need for clifford algebra any more to evaluate them. Alexei Sheplyakov-2 wrote:
My problem is this. When a request like inner_product(lhs, rhs) is made, where one of lhs and rhs is not a vector, I would like to replace the inner_product with a regular product. How can I achieve this?
if (typeid(ex_to<basic>(lhs)) != typeid(your_class)) { // do the replacement } else if (typeid(ex_to<basic>(rhs)) != typeid(your_class)) { // same here } else { // do something nontrivial }
Yes. This would be sufficient. Alexei Sheplyakov-2 wrote:
I am planning to do it as follows 1) extend a symbol to a vector
I don't think it's a good idea. Symbol is something simple and in a sense "atomic". Also it's quite performance and memory critical. You'd better use the clifford class.
I need to think about this. thanks, Krishna. -- View this message in context: http://www.nabble.com/extending-the-symbol-tp19818944p19849081.html Sent from the Ginac - General mailing list archive at Nabble.com.
nomad wrote:
Alexei Sheplyakov-2 wrote:
I am planning to do it as follows 1) extend a symbol to a vector
I don't think it's a good idea. Symbol is something simple and in a sense "atomic". Also it's quite performance and memory critical. You'd better use the clifford class.
I need to think about this.
It is now somewhat clear to me how to proceed. I will represent a vector by a vector symbol, a basis symbol and possibly fixed size. I will represent scalar and vector products as separate products different from '*'. When substitutions are made for the vector symbol and basis symbol, I will evaluate the scalar and vector products. One thing that is not clear to me however is indexing into vectors. If we have vector A and B, what should something like A.0 * B.1 signify? Should indexing be supported at all? -- View this message in context: http://www.nabble.com/extending-the-symbol-tp19818944p19853690.html Sent from the Ginac - General mailing list archive at Nabble.com.
Hi,
I will represent scalar and vector products as separate products different from '*'. When substitutions are made for the vector symbol and basis symbol, I will evaluate the scalar and vector products.
One thing that is not clear to me however is indexing into vectors. If we have vector A and B, what should something like A.0 * B.1 signify? Should indexing be supported at all?
We already have classes (indexed, idx, varidx) designed for manipulating tensors without the need to resort to a specific basis. Your vector looks very similar. Could you please give a few examples (in a form of pseudocode or something like that) demonstrating what kind of operations/features your vector class is supposed to support? Best regards, Alexei -- All science is either physics or stamp collecting.
Hello All, I am attaching the code for performing vector algebra using GiNaC. It supports inner products, cross products and components of vectors. Currently cross product between two 2D vectors returns a scalar and between two 3D vectors returns a vector. I hope that someone will find it useful. Here are a few examples // define vectors vector v1("v1"), v2("v2"), v3("v3"); // vector components cout << v1[2] << endl; // v1[2] // various products cout << inner_prod(v1, v2) << endl; // (v1 . v2) cout << cross_prod(v1, v2) << endl; // (v1 x v2) cout << inner_prod(v1, cross_prod(v2, v3)) << endl; // (v1 . (v2 x v3)) cout << cross_prod(v1, cross_prod(v2, v3)) << endl; // (v1 x (v2 x v3)) // identities (nothing fancy yet) cout << cross_prod(v1, v1) << endl; // 0 // expand ex e1 = inner_prod(v1, v2 + v3); cout << e1 << endl; // (v1 . (v2 + v3)) cout << expand(e1) << endl; // (v1 . v2) + (v1 . v3); // substitution (expand must be used before substitution) lst l1(1,2,3), l2(1,0,1), l3(1,1,0); cout << v1[2].subs(v1 == l1) << endl; // 3 cout << expand(e1).subs(lst(v1 == l1, v2 == l2, v3 == l3)) << endl; // 7 cheers, Krishna.
It can be interesting for some of the guys following this discussion to know about lib3d_mec-ginac. The version at the www is not up to date, but if some one wants it I can send a copy. http://www.imac.unavarra.es/3d_mec/pages/lib3d_mec-ginac.php I'm supporting vector algebra using 3-tuple and 3x3-matrixes, but I was planning to support vector types similar the ones that you are defining. Cheers, Javier.
Hello,
Can you please attach a copy of your replies to my email address? I disable email delivery whenever I subscribe to forums as most of the times I post infrequently.
Sure. Also you can set proper Reply-To: header so my email client software will do this automatically.
If vector and scalar products of vectors are not given their own identities but are implemented using the clifford algebra as in the post http://www.ginac.de/pipermail/ginac-list/2005-June/000671.html then the output no longer bears any resemblance to the original definition. For example the consider the following output
"-C.0*B.2*A.1-C.1*A.2*B.0+C.2*B.0*A.1+C.0*A.2*B.1+C.1*B.2*A.0-C.2*B.1*A.0" There is no resemblance to the original definition
In general, the canonical form of GiNaC expressions is unpredictable, i.e. it changes from run to run (no matter what is the type of the expression). The following script demonstrates this: for i in `seq 1 100`; do echo "a = x; b = y; x - y;" | ginsh done | sort -n | uniq x x-y y -y+x Depending on luck, canonical form of the same expression (x-y) might be either 'x-y' or '-y+x' (of course it's the same during one run). This is kind of design decision: we trade deterministic output for speed. (Still nothing prevents interested parties from writing a custom printing method which outputs terms in a more or less predictable manner).
which could be printed nicely "A . (B x C)"
To emphasize my point, I dont really care how the triple product is represented inside. But when things go wrong (due to bugs) I would like to easily debug the code. For example, if I was expecting A . (C x B), the second output will immediately point out that to me.
This problem can be solved with a custom printing method. But the real question is: do you really need/want to represent tensor expressions in a component form?
On the other hand if scalar and vector products of vectors are given their own identities, then there is no need for clifford algebra any more to evaluate them.
You can write a new class from scratch if modifying clifford (or indexed) is not an option. Best regards, Alexei -- All science is either physics or stamp collecting.
participants (4)
-
Alexei Sheplyakov
-
jros
-
Krishna Mohan Gundu
-
nomad