0
$\begingroup$

First of all, thank you for taking the time to read this. I'm working on a portion of code related to the genetic algorithm that is not producing the expected results. What the code is supposed to do is take a list of lists with binary bits, in this case c = {{1, 0}, {1, 1}}, and change the elements within the sub-lists to either ones or zeros depending on what's given. So, in the case of the list c, when fed into the code, it should yield {{0,1}, {0,0}}. So I created a code involving two nested For loops. After some testing, I've come to realize it's only changing the first element in c ({1, 0}), but not the second ({1, 1}) and returns {{0, 1}, {0, 1}} instead of {{0, 1}, {0, 0}}. I've been trying for some time now to correct this, but so far I've been unsuccessful. I was hoping I could get some help here. The code is as follows:

    c = {{1, 0}, {1, 1}};
    Mutation1[c_] := Module[{d = c},
    MutatedSet = {}; (*This will be used to Append the new lists later*)

    For[i = 1, i <= Length[d], i++,

       (*This For Loop should take {1,0} AND 
       {1,1} the apply the rest of the code, but only does 
       this for the first element, {1,0}*)

       position = d[[i]];
       length = Length[position];

       For[i = 1, i <= length, i++,
          location = position[[i]];
          If[location == 0,
           Mutated = ReplacePart[position, i -> 1];
           ,
           Mutated = ReplacePart[position, i -> 0];
          ];
          position = Mutated;
        ];
       MutatedSet = Append[MutatedSet, position];
      ];
     MutatedSet = Append[MutatedSet, position];
     Print[MutatedSet];
    ];

Thanks again in advance for the help. It is very much appreciated!

$\endgroup$

closed as off-topic by Daniel Lichtblau, bbgodfrey, Dr. belisarius, Sjoerd C. de Vries, MarcoB Jun 4 '15 at 23:56

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "This question arises due to a simple mistake such as a trivial syntax error, incorrect capitalization, spelling mistake, or other typographical error and is unlikely to help any future visitors, or else it is easily found in the documentation." – Daniel Lichtblau, bbgodfrey, Dr. belisarius, Sjoerd C. de Vries, MarcoB
If this question can be reworded to fit the rules in the help center, please edit the question.

  • $\begingroup$ Welcome to Mathematica.SE! I hope you will become a regular contributor. To get started, 1) when you see good questions and answers, vote them up by clicking the gray triangles, because the credibility of the system is based on the reputation gained by users sharing their knowledge, 2) remember to accept the answer, if any, that solves your problem, by clicking the checkmark sign, and 3) give help too, by answering questions in your areas of expertise. $\endgroup$ – bbgodfrey Jun 4 '15 at 18:19
  • 6
    $\begingroup$ For does not localize the variable i, therefore when the inner For loop runs out, the condition for the outer loop also fails and evaluation ceases. $\endgroup$ – LLlAMnYP Jun 4 '15 at 18:24
5
$\begingroup$

In general, For loops are almost always unnecessary in Mathematica, but I'll address that towards the end of the answer. Don't miss the link at the end!

First of all, here are the corrections to the code keeping to your style:

Mutation1[c_] := Module[{d = c}, MutatedSet = {};

   For[i = 1, i <= Length[d], i++,

    position = d[[i]];
    length = Length[position];

    For[j = 1, j <= length, j++, location = position[[j]];
     If[location == 0, Mutated = ReplacePart[position, j -> 1];, 
      Mutated = ReplacePart[position, j -> 0];];
     position = Mutated;];

    MutatedSet = Append[MutatedSet, position];];
   Print[MutatedSet];];

You need different names for iterators in the two For loops. When you correct that, you get {{0, 1}, {0, 0}, {0, 0}} as output, because you had an extra unnecessary MutatedSet = Append... at the end of the Module.

There are still some issues with your function, however.

  • You use Module which is a nice way to localize variables, yet the only local variable for this Module is d. Upon execution it creates several global variables, namely, i, j (in my corrected example), length, position, MutatedSet, location, Mutated.
  • The function returns no output. It simply prints the value of MutatedSet as a side effect, but if you have something like f[g[Mutation1[somelist]]], it will evaluate to f[g[Null]] which is probably not useful.

Let's address these issues.

Mutation1[c_] := 
  Module[{d = c, MutatedSet = {}, i, j, length, position, location, Mutated},

   For[i = 1, i <= Length[d], i++, 

    position = d[[i]];
    length = Length[position];

    For[j = 1, j <= length, j++, location = position[[j]];
     If[location == 0, Mutated = ReplacePart[position, j -> 1];, 
      Mutated = ReplacePart[position, j -> 0];];
     position = Mutated;];

    MutatedSet = Append[MutatedSet, position];];
   MutatedSet];

Nextly, all of these extra variables that are position, length, location are way too redundant, you're creating copies of several parts of the initial list. Also, you can do all the ReplaceParts to the initial list, but even better is to reassign the relevant parts of the list. Here's a simplification of the code, staying with For loops for the time being:

Mutation1[c_] := Module[{d = c, i, j},

   For[i = 1, i <= Length[d], i++,

    For[j = 1, j <= Length[d[[i]]], j++,
      If[d[[i, j]] == 0, d[[i, j]] = 1;, d[[i, j]] = 0;];
      ];
    ];
   d];

Much simpler. Now you're using For loops to iterate over the atomic elements of a list of lists apply the If operation to each element, which directly re-Sets the value of each element, rather than creating a copy of the sublist, then redefining the sublist as a list on which ReplacePart had worked, then appending it to an empty list... (my head's spinning, trying to describe this).

Finally, the good folks at Wolfram acknowledged long ago, that working with arrays is a very common thing and creating For loops every damn time to do this is tedious (when will C and such evolve to this thinking, huh?) and gave us the Map function.

Take your If[...] function, which is what's doing all the work here and map it to your list at level 2:

Mutation1[c_] := Map[If[# == 0, 1, 0]&, c, {2}]

I leave it to other contributors to suggest a simplification to the If function, as I imagine, you might have something more complex in mind, than applying Not to a list of boolean values.

Please read up on this as well.

$\endgroup$
  • $\begingroup$ Incredible! Thank you so much! I'm not much of a programmer which I'm sure is evident. I cannot thank you enough for this! $\endgroup$ – Qwerty Jun 4 '15 at 19:33
  • $\begingroup$ This is a very nice, straightforward discussion of how to make existing code better and how to make the transition from procedural programming to Mathematica-style functional programming. +1 $\endgroup$ – march Jun 4 '15 at 21:08
  • $\begingroup$ @march Thanks. Y'know, as soon as I wrote up this answer I went to google and again started looking for queries such as "why is Map not present in C" and such. Are there any programmers in other languages around that know, why everything is done via For loops everywhere else STILL in the XXI century??? $\endgroup$ – LLlAMnYP Jun 4 '15 at 22:32

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