Re: Re: Re: Define an antisymmetric function
- To: mathgroup at smc.vnet.net
- Subject: [mg107451] Re: [mg107444] Re: [mg107402] Re: Define an antisymmetric function
- From: "Carl K. Woll" <carlw at wolfram.com>
- Date: Sat, 13 Feb 2010 05:21:30 -0500 (EST)
- References: <hl0r36$uu$1@smc.vnet.net> <201002111307.IAA03558@smc.vnet.net> <201002120946.EAA15000@smc.vnet.net>
Another alternative is: G[a, b] := f[a, b] G[a, c] := g[a, c] G[b, c] := h[b, c] G[a_, b_] /; Signature[{a, b}] == -1 := -G[b, a] It requires that you give literal definitions for the signature 1 ordering of arguments. Carl Woll Wolfram Research On 2/12/2010 4:46 AM, Leonid Shifrin wrote: > 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 >> >> >> >
- References:
- Re: Define an antisymmetric function
- From: Szabolcs Horvát <szhorvat@gmail.com>
- Re: Re: Define an antisymmetric function
- From: Leonid Shifrin <lshifr@gmail.com>
- Re: Define an antisymmetric function