Services & Resources / Wolfram Forums / MathGroup Archive
-----

MathGroup Archive 2010

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

Search the Archive

Re: Programmatically creating functions of many variables

  • To: mathgroup at smc.vnet.net
  • Subject: [mg113683] Re: Programmatically creating functions of many variables
  • From: Leonid Shifrin <lshifr at gmail.com>
  • Date: Sun, 7 Nov 2010 05:13:07 -0500 (EST)

Hi Yaroslav,

Unfortunately I don't quite follow the specific problem you stated - if you
start
with an adjacency matrix, I don't quite see how you can get improper
labeling -
if you have ones on the diagonal that would just mean self-loops.

Regarding a general question of run-time generation of multivariate
functions,
this is rarely needed since in most such cases all arguments have similar
nature
and can then be combined into a list, so that you have a function of a
single argument
being a list. If you still want to do this, here are a few ways (I have no
idea whether
or not they are typical - these are what I use sometimes).

I will use a model problem of a function which takes any nonzero number of
integer
arguments and checks that none of them is a multiple of some fixed number.
One way to
generate such a function is to create a pattern-based definition for some
symbol
and then return that symbol:

In[1]:=
Clear[noDivisorCheck];
noDivisorCheck[n_Integer] :=
 Module[{checkF},
  checkF[args__Integer] := And @@ Thread[Mod[{args}, n] != 0];
  checkF]

In[3]:= fn = noDivisorCheck[5]

Out[3]= checkF$110

In[4]:= fn[1, 2, 3, 4]


Out[4]= True

In[5]:= fn[1, 2, 3, 4, 5]


Out[5]= False

You can also do this using a pure function, but then we have to use the
undocumented
form Function[Null, body], which can accept any number of arguments:

In[6]:=
Clear[noDivisorCheckPF];
noDivisorCheckPF[n_Integer] :=
  Function[Null, And @@ Thread[Mod[{##}, n] != 0]];

In[8]:= fnPF = noDivisorCheckPF[5]

Out[8]= Function[Null, And @@ Thread[Mod[{##1}, 5] != 0]]

In[9]:= fnPF [1, 2, 3, 4]

Out[9]= True

In[10]:= fnPF [1, 2, 3, 4, 5]

Out[10]= False

Note that these two methods have a couple of subtle differences in the way
they work.
One of them is that if you copiously produce functions with the first
method, these symbols are not garbage-collected unless you explicitly Remove
them,
so you may eventually produce a lot of garbage in your working context. This
problem
does not exist for pure functions.

If you know the number of arguments at the moment when you create a
function,
and it will be fixed, you can do something similar to what you suggested
(can not
use subscripts though):

In[11]:=
Clear[noDivisorCheckPFFixedArgNum]
noDivisorCheckPFFixedArgNum[n_Integer, argnum_Integer?Positive] :=
 Block[{x},
  With[{args  = ToExpression["x" <> ToString@#] & /@ Range[argnum]},
   Function @@ Hold[args, And @@ Thread[Mod[args, n] != 0]]]]

Block[{x},...] was used to make sure that we don't capture any global value
that <x>
may have, at the moment when we create our function (This could have been
accomplished
also by using Hold wrappers on the individual x variables, but that would be
more code).
Hold was used to prevent the premature evaluation of the body of the
function.

In[13]:= fn4 = noDivisorCheckPFFixedArgNum[5, 4]

Out[13]= Function[{x1, x2, x3, x4},
 And @@ Thread[Mod[{x1, x2, x3, x4}, 5] != 0]]

In[14]:= fn4[1, 2, 3, 4]

Out[14]= True

In this method, however, we have to create a new function for a
different number of arguments, so it is less flexible in that sense:


In[15]:= fn5 = noDivisorCheckPFFixedArgNum[5, 5]

Out[15]= Function[{x1, x2, x3, x4, x5},
 And @@ Thread[Mod[{x1, x2, x3, x4, x5}, 5] != 0]]

In[16]:= fn5[1, 2, 3, 4, 5]

Out[16]= False

Hope this helps.

Regards,
Leonid



On Sat, Nov 6, 2010 at 1:01 PM, Yaroslav Bulatov <yaroslavvb at gmail.com>wrote:

> Suppose I have a graph, and I'd like to create a function which checks
> whether given assignment of nodes is a proper labeling -- ie, no two
> adjacent nodes get the same number. One could do something like the
> following, but that gives Part warnings. Is there a preferred
> approach?
>
> graph = GraphData[{"Grid", {2, 2}}, "AdjacencyMatrix"] // Normal;
> f = Function @@ {{x}, And @@ (x[[First[#]]] != x[[Last[#]]] & /@
> Position[graph, 1])}
>
> This is actually a problem that I periodically come across. Part
> approach causes warnings meanwhile something like Function @@
> {Subscript[x,#]&/@Range[n], ...} doesn't work. What are typical ways
> of generating multivariate functions automatically?
>
> ----
> Yaroslav
> http://stackoverflow.com/users/419116/yaroslav-bulatov
>
>



  • Prev by Date: Re: MathOO: Adding Object Orientation to Mathematica
  • Next by Date: Re: Balance point of a solid
  • Previous by thread: Programmatically creating functions of many variables
  • Next by thread: FFT in mathematica