MathGroup Archive 2011

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: pattern bugs and comment on intuitive syntax for the New Year

  • To: mathgroup at smc.vnet.net
  • Subject: [mg115183] Re: pattern bugs and comment on intuitive syntax for the New Year
  • From: Richard Fateman <fateman at cs.berkeley.edu>
  • Date: Tue, 4 Jan 2011 04:21:37 -0500 (EST)
  • References: <ifs30a$oor$1@smc.vnet.net>

Andrezj wrote..
(his stuff modified so it doesn't go off the end of the line,
prefixed with $)

$ I certainly don't intend to provide incentive for more of
$ these seemingly never ending monologues by Richard.

Can't be a monologue if you respond.

$ They
$ standard pattern that they have followed for years is to begin
$ a discussion about some aspect of Mathematica (usually to
$ claim or suggest some "bug" or bad design) and then when it is
$ pointed out that the behaviour described is perfectly natural
$ and logical (given the basic principles of Mathematica) to
$ point out triumphantly that ... it is done differently in
$ Lisp...

$ A typical example was in a recent response to a post of mine
$ (which I decided to ignore at the time): when I pointed out
$ that symbolic programs can't be compiled in Mathematica
$ Richard kindly informed me that they can be compiled in Lisp,
$ which is hardly surprising given that Lisp, unlike
$ Mathematica, is a compiled language.

Simply stated, a programming language is a kind of abstraction.
An implementation of a language can be interpreted, compiled,
both, or something in-between.  Some implementations of Lisp
are only compiled. some are only interpreted (usually toys).
Some are "byte-compiled". Many are both.  Mathematica allows
for compilation of some stuff but is mostly interpreted, so
it resembles most Lisps in this respect.

So to call Lisp compiled and Mathematica not compiled is either
over-simplified or ignorant.


$ (When posting here Richard generally assumes that no one but
$ him knows anything about languages like Lisp.

Of course I don't assume that.  I tweak you because you are
so authoritative and incorrect.

 >It may perhaps
$ come as a shock to him but I actually thought Scheme for three
$ taught?
$ years, to, horror of horrors, computer science students, using
$ Friedman and Felleisen's The Little Schemer and the Seasoned
$ Schemer. This was at a major computer science school in Japan,
$ where none of the students knew any Lisp or Scheme and now
$ that I no longer teach this course, nobody else does
$ either.

I would guess that the students you taught did not get a
very good introduction to the Lisp language.

$ It suggests to me a less than bright future for this
$ once important language and, of course, any CAS that use it
$ for programming).

I would suggest Norvig's Paradigms of AI Programming as suitable
reading for how to build a CAS in Lisp. Lots of working (though
over-simplified) code, including symbolic integration is given
in that text.

$ So, while I don't intend to respond to this latest RJF post in
$ detail, there are a couple of issues here that may be of some
$ general interest and seem worth commenting on.

Thanks for avoiding detail.

$ First, most of the patterns used in these examples are unlikely to
$ appear in practice.

See below, for the practical exercise that lead me to this
example.

$ If I understand correctly the intention behind
$ them, the natural way to achieve the "desired" result would have been:

$  x + 3 /. x_ + c_. :> aha[c]
$  x /. x_ + c_. :> aha[c]
$ x + y + 3 /. x +  y + c_. :> aha[c]

$  which all produce the expected results. Perhaps I am missing
$  something but I can't see at all why anybody would use
$  BlankNullSequence in this situation.

OK, since c___ matches 0 or more elements, one might reasonably
expect it to absorb everything left over in the sum.  It does so
for x+y+3, as well as x+y.
It fails to do so when presented with the second of the two examples
x+3,  x.
Could the pattern matcher be changed to handle that in a consistent
fashion? When it is looking for a Plus, but finds something, say expr,
which is not a Plus, to treat it as Plus[expr,0]? Maybe.  Could the 
programmer (Andrzej) come up with a work-around? Yes.

$  Second, the one thing, that may be somewhat puzzling among
$  the examples below, is the difference between:

$  MatchQ[x + y, x + y + c___]

$  True

$  MatchQ[x, x + c___]

$  False

$  Actually there is nothing surprising here.

The issue really is, if you were writing a pattern for the concept of
"linear in x", you might write a pattern a_*x+b_, which doesn't work
too well. Then a_.*x+b___ might occur to you. No good.
Possibly a_.*x+b___:0 which works, at which point you stop.
  You might try a_.x+b_. which also works,
  but you might not try it since you already have something
that works.

As I have said before, you cannot be the judge of whether something
is puzzling to another person.  After all, "why is the sky blue"
is puzzling to some people.

$ The first match
$  works because of the Flat and OneIdentity attributes of Plus
$  cause Plus[x,y] to be rewritten as Plus[x,y,Plus[]] so that
$  now the pattern Plus[x,y,c___] and the answer is:

$  x + y /. x + y + c___ :> aha[c]

$  aha()

$  Mathematically this does "match" does not make sense

How can you say that it does not make sense?  It makes perfect sense
in that it is the result of the program running on the computer.
Even bugs make sense in that respect.  If I am relying on the
computer program running in a certain way, then it makes sense
for me to use it that way.  And frankly, I find this match
entirely understandable:  x is matched to x, y is matched to y, and
c is matched to the remaining sequence, which is now empty.
Anyone writing a pattern matcher has to deal with patterns of
the form  expression+ c___  as either
(a) something to match
(b) an error condition to deal with somehow.

So the implemented behavior is choice (a).


$ but then
$  nobody wanting to make sense would use a BlankNullSequence in
$  this situation: it is an artificial examples made up purely
$  to cause puzzlement and an appearance of something like a
$  "bug". In the case

$  x /. x + c___ :> aha[c]

$  x

$  one gets a different outcome because no match is found, but
$  there is nothing at all surprising here since the function
$  Plus with its attributes is not explicitly involved and one
$  would not expect Mathematica to replace all instances of
$  single symbols by Plus[x] in order to make a match.

Of course Mathematica would not have to use your proposed mechanism
to make this match. Indeed, I doubt that it uses your proposed
mechanism of rewriting as Plus[x,y,Plus[]], either.  But one does
not have to replace "all instances of single symbols by Plus[x].
Only when trying to match against a pattern that looks like Plus[...].

This might not work so well for the Mathematica evaluator, but when
a user explicitly offers a rule, it makes sense to try to match
that rule even at a somewhat higher cost.


$ In fact,
$  by using an explicit Plus (with Unevaluated) we get the
$  expected behaviour:

$  Unevaluated[Plus[x]] /. x + c___ :> aba[c]

$   aba()

Oh, that really solves the problem!

$   Every single one of the examples given below is logical and
$   easily predictable.

Even better, one can run the program and see what happens. That
makes it unnecessary to predict anything.

$ This is not to say that it "could not be
$   different" (this is the kind of claim that nobody here ever
$   makes except perhaps in Richard's imagination, which of
$   course provides him with another excuse for providing more
$   jolly news about Lisp and the existence of other CAS systems
$   that do things in a different way, etc...) but that it is
$   all intentional and consistent. Whether it is better or
$   worse than other approaches is essentially a matter of taste
$   and, I am glad to observe, my taste rarely agrees with
$   Richard's.

Ok, here's why I tried c___, seeing the construction c_.  (or
in this example, b_., fail. Desperation? Flailing?)

Construct a test to see if an expression is a quadratic in a
given variable.

quadp[a_. x_^2+ b_. x_+c_., x_]:= qq[c,b,a] /; FreeQ[{a,b,c},x]

for example,
quadp[5+4*x +3*x^2,x]  produces qq[5,4,3].
quadp[  4*x +3*x^2,x]  produces qq[0,4,3].
quadp[    x +  x^2,x]  produces qq[0,1,1].

quadp[5     +3*x^2,x]  no match  oops.

Now, using 2 rules seems to help:
quadp[a_. x_^2+ b_. x_+c_., x_]:= qq[c,b,a] /; FreeQ[{a,b,c},x]
quadp[a_. x_^2        +c_., x_]:= qq[c,0,a] /; FreeQ[{a,c},x]

Now this pattern collection also fails, e.g. for  r*x^2+s*x^2+1  which 
most people would think is a quadratic.  (I tried various other
tricks like Alternatives, to get everything into one neat rule,
but decided the 2 rules were probably better.  I'm open to suggestions
of neater patterns.

Here is a better program. Something like

quadp=Function[{ex,var}, Module[{ans=CoefficientList[ex,var]},
   If [Length[ans]==3 && FreeQ[ans,var],  Apply[qq,ans], notqq[ex]]]]

It also works for r*x^2+s*x^2.
RJF





$   Andrzej Kozlowski




  • Prev by Date: Re: pattern bugs and comment on intuitive syntax for the New Year
  • Next by Date: Re: NDSolve, three 2-d order ODE, 6 initial conditions
  • Previous by thread: Re: pattern bugs and comment on intuitive syntax for the New Year
  • Next by thread: Re: pattern bugs and comment on intuitive syntax for the New Year