3
$\begingroup$

I have an array of 10000 elements. I want to randomly assign energy to these 10000 elements using Gaussian or Exponential distribution, such that each time a particular element is selected its energy should also be shown in the output. Can anyone suggest me how to solve this problem?

Let's say, I have 10 elements in the array {8,4,6,2,9,0,5,1,7,3} and I am assigning energy to these 10 elements randomly. After that I am selecting one of the element in the array, say 7, when I select this number I also want to know the energy that number possesses.

This is the program I wrote to generate 1000 elements.

l = 0;
For[i = 0, i < 10, i++,
 For[j = 0, j < 10, j++,
  For[k = 0, k < 10, k++,
   Xarray[l] = A[i, j, k];
   Print[Xarray[l]];
   l++;
   ]
  ]
 ]
Xarray[5]

When Xarray[5] is given it will show the coordinate it possesses. In addition to this I want to know the energy when I am giving Xarray[5], Xarray[998], etc.

$\endgroup$
6
  • 1
    $\begingroup$ Can you give a small example of what you want to see (say, for a ten-element array)? $\endgroup$ Commented Jul 5, 2012 at 9:59
  • 1
    $\begingroup$ Daniel, if you will register you account it will be easier for you to edit your questions, post comments, etc. $\endgroup$
    – Mr.Wizard
    Commented Jul 5, 2012 at 10:26
  • 2
    $\begingroup$ Daniel, I see that you have already registered an account; I merged the temporary ones with this one. You should sign in before posting or editing. $\endgroup$
    – Mr.Wizard
    Commented Jul 5, 2012 at 10:30
  • 1
    $\begingroup$ You definitely don't need that For loop. Xarray=A @@@ Tuples[Range[0, 9], 3] will do just as well, and it's much, much faster to type and to evaluate. $\endgroup$
    – Verbeia
    Commented Jul 5, 2012 at 10:43
  • $\begingroup$ Verbeia, Thanks for your wonderful suggestion. I have one doubt, In for loop program if I type Xarray[5], it will show the coordinates. How about this in your suggestion. $\endgroup$
    – Daniel
    Commented Jul 5, 2012 at 10:49

5 Answers 5

1
$\begingroup$

I am adding this as another answer to address some specific issues raised in comments.

First, it is almost always true that "if you are using a For loop in Mathematica, you are doing it wrong". So here is a simpler and faster way to create your array.

Xarray = A @@@ Tuples[Range[0, 9], 3];

You can then write:

energies = 
  RandomVariate[ExponentialDistribution[1.5], {Length@Xarray}];

Now, here is a very simple function that returns an element from Xarray and the matching element from energies. Notice the use of Pick and the pure function using Slot (#) notation.

f = {#, First@Pick[energies, Xarray, #]} &

If you know which element you want to get the element-energy pair for, you would do this:

f@A[0, 0, 4]

(*{A[0, 0, 4], 1.00466}*)

If you just wanted the fifth element, without knowing in advance what it was, you would instead evaluate:

f@Xarray[[5]]

(*{A[0, 0, 4], 1.00466}*)
$\endgroup$
4
  • $\begingroup$ Thank You so much for your kindness in answering my question. $\endgroup$
    – Daniel
    Commented Jul 5, 2012 at 11:51
  • $\begingroup$ Verbeia, I am new To the programming field. As per your program, energies are assigned to each elements in the array. Now I want to randomly select let say 5 elements from this 1000 element array randomly such that no element should repeat. let { 89,5,79,34,900} be the elements I randomly selected.Now for each element I should get the energies and coordinates automatically. Could you do this. $\endgroup$
    – Daniel
    Commented Jul 5, 2012 at 12:08
  • 1
    $\begingroup$ yes, but please ask this is a separate question. $\endgroup$
    – Verbeia
    Commented Jul 5, 2012 at 12:09
  • $\begingroup$ @Daniel Perhaps it's time to read a Mathematica tutorial? $\endgroup$
    – Ajasja
    Commented Jul 5, 2012 at 12:11
4
$\begingroup$

Does this simple element-energy pairing solve your problem?

n = 50;
array = Table[i, {i, n}];
energy = RandomVariate[NormalDistribution[0, 1], {n}];

coupled = Thread@{array, energy}; (* this returns a list where each member is an {element, energy} pair *)
TableForm@coupled

Mathematica graphics

$\endgroup$
1
  • $\begingroup$ I'd use Thread[array -> energy] myself. (+1) $\endgroup$
    – Mr.Wizard
    Commented Jul 5, 2012 at 10:20
4
$\begingroup$

Perhaps something like this is what you are looking for?

Suppose you have an array of objects. I have used the Array function here, but the contents of this array could be anything.

elements = Array[a, {10}]

(*{a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10]}*)

Create a separate vector of energies. Since István has already shown the NormalDistribution, I'll use ExponentialDistribution.

energies = RandomVariate[ExponentialDistribution[1.5], {10}]

(*{0.0969302, 0.335765, 0.564123, 1.51769, 0.142579, 0.222407, \
0.842437, 1.35341, 0.239727, 0.0312016}*)

Now consider a function like this, which takes the index of the element and returns both the element and the associated energy. Notice that I have specified that n has to be a positive integer, because indices of lists are always positive integers, and that it must also be less than the total length of the elements list.

getElement[n_Integer?Positive] /; 
  n <= Length[elements] := {elements[[n]], energies[[n]]}

getElement[4]

(*{a[4], 1.51769}*)

Because 20 is greater than the current length of elements, getElement[20] is undefined and returns itself unchanged.

getElement[20]

(* getElement[20] *)

But if you go back and redefine elements (and energies) to be longer, then re-evaluating getElement[20] will return the 20th element-energy pair.

You could of course include some other checks to make sure that energies is always the same length as elements, but this should be enough to get you started.

EDIT

Based on your edit, it is possible that this is more appropriate. This function works out the position of the element in a particular vector, and returns that element and the matching element from the energies vector.

getEnergyByElement[elem_, vec_?VectorQ] := 
 With[{n = Position[vec, elem][[1, 1]]}, {vec[[n]], energies[[n]]}]

getEnergyByElement[a[4], elements]
(* {a[4], 1.51769} *)

An even simpler way is

{#, First@Pick[energies, elements, #]} &@a[5]

(*{a[5], 0.142579} *)
$\endgroup$
2
  • $\begingroup$ Thanks Verbeia, for your wonderful suggestion. I have one doubt, In for loop program if I type Xarray[5], it will show the coordinates. How about this in your suggestion.Please help me. $\endgroup$
    – Daniel
    Commented Jul 5, 2012 at 10:58
  • $\begingroup$ Thank You Verbeia. Your model Suits to my program. $\endgroup$
    – Daniel
    Commented Jul 5, 2012 at 11:13
1
$\begingroup$

How about this approach which drops the need for extra storage to hold the paired values:

   elements = {8, 4, 6, 2, 9, 0, 5, 1, 7, 3};
   energy = RandomReal[NormalDistribution[0, 1], Length@elements];

Then you can have:

energy[[elements]]

{-0.318708, 1.18351, -0.281984, -0.94776, -1.3151, -1.00745, 1.2463, \ -1.01972, -0.572084, 1.81867}

And:

 energy[[7]]

1.2463

And with an extra function show you can display both element and energy value:

show = With[{p = First@Position[elements, #]}, {#, energy[[p]]}] &

Giving:

show@7

{7,{1,2463}}

and:

show /@ {2, 7, 9}

{{2, 1.18351}, {7, 1.2463}, {9, -0.572084}}

If you want to use the array of elements to indirectly access the energies then you can define a function retrieve:

retrieve = With[{p = First@Position[elements, #]}, {#, energy[[p]]}] &

will lead to:

retrieve /@ {2, 7, 9}

{{4, -0.94776}, {5, -1.3151}, {7, 1.2463}}

Then the following code will show all the elements and their associated energies:

retrieve /@ elements

{{8, {-0.318708}}, {4, {1.18351}}, {6, {-0.281984}}, {2, {-0.94776}}, \ {9, {-1.3151}}, {0, {-1.00745}}, {5, {1.2463}}, {1, {-1.01972}}, {7, \ {-0.572084}}, {3, {1.81867}}}

$\endgroup$
1
$\begingroup$

I guess I'll show the Rule variation I alluded to in a comment.

keys = {8, 4, 6, 2, 9, 0, 5, 1, 7, 3};

vals = RandomReal[NormalDistribution[0, 1], Length@elements]

rules= Dispatch@Thread[keys -> vals];

{7, 7 /. rules}
{7, 0.698481}
{1, 2, 3} /. rules
{0.144972, -0.757016, -1.02032}
rules[[1, 3]]
6 -> 1.49672

In the last example the [[1, 3]] is required rather than [[3]] because I converted to rules into a Dispatch table for speed; this is needed to access the raw rules.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.