MathGroup Archive 2010

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

Search the Archive

Re: Re: Define an antisymmetric function

  • To: mathgroup at smc.vnet.net
  • Subject: [mg107444] Re: [mg107402] Re: Define an antisymmetric function
  • From: Leonid Shifrin <lshifr at gmail.com>
  • Date: Fri, 12 Feb 2010 04:46:08 -0500 (EST)
  • References: <hl0r36$uu$1@smc.vnet.net> <201002111307.IAA03558@smc.vnet.net>

Hi Torsten,

here is a little more high-level variation of Szabolcs's solution, which
isn't robust either, since it assumes only Downvalue - based definitions and
that you will not add more general (pattern-based) definitions to G later
on.

ClearAll[G];
G[a, b] := f[a, b]
G[a, c] := g[a, c]
G[b, c] := h[b, c]
G[x_, y_] := -G[y, x] /;
  Hold[G[y, x]] =!= (Hold[G[y, x]] /. Most@DownValues[G])

It may however be a little faster since the specific rules (without
patterns) in DownValues are
hash-table based and therefore the rule look-up should be constant time in
the size of the definition list.

Out of curiosity, I also tried to  address a different fomulation of your
problem, where for unknown
arguments the function must use antisymmetry, but just once:
G[x,y]->-G[y,x]. The following
hack seems to do it:

In[318]:= Clear[GG];

GG[a,b]:=f[a,b]
GG[a,c]:=g[a,c]
GG[b,c]:=h[b,c]

Module[{tried, reset},
 reset[] := (Clear[tried]; tried[_, _] = False);
 reset[];
 GG[x_, y_] /; ! tried[x, y] := (tried[y, x] = True; -GG[y, x]);
 GG[x_, y_] := "" /; reset[];
 ]

In[323]:= GG[a,b]

Out[323]= f[a,b]

In[324]:= GG[b,a]

Out[324]= -f[a,b]

In[325]:= GG[d,e]

Out[325]= -GG[e,d]

In[326]:= GG[e,d]

Out[326]= -GG[d,e]

One problem with it is that it may keep some garbage in <tried> for
arguments on which
GG has been defined (a,b,c here) - it will still work but consume a little
extra memory.

Regards,
Leonid


2010/2/11 Szabolcs Horv=E1t <szhorvat at gmail.com>

> On 2010.02.11. 12:53, Torsten Schoenfeld wrote:
> > I'd like to define an antisymmetric function by giving its value on a
> > set of known objects.  I'm having trouble enforcing antisymmetry.  Say I
> > want to define G[_, _] on the objects {a, b, c}:
> >
> >     G[a, b] := f[a, b]
> >     G[a, c] := g[a, c]
> >     G[b, c] := h[b, c]
> >
> > If I now enforce antisymmetry simply by
> >
> >     G[x_, y_] := -G[y, x]
> >
> > then it mostly works (e.g., G[b, a] evaluates to -f[a, b]).  But if I
> > apply G to something that is not in {a, b, c}, then I run into an
> > infinite loop: G[a, f[b]] yields "$RecursionLimit::reclim: Recursion
> > depth of 256 exceeded."
> >
> > Ideally, I would like applications to unknown input to stay unevaluated
> > (e.g., G[a, f[b]] just yields G[a, f[b]]).  How can I achieve that while
> > also enforcing antisymmetry?
> >
>
> Hello Torsten,
>
> I do not think that it is possible to do this in a general way.  It
> might, however, be possible to make it work for the special cases that
> you need.
>
> The reason why it is not possible to implement it in a completely
> general way is this:
>
> Suppose we input G[a,b], and suppose that there is no definition
> associated with G that would allow computing the value of G[a,b].  Now
> we need to check if G[b,a] can be computed, and if so, then use the
> value -G[b,a] for G[a,b].  But how can we check if G[b,a] "can be
> computed", that is, if it evaluates to something different than itself?
>  If we aim for complete generality, this is only possible by trying to
> evaluate G[b,a], which will then trigger the antisymmetry definition
> again, and lead to infinite recursion...
>
> So, let's not aim for completely generality.  Instead, let's just check
> if an *explicit* definition exists for G[b,a] (i.e. for the explicit
> values b and a):
>
> G[x_, y_] := -G[y, x] /; hasValue[G[y,x]]
>
> hasValue[f_[args___]] :=
>  MemberQ[First /@ DownValues[f], Verbatim@HoldPattern[f[args]]]
>
> This will work for simple cases, but it is neither pretty, nor robust.
> I hope someone will post a better suggestion.
>
> One more thing that needs to be mentioned is that there is already a
> function similar to hasValue[] built into Mathematica:  ValueQ[].
> However, it cannot be used here because for non-atomic arguments
> (anything more complicated than a symbol) it determines if it has a
> value by evaluating it and checking whether it has changed.  So the
> infinite recursion still wouldn't be avoided.
>
> I hope this helps,
> Szabolcs
>
>


  • Prev by Date: char** and uuid_t type issue with DefineDLLFunction
  • Next by Date: Re: Question about subscripts and polynomial
  • Previous by thread: Re: Define an antisymmetric function
  • Next by thread: Re: Re: Re: Define an antisymmetric function