1

Recently I decided to take on the challenge of evolutionary programming, and following the problem posted at Rosetta Code, which says that given a target string, mutate a randomly generated string until it matches the target. I've managed to do the mutations just fine, but I'm getting the wrong value for my fitness function, but I have no idea why. My fitness function is:

int
closeness (char* string, char* target, int n)
{
  int fit = 0, i, j;

  if (n == 0) return 0;

  if (!strcmp (string, target)) return 99999999; //if strings match, no need to iterate

    for (i = n - 1; i > 0; i--)
      {
        if ((string[i] == target[i])) fit++; //fit gets increased by each matching letter.
      }

  return fit;

And, for not cluttering the whole post, here's the full code (Pastebin).
Any Help is appreciated guys.

Sample output (for target string "methinks"):

best match: ecskyzfjh in generation 1, specimen 0 with fitness 0
best match: ecsuyzfjh in generation 2, specimen 0 with fitness 0
best match: ecsuyzfjh in generation 3, specimen 0 with fitness 0
best match: vc uyzfjh in generation 4, specimen 0 with fitness 0
best match: vc uyzfjh in generation 5, specimen 0 with fitness 0
best match: ve uyzfjh in generation 6, specimen 4 with fitness 1
best match: ve lyzfjh in generation 7, specimen 4 with fitness 1
best match: ve lyzfjh in generation 8, specimen 4 with fitness 1
best match: ve lyzfjh in generation 9, specimen 4 with fitness 1
best match: ve lyzfjh in generation 10, specimen 4 with fitness 1
best match: vg lyzfjh in generation 11, specimen 4 with fitness 1
best match: vgalyzfjh in generation 12, specimen 4 with fitness 1
best match: vgalyzfjh in generation 13, specimen 4 with fitness 1
best match: vgalyzfjh in generation 14, specimen 4 with fitness 1
best match: ugalyzfjh in generation 15, specimen 4 with fitness 1
best match: ugalyzrjh in generation 16, specimen 4 with fitness 1
best match: ugalyhtjh in generation 17, specimen 4 with fitness 1
best match: ugalyhtjh in generation 18, specimen 4 with fitness 1
best match: ugalyhtjh in generation 19, specimen 4 with fitness 1
best match: ugalyhtjz in generation 20, specimen 4 with fitness 1
best match: ugalyhtjz in generation 21, specimen 4 with fitness 1
best match: ugalyht l in generation 22, specimen 4 with fitness 1
best match: ugalyht l in generation 23, specimen 4 with fitness 1
best match: ugalyht l in generation 24, specimen 4 with fitness 1
best match:  galyyt l in generation 25, specimen 4 with fitness 1
best match:  galyyt l in generation 26, specimen 4 with fitness 1
best match:  yalyyt l in generation 27, specimen 4 with fitness 1
best match:  yalyytil in generation 28, specimen 4 with fitness 1
best match:  yalqytil in generation 29, specimen 4 with fitness 1
best match: pyajqytil in generation 30, specimen 4 with fitness 1
best match: pyajqytil in generation 31, specimen 4 with fitness 1
best match: pyajqytio in generation 32, specimen 4 with fitness 1
best match: pyajqytio in generation 33, specimen 4 with fitness 1
best match: pyazqytio in generation 34, specimen 4 with fitness 1
best match: pyazqytio in generation 35, specimen 4 with fitness 1
best match: pyazqytio in generation 36, specimen 4 with fitness 1
best match: pyazqptio in generation 37, specimen 4 with fitness 1
best match: pyazoztuo in generation 38, specimen 4 with fitness 1
best match: pyazoztuo in generation 39, specimen 4 with fitness 1
best match: pyazoztux in generation 40, specimen 4 with fitness 1
best match: hyazont x in generation 41, specimen 4 with fitness 1
best match: hyazont y in generation 42, specimen 4 with fitness 1
best match: hyazontay in generation 43, specimen 4 with fitness 1
best match: hyuzoltay in generation 44, specimen 4 with fitness 1
best match: hyuyoltay in generation 45, specimen 4 with fitness 1
best match: hyuyoltay in generation 46, specimen 4 with fitness 1
best match: hyuyoltay in generation 47, specimen 4 with fitness 1
best match: hvuyoltay in generation 48, specimen 4 with fitness 1
best match: hvuyoltay in generation 49, specimen 4 with fitness 1
best match: hvlyoltly in generation 50, specimen 4 with fitness 1
best match: hvlyoltly in generation 51, specimen 4 with fitness 1
best match: hvlynltlv in generation 52, specimen 4 with fitness 1
best match: hvlynltlv in generation 53, specimen 4 with fitness 1
best match: hvlynltlv in generation 54, specimen 4 with fitness 1
best match: hvlexltxv in generation 55, specimen 4 with fitness 1
best match: hvlexltev in generation 56, specimen 4 with fitness 1
best match: hvlexltev in generation 57, specimen 4 with fitness 1
best match: hvlexltev in generation 58, specimen 4 with fitness 1
best match: lvlexltev in generation 59, specimen 4 with fitness 1
best match: lvlexltem in generation 60, specimen 4 with fitness 1
best match: lvlexltem in generation 61, specimen 4 with fitness 1
best match: lqlexlpem in generation 62, specimen 4 with fitness 1
best match: lqlexdpem in generation 63, specimen 4 with fitness 1
best match: lylaxdpem in generation 64, specimen 4 with fitness 1
best match: lylaxdqem in generation 65, specimen 4 with fitness 1
best match: lylsxdqxm in generation 66, specimen 4 with fitness 1
best match: lylsidqxm in generation 67, specimen 4 with fitness 1
best match:  in generation 68, specimen 4 with fitness 1
best match:  in generation 69, specimen 4 with fitness 1
best match:  in generation 70, specimen 4 with fitness 1
best match:  in generation 71, specimen 4 with fitness 1
best match:  in generation 72, specimen 4 with fitness 1
best match: ynldqxq q in generation 73, specimen 4 with fitness 1
best match: ynhdqxq q in generation 74, specimen 4 with fitness 1
best match: znhdqxqkq in generation 75, specimen 4 with fitness 1
best match: znhdqxqqq in generation 76, specimen 4 with fitness 1
best match: znbdqxqqq in generation 77, specimen 4 with fitness 1
best match: znbjqxqqq in generation 78, specimen 4 with fitness 1
best match: zbbjqxqqq in generation 79, specimen 4 with fitness 1
best match: zbbjqxqpq in generation 80, specimen 4 with fitness 1
best match: zbbjqxqpq in generation 81, specimen 4 with fitness 1
best match:  bbjqxqpq in generation 82, specimen 4 with fitness 1
best match:  bbjqxqpq in generation 83, specimen 4 with fitness 1
best match:  bbjqxlpq in generation 84, specimen 4 with fitness 1
best match:  brjqxaaq in generation 85, specimen 4 with fitness 1
best match:  brjqxaaq in generation 86, specimen 4 with fitness 1
best match:  prfqmaaq in generation 87, specimen 4 with fitness 1
best match: xprfqmaaq in generation 88, specimen 4 with fitness 1
best match: xprfrzaad in generation 89, specimen 4 with fitness 1
best match: xpzfrxaad in generation 90, specimen 4 with fitness 1
best match: xpefrxaad in generation 91, specimen 4 with fitness 1
best match: xgefrxaad in generation 92, specimen 4 with fitness 1
best match: xgefruaod in generation 93, specimen 4 with fitness 1
best match: dgefruaod in generation 94, specimen 4 with fitness 1
best match: dgefruaod in generation 95, specimen 4 with fitness 1
best match: dge in generation 96, specimen 4 with fitness 1
best match:  in generation 97, specimen 4 with fitness 1
best match:  in generation 98, specimen 4 with fitness 1
best match:  in generation 99, specimen 4 with fitness 1
best match:  in generation 100, specimen 4 with fitness 1

The expected fitness for most of them would be 0.

Pedro
  • 333
  • 1
  • 5
  • 24
  • Specify sample input, what fitness value you expect, and what fitness value you actually get. – Eric J. Jul 22 '15 at 02:33
  • I can't because the function is inside a loop that iterates until the matched string is the same as the original string. – Pedro Jul 22 '15 at 02:42
  • So you cannot use printf to print it out as it changes and you can also not use the debugger? – Cobusve Jul 22 '15 at 02:58
  • I tought he meant like an written thing. I'll post the sample output – Pedro Jul 22 '15 at 03:04
  • Using `n` and `strcmp()` is suspicious. Why is `n` needed? Is code generating null characters in the randomly generated string? – chux - Reinstate Monica Jul 22 '15 at 03:18
  • n is needed to make sure I do not exceed the string size, also to make sure that the mutation position is withing the string range. The code does not generate null characters, only the ones within the set = "abcdefghijklmnopqrstuvwxyz " (thats a space in the end) – Pedro Jul 22 '15 at 03:23
  • Try changing your loop to: for (i=n; i--;) – Pynchia Jul 22 '15 at 04:21
  • @Pynchia this didn't work. I'm still getting the same false fitness values. – Pedro Jul 22 '15 at 04:27
  • Ok. Just be aware your loop was not considering the first char (index zero) – Pynchia Jul 22 '15 at 04:30
  • @Pynchia Thank you very much, I wasn't aware of that. I might keep the simulation going overnight, to see if there's any improvements. – Pedro Jul 22 '15 at 04:54
  • Nah. Print the strings and fit within the loop and see what happens on each cycle – Pynchia Jul 22 '15 at 04:57
  • @Pynchia i'm getting random strings that have their fitness increased seemly randomly. It's the same thing as the example output that I posted above. – Pedro Jul 22 '15 at 21:04
  • Your code has several weird/incorrect details. I do not know where the problem lies, but I can tell you it's going to be a silly one – Pynchia Jul 22 '15 at 21:32
  • @Pynchia would you mind elaborating where I went wrong? – Pedro Jul 23 '15 at 23:02
  • Why are you iterating backwards? That's just asking for confusion... I would drop the n=0 strcmp logic, and just loop from 0 to n-1 counting up matches. The n=0 case is covered because the loop will just terminate immediately. If the strings match, then you'll return n, which is the maximum - no need for a 999999 value. You can eliminate n completely by just looping until you see a null character - I assume that since you used strcmp they must be null-terminated. – Katie Aug 07 '15 at 18:08

2 Answers2

0

The call to your function is:

fitness[i] = closeness (specimen[i], target, size);

and size is:

char target[] = "methinks"; size = sizeof (target);

Every string in c ends with a char '\0', so all the string-functions know, where the strings end. If you start comparing two strings at the position sizeof(target)-1, it will compare the both '\0' first (which are equal, logically) and then compare the rest.

Furthermore I would change the loop to:

for (i = n - 1; i >= 0; i--)

Otherwise, the first character won't be compared.

Let me know, if this fixed your problem. ;)

dubi
  • 11
  • 3
0

Here's a quick implementation of what I mentioned in my comment above. It eliminates the special-case checks, because the loop takes care of it anyways. There is no need for n because your use of strcmp implies the strings are null-terminated. It doesn't check for equality and put out a magic value, because you already know that an exact match will return the maximum value.

The only potential bug introduced I can think of is if you don't null-terminate strings in cases where you passed n=0 before - this doesn't have a chance to bail out. But if your empty strings start with a null then it is safe.

Beware, I haven't actually tried to compile or test the code.

int closeness(char* string, char* target)
{
    int fit = 0;
    int index = 0;
    while(string[index] && target[index])
    {
        if(string[index] == target[index])
            fit++;
        index++;
    }
    return fit;
}
Katie
  • 1,260
  • 10
  • 20