matrices with arbitrary dimensionality

0 visualizzazioni
Passa al primo messaggio da leggere

alexxx...@gmail.com

da leggere,
25 mag 2007, 06:38:0125/05/07
a
Hi there,
with V.6.0 I keep on with my experiment in translating a large C++
spin simulation program.

What I'm bouncing my head against today is the following:

there is a way in M to describe objects (matrices) having an arbitrary
number of dimensions, defined just at runtime?

In detail, I work on an orthogonal lattice where my spins are defined,
but the simulations require sometimes to deal with 1d (arrays),
sometimes more.

Yet I'd like to write the most general code it is possible, e.g. when
writing a procedure that - given a location in the lattice at the
coordinates {i,j,...} - returns a list of locations of the nearest
neighbors
(in 1d: {{i-1},{i+1}}; in 2d: {{i-1,j},{i+1,j},{i,j-1},{i,j+1}} and so
on...)

thanks for any hint...

Alessandro Magni

Sseziwa Mukasa

da leggere,
26 mag 2007, 04:36:3326/05/07
a

How's this?

In[11]:=
neighbors[pnt_]:=
Table[pnt+Table[d[i],{i,Length[pnt]}],
Evaluate[Sequence@@Table[{d[i],-1,1,2},{i,Length[pnt]}]]]
neighbors[{i,j}]
Out[12]=
{{{-1+i,-1+j},{-1+i,1+j}},{{1+i,-1+j},{1+i,1+j}}}

You have to specify 1D points as {i} but you could do

neighbors[pnt_List]:=
Table[pnt+Table[d[i],{i,Length[pnt]}],
Evaluate[Sequence@@Table[{d[i],-1,1,2},{i,Length[pnt]}]]]
neighbors[pnt_?SymbolQ]:=neighbors[{pnt}]

or

neighbors[pnt_?AtomQ]:=neighbors[{pnt}]

or something like that as suits your needs.

Regards,

Ssezi

David Bailey

da leggere,
26 mag 2007, 04:41:3726/05/07
a
I suppose you could write code in which the low level
dimension-dependent operations are overloaded:

Nearestpoints[x_ /; ArrayDepth[x] == 1] := ...

Nearestpoints[x_ /; ArrayDepth[x] == 2] := ...

Nearestpoints[x_ /; ArrayDepth[x] == 3] := ...

However, I would be a little cautious before changing your code to this
or any other scheme, because I suspect it will be critical to ensure
that your code operates as fast as possible. The speed of Mathematica
code can vary in some fairly subtle ways - so time any change before you
decide to adopt it!

Also, if you intend to use the Compile function for production use, use
it for this test - you don't want any unpleasant surprises just at the
end of your project as you start to scale up to serious examples!

David Bailey
http://www.dbaileyconsultancy.co.uk

Ray Koopman

da leggere,
26 mag 2007, 05:13:0926/05/07
a
On May 25, 3:38 am, "alexxx.ma...@gmail.com" <alexxx.ma...@gmail.com>
wrote:

neighbors[v_List?VectorQ] := Flatten[{v-#,v+#}& /@
IdentityMatrix@Length@v,1]
neighbors[{x,y,z}]

{{-1+x,y,z},
{1+x,y,z},
{x,-1+y,z},
{x,1+y,z},
{x,y,-1+z},
{x,y,1+z}}

alexxx...@gmail.com

da leggere,
30 mag 2007, 05:18:5130/05/07
a
Thanks everybody.
I solved in the following way - with your help - my needs concerning
arbitrary dimension matrices.

Here I generate it, with dim dimensions, and hypercube lateral size =
lspins:

generateArbMat[dim_, lspins_] := Module[{ind},
ind = Map[{#, lspins} & ,
Map[Unique, Map[FromCharacterCode, 64 + Range[dim]]]];
Apply[Table[0, ##] &, ind]
]

In[301]:= generateArbMat[4, 2]
Dimensions[%]

Out[301]= {{{{0, 0}, {0, 0}}, {{0, 0}, {0, 0}}}, {{{0, 0}, {0,
0}}, {{0, 0}, {0, 0}}}}
Out[302]= {2, 2, 2, 2}

Here is the code for the next neighbors (thank you Ray!), adapted for
periodic boundary conditions:

neighbors[v_List?VectorQ] := Module[{a},
a = Flatten[{v - #, v + #} & /@ IdentityMatrix[Length[v]], 1];
a = a /. 0 -> 1; a = a /. lspins + 1 -> 1;
a
]

Here is the function giving the array of all the matrix indices:

locations[] := Distribute[Table[Range[lspins], {dim}], List]

In[307]:= locations[] (* dim=2 and lspins=4 *)

Out[307]= {{1, 1, 1}, {1, 1, 2}, {1, 1, 3}, {1, 2, 1}, {1, 2, 2}, {1,
2, 3}, {1, 3, 1}, {1, 3, 2}, {1, 3, 3}, {2, 1, 1}, {2, 1, 2}, {2, 1,
3}, {2, 2, 1}, {2, 2, 2}, {2, 2, 3}, {2, 3, 1}, {2, 3, 2}, {2, 3,
3}, {3, 1, 1}, {3, 1, 2}, {3, 1, 3}, {3, 2, 1}, {3, 2, 2}, {3, 2,
3}, {3, 3, 1}, {3, 3, 2}, {3, 3, 3}}

To setup the matrix values (e.g. with random values):

f = generateArbMat[d, lspins];
f = f /. 0 :> RandomReal[NormalDistribution[0., 1.]];

Last, to operate on the matrix, e.g. to sum all the f values of the
neighbors of a given location i0:

Apply[Plus, Map[Extract[f, #] &, neighbors[i0]]]

any other suggestion is welcome, thanks!

Alessandro

Rispondi a tutti
Rispondi all'autore
Inoltra
0 nuovi messaggi