3

I'm honestly not quite sure if I've titled this question correctly, because I can't identify the issue. Also, keep in mind I still have much to learn about evolutionary algorithms, and am not a master at them by any means.

The code below is that of a simple genetic algorithm, if you even want to call it that. It's missing multiple features of a real, complete genetic algorithm, but it's simply an example for demonstration. All it does is take a string (predetermined by me, in this case) and mutate it, one character at a time, until the string becomes "Hello, world!". Take a look:

var source2 = "og834tnUEF*bt"; //random string
var target2 = "Hello, world!";

function fitness(source, target) {
    var fitval = 0;
    for(var i = 0; i < source.length; i++) {
        fitval += Math.pow(target.charCodeAt(i) - source.charCodeAt(i), 2);
    } return (fitval);
}

function mutate(source) {
    var charpos = Math.floor(Math.random() * source.length);
    parts = source.split("");
    var temp = String.fromCharCode(source.charCodeAt(charpos) + (Math.random() < 0.5 ? -1 : 1));
    parts[charpos] = temp;
    return (parts.join(""));
}

//functions end

var fitval = fitness(source2, target2);
var p = 0;
while(true) {
    p += 1;
    mutant = mutate(source2);
    mutFit = fitness(mutant, target2);
    if (mutFit < fitval) {
        fitval = mutFit;
        source2 = mutant;
        document.write(p + " : " + mutFit + "  :  " + mutant + "<br />");
    } if (fitval === 0) break;
}

I don't believe the description of the algorithm matters too much, because I don't have a problem with the code. This line here:

document.write(p + " : " + mutFit + "  :  " + mutant + "<br />");

seems to be giving me issues. Although a line break is included at the end, the output in the browser groups up every once in a while for no reason. Check out the JSFiddle here: https://jsfiddle.net/oaahzsuf/

Notice the output getting bundled up? I've found that the grouping up seems to occur every time a semicolon is mutated, but I don't know what that has to do with anything. Any ideas as to what the issue is? I feel like I'm overlooking something simple, so any help is appreciated.

SiteChunk
  • 33
  • 4

2 Answers2

1

Your random-character generator is outputting a < character!

Perhaps make your character generator behave by only allowing it to create valid characters that would actually be in your output.


If you really want these characters anyway, then escape the html entities like so:

function htmlEscape(str) {
    return String(str)
            .replace(/&/g, '&amp;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;');
}

...

document.write(p + " : " + htmlEscape(mutFit) + "  :  " + htmlEscape(mutant) + "<br />");

Additionally, don't use document.write.

If you execute your page after the page has full loaded, then you can append output to the <body> element.

document.addEventListener("DOMContentLoaded", function(event) { 
  var documentBody = document.getElementsByTagName('body')[0];
  //do work
  documentBody.innerHTML += p + " : " + mutFit + "  :  " + mutant + "<br />";
});
Community
  • 1
  • 1
Joe Frambach
  • 25,568
  • 9
  • 65
  • 95
1

If you console.log every string you're appending to the output div, then you'll notice that some of them break your <br> tags, because they contain HTML characters, like <, and innerHTML tries to parse the string into HTML (I checked the jsFiddle, where you're using innerHTML). The same issue happens with document.write.

The simplest solution is to append the <br> tag on a second concat operation.

Like this:

https://jsfiddle.net/oaahzsuf/1/

output.innerHTML += (p + " : " + mutFit + "  :  " + mutant);
output.innerHTML += '<br />';

If there's a chance that your string will ever contain a full tag <>, then you could do this:

output.innerText += (p + " : " + mutFit + "  :  " + mutant);
output.innerHTML += '<br />';

innerText threats the string as plain text.

A third option is using <pre> tags around your string:

https://jsfiddle.net/oaahzsuf/4/

output.innerHTML += (p + " : " + mutFit + "  :  <pre>" + mutant + "</pre><br />");

And a fourth option is escaping the string like @Joe pointed out.

Also, calling document.getElementById that many times in a loop might not be the best thing. Just save a reference to your output div outside of the loop.