Re: Compile function and AppendTo for lists (vrs. 8.0.4)
- To: mathgroup at smc.vnet.net
- Subject: [mg124592] Re: Compile function and AppendTo for lists (vrs. 8.0.4)
- From: "Oleksandr Rasputinov" <oleksandr_rasputinov at hmamail.com>
- Date: Wed, 25 Jan 2012 07:11:11 -0500 (EST)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- References: <jflvt0$jpr$1@smc.vnet.net>
On Tue, 24 Jan 2012 10:07:28 -0000, kris <kristophs.post at web.de> wrote: > Hi > > I have some trouble with my code and would like ask for your help. In > general it is about appending data in form of a list to an existing > list in a compiled function. As far as I understand Mathematica is not > supporting what I am asking for. In order to understand the problem in > more detail I present some "toy" code below. > > test=Compile[{{k,_Integer}}, > Module[{mat={}}, > For[i=1,i<=k,i++, > AppendTo[mat,{1,i}]; > ]; > mat > ] > ]; > > test[2] > (*which produces an error*) > > Appending data in form of numbers for example works just fine but not > with lists. Can anybody explain why Mathematica does not support > appending lists to lists for compiled function? As an alternative I > tried Reap and Sow, which also produces an error. > Mathematica does support what you're trying to do, but you've run into what I would consider a weak point of the compiler: it's difficult to specify variables of tensor types without using tricks. The following works: test = Compile[{{k, _Integer, 0}}, Module[{mat = {{0, 0}}, i = 0}, For[i = 1, i <= k, i++, AppendTo[mat, {1, i}]]; Rest[mat] ] ]; In := test[2] Out = {{1, 1}, {1, 2}} The trick here is that mat's type (a rank-2 integer tensor) must be specified, otherwise Mathematica infers it to be a scalar (and in Mathematica 8 an integer, but in previous versions, a real number). To do this properly you must assign it a suitable value initially, which in this case is {{0, 0}}. Also, you didn't specify that i is local to the compiled function or an integer scalar, nor that k is a scalar, so I added these specifications as well. As a point of note, in Mathematica 8, you can define types using e.g. Most[{{0, 0}}], which creates an empty rank-2 integer tensor (well, strictly speaking, it creates a rank-2 integer tensor consisting of {{0, 0}} and then clears it), but in previous versions it is apparently not possible to clear variables like this without also losing the type information, hence the need to return Rest[mat] above if you want your code to work in older versions of Mathematica and without a spurious {0, 0} prefixed to the list of results. Additionally, Sow and Reap cannot be compiled, and anything that seems to indicate they can be is just an illusion. It would certainly be nice if they could be, given that AppendTo is an O(N^2) operation whereas Sow is O(1) on average (I think). What can be compiled are the functions used internally to implement Sow and Reap (Internal`Bag, Internal`StuffBag, Internal`BagPart), although these are undocumented and complicate matters by introducing yet more types. However, I shan't discuss these further for the time being as I'm not sure whether the compiler supports bags of tensor type and don't have time right now to investigate. > However, what seems funny is the following code: > > mat={}; > test=Compile[{{k,_Integer}}, > For[i=1,i<=k,i++, > AppendTo[mat,{1,i}]; > ]; > ]; > > test[2];mat > > The above code produces the result that I was looking for in a > cumbersome way. I would like to prefer compile code which produces the > same result without calling the list mat again. > This code only works because it is not compiled in any meaningful way (and therefore it will gain none of the performance one usually desires when compiling code). The compiled code is calling out to the interpreter to perform the necessary operations.