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 > >