- removed debugging code in match()
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Fri, 25 May 2001 20:51:35 +0000 (20:51 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Fri, 25 May 2001 20:51:35 +0000 (20:51 +0000)
- added ex::match(const ex & pattern) which doesn't take a list as second
  argument
- expairseq::subs() substitutes in recombined pairs when the pattern is a
  product or a power; this is necessary for things like subs(2*x^2,x^2==3)
  because the first expression is mul(<x,2>,2) and only substituting in the
  "rest" part of the expair is not enough

ginac/basic.cpp
ginac/ex.cpp
ginac/ex.h
ginac/expairseq.cpp
ginac/idx.cpp
ginac/idx.h

index c899d19..90b9c14 100644 (file)
@@ -213,10 +213,10 @@ ex basic::operator[](int i) const
        return op(i);
 }
 
-/** Search ocurrences.  An object  'has' an expression if it is the expression
+/** Search ocurrences.  An object 'has' an expression if it is the expression
  *  itself or one of the children 'has' it.  As a consequence (according to
  *  the definition of children) given e=x+y+z, e.has(x) is true but e.has(x+y)
- *  is false. */
+ *  is false.  The expression can also contain wildcards. */
 bool basic::has(const ex & other) const
 {
        GINAC_ASSERT(other.bp!=0);
@@ -405,7 +405,22 @@ bool basic::contract_with(exvector::iterator self, exvector::iterator other, exv
  *  is added to repl_lst. */
 bool basic::match(const ex & pattern, lst & repl_lst) const
 {
-//clog << "match " << *this << " with " << pattern << ", repl_lst = " << repl_lst << endl;
+/*
+       Sweet sweet shapes, sweet sweet shapes,
+       Thats the key thing, right right.
+       Feed feed face, feed feed shapes,
+       But who is the king tonight?
+       Who is the king tonight?
+       Pattern is the thing, the key thing-a-ling,
+       But who is the king of pattern?
+       But who is the king, the king thing-a-ling,
+       Who is the king of Pattern?
+       Bog is the king, the king thing-a-ling,
+       Bog is the king of Pattern.
+       Ba bu-bu-bu-bu bu-bu-bu-bu-bu-bu bu-bu
+       Bog is the king of Pattern.
+*/
+
        if (is_ex_exactly_of_type(pattern, wildcard)) {
 
                // Wildcard matches anything, but check whether we already have found
@@ -458,7 +473,7 @@ ex basic::subs(const lst & ls, const lst & lr, bool no_pattern) const
                for (unsigned i=0; i<ls.nops(); i++) {
                        lst repl_lst;
                        if (match(*ls.op(i).bp, repl_lst))
-                               return lr.op(i).bp->subs(repl_lst, true); // avoid recursion when re-substituting the wildcards
+                               return lr.op(i).bp->subs(repl_lst, true); // avoid infinite recursion when re-substituting the wildcards
                }
        }
 
index 02d20e8..e8ce2da 100644 (file)
@@ -31,6 +31,7 @@
 #include "power.h"
 #include "relational.h"
 #include "indexed.h"
+#include "lst.h"
 #include "input_lexer.h"
 #include "debugmsg.h"
 #include "utils.h"
@@ -136,6 +137,13 @@ ex ex::diff(const symbol & s, unsigned nth) const
                return bp->diff(s, nth);
 }
 
+/** Check whether expression matches a specified pattern. */
+bool ex::match(const ex & pattern) const
+{
+       lst repl_lst;
+       return bp->match(pattern, repl_lst);
+}
+
 /** Simplify/canonicalize expression containing indexed objects. This
  *  performs contraction of dummy indices where possible and checks whether
  *  the free indices in sums are consistent.
index 1449b63..34ce8b8 100644 (file)
@@ -105,6 +105,7 @@ public:
        ex evalf(int level = 0) const { return bp->evalf(level); }
        ex diff(const symbol & s, unsigned nth = 1) const;
        ex series(const ex & r, int order, unsigned options = 0) const;
+       bool match(const ex & pattern) const;
        bool match(const ex & pattern, lst & repl_lst) const { return bp->match(pattern, repl_lst); }
        ex subs(const lst & ls, const lst & lr, bool no_pattern = false) const { return bp->subs(ls, lr, no_pattern); }
        ex subs(const ex & e, bool no_pattern = false) const { return bp->subs(e, no_pattern); }
index 2d9a8f6..9421570 100644 (file)
@@ -324,7 +324,6 @@ ex expairseq::normal(lst &sym_lst, lst &repl_lst, int level) const
 
 bool expairseq::match(const ex & pattern, lst & repl_lst) const
 {
-//clog << "match " << *this << " with " << pattern << ", repl_lst = " << repl_lst << endl;
        // This differs from basic::match() because we want "a+b+c+d" to
        // match "d+*+b" with "*" being "a+c", and we want to honor commutativity
 
@@ -1659,47 +1658,89 @@ epvector expairseq::diffchildren(const symbol &y) const
 /** Member-wise substitute in this sequence.
  *
  *  @see expairseq::subs()
- *  @return pointer to epvector containing pairs after application of subs or zero
- *  pointer, if no members were changed. */
+ *  @return pointer to epvector containing pairs after application of subs,
+ *    or NULL pointer if no members were changed. */
 epvector * expairseq::subschildren(const lst &ls, const lst &lr, bool no_pattern) const
 {
-       // returns a NULL pointer if nothing had to be substituted
-       // returns a pointer to a newly created epvector otherwise
-       // (which has to be deleted somewhere else)
        GINAC_ASSERT(ls.nops()==lr.nops());
-       
-       epvector::const_iterator last = seq.end();
-       epvector::const_iterator cit = seq.begin();
-       while (cit!=last) {
-               const ex &subsed_ex=(*cit).rest.subs(ls,lr,no_pattern);
-               if (!are_ex_trivially_equal((*cit).rest,subsed_ex)) {
+
+       // The substitution is "complex" when any of the objects to be substituted
+       // is a product or power. In this case we have to recombine the pairs
+       // because the numeric coefficients may be part of the search pattern.
+       bool complex_subs = false;
+       for (unsigned i=0; i<ls.nops(); i++)
+               if (is_ex_exactly_of_type(ls.op(i), mul) || is_ex_exactly_of_type(ls.op(i), power)) {
+                       complex_subs = true;
+                       break;
+               }
+
+       if (complex_subs) {
+
+               // Substitute in the recombined pairs
+               epvector::const_iterator cit = seq.begin(), last = seq.end();
+               while (cit != last) {
+
+                       const ex &orig_ex = recombine_pair_to_ex(*cit);
+                       const ex &subsed_ex = orig_ex.subs(ls, lr, no_pattern);
+                       if (!are_ex_trivially_equal(orig_ex, subsed_ex)) {
+
+                               // Something changed, copy seq, subs and return it
+                               epvector *s = new epvector;
+                               s->reserve(seq.size());
+
+                               // Copy parts of seq which are known not to have changed
+                               s->insert(s->begin(), seq.begin(), cit);
+
+                               // Copy first changed element
+                               s->push_back(split_ex_to_pair(subsed_ex));
+                               ++cit;
+
+                               // Copy rest
+                               while (cit != last) {
+                                       s->push_back(split_ex_to_pair(recombine_pair_to_ex(*cit).subs(ls, lr, no_pattern)));
+                                       ++cit;
+                               }
+                               return s;
+                       }
+
+                       ++cit;
+               }
+
+       } else {
+
+               // Substitute only in the "rest" part of the pairs
+               epvector::const_iterator cit = seq.begin(), last = seq.end();
+               while (cit != last) {
+
+                       const ex &subsed_ex = cit->rest.subs(ls, lr, no_pattern);
+                       if (!are_ex_trivially_equal(cit->rest, subsed_ex)) {
                        
-                       // something changed, copy seq, subs and return it
-                       epvector *s = new epvector;
-                       s->reserve(seq.size());
+                               // Something changed, copy seq, subs and return it
+                               epvector *s = new epvector;
+                               s->reserve(seq.size());
+
+                               // Copy parts of seq which are known not to have changed
+                               s->insert(s->begin(), seq.begin(), cit);
                        
-                       // copy parts of seq which are known not to have changed
-                       epvector::const_iterator cit2 = seq.begin();
-                       while (cit2!=cit) {
-                               s->push_back(*cit2);
-                               ++cit2;
-                       }
-                       // copy first changed element
-                       s->push_back(combine_ex_with_coeff_to_pair(subsed_ex,
-                                                                  (*cit2).coeff));
-                       ++cit2;
-                       // copy rest
-                       while (cit2!=last) {
-                               s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.subs(ls,lr,no_pattern),
-                                                                          (*cit2).coeff));
-                               ++cit2;
+                               // Copy first changed element
+                               s->push_back(combine_ex_with_coeff_to_pair(subsed_ex, cit->coeff));
+                               ++cit;
+
+                               // Copy rest
+                               while (cit != last) {
+                                       s->push_back(combine_ex_with_coeff_to_pair(cit->rest.subs(ls, lr, no_pattern),
+                                                                                  cit->coeff));
+                                       ++cit;
+                               }
+                               return s;
                        }
-                       return s;
+
+                       ++cit;
                }
-               ++cit;
        }
        
-       return 0; // signalling nothing has changed
+       // Nothing has changed
+       return NULL;
 }
 
 //////////
index 117a02b..7088c5b 100644 (file)
@@ -305,17 +305,45 @@ int spinidx::compare_same_type(const basic & other) const
        GINAC_ASSERT(is_of_type(other, spinidx));
        const spinidx &o = static_cast<const spinidx &>(other);
 
+       // Check dottedness first so dummy indices will end up next to each other
+       if (dotted != o.dotted)
+               return dotted ? -1 : 1;
+
        int cmpval = inherited::compare_same_type(other);
        if (cmpval)
                return cmpval;
 
-       // Check variance and dottedness last so dummy indices will end up next to each other
+       return 0;
+}
+
+bool idx::match(const ex & pattern, lst & repl_lst) const
+{
+       if (!is_ex_of_type(pattern, idx))
+               return false;
+       const idx &o = ex_to_idx(pattern);
+       if (!dim.is_equal(o.dim))
+               return false;
+       return value.match(o.value, repl_lst);
+}
+
+bool varidx::match(const ex & pattern, lst & repl_lst) const
+{
+       if (!is_ex_of_type(pattern, varidx))
+               return false;
+       const varidx &o = ex_to_varidx(pattern);
        if (covariant != o.covariant)
-               return covariant ? -1 : 1;
-       if (dotted != o.dotted)
-               return dotted ? -1 : 1;
+               return false;
+       return inherited::match(pattern, repl_lst);
+}
 
-       return 0;
+bool spinidx::match(const ex & pattern, lst & repl_lst) const
+{
+       if (!is_ex_of_type(pattern, spinidx))
+               return false;
+       const spinidx &o = ex_to_spinidx(pattern);
+       if (dotted != o.dotted)
+               return false;
+       return inherited::match(pattern, repl_lst);
 }
 
 ex idx::subs(const lst & ls, const lst & lr, bool no_pattern) const
index 02caba5..8f952b8 100644 (file)
@@ -51,7 +51,7 @@ public:
        bool info(unsigned inf) const;
        unsigned nops() const;
        ex & let_op(int i);
-protected:
+       bool match(const ex & pattern, lst & repl_lst) const;
        ex subs(const lst & ls, const lst & lr, bool no_pattern = false) const;
 
        // new virtual functions in this class
@@ -105,6 +105,7 @@ public:
        // functions overriding virtual functions from bases classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
+       bool match(const ex & pattern, lst & repl_lst) const;
        bool is_dummy_pair_same_type(const basic & other) const;
 
        // non-virtual functions in this class
@@ -147,6 +148,7 @@ public:
        // functions overriding virtual functions from bases classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
+       bool match(const ex & pattern, lst & repl_lst) const;
        bool is_dummy_pair_same_type(const basic & other) const;
 
        // non-virtual functions in this class