0

I am implementing Genetic Algorithm (GA). There are 43 numbers [Ambulance Locations] to choose from (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39) , I choose 3 places since I have 3 ambulances.

I can only put my ambulance in 3 locations among 1-39 locations (Restriction).

A chromosome sample: [000010000000000000100000000000100000000]. This represents that I want to put my Ambulance on the 5th, 19th, and 31 positions. The bits against positions 5th, 19th, and 31 are 1 and rest positions are 0. In other words, I am turning on 5-bit, 19-bit, and 31-bit.

Let's say

Candidate solution 1 (111000000000000000000000000000000000000) 

and

Candidate Solution 2 (000000000000000000000000000000000000111)

My candidate solutions are encoded in 39-bits,I want to do a cross-over these 39-bits. Above two candidates solutions are a bit weird. What can be done here?

What can be a good approach to perform cross-over while puting ambulances in 3 locations among 1-39 locations?

  • I have no idea what you mean by "crossover". Do you mean reversing the bits? You can reverse a string in Python by doing `s[::-1]`. If you just want to put the bits in the opposite order, then instead of adding `1 << i`, add in `1 << (31-i)`. – Tim Roberts Oct 05 '22 at 19:56
  • @TimRoberts I am using the genetic algorithm to perform cross-over. I need to create off-spring/child from parents chromosomes. –  Oct 05 '22 at 20:01
  • @AdilAbid So how exactly is this related to ambulances? – pigrammer Oct 05 '22 at 20:04
  • @pigrammer I need to explore my search space. My Search Space is `9139`. Following the genetic algorithm, I need to perform mutation and cross-over to find the best 3 locations to put my ambulances. –  Oct 05 '22 at 20:07

1 Answers1

1

OPs question

There are many ways to perform crossover - in this example as we must end up with the same number of bits in the input and the output I have used a crossover between the bits, allowing for 0-3 bits to get swapped between the two inputs.

The solution provided is dynamic and will work for any length chromosome with any number of flipped bits (1s).

import random
from typing import Union
def crossover(cs1: str, cs2: str) -> Union[str, str]:
    if len(cs1) != len(cs2):
        raise Exception("Candidate solutions input are of different length.")
    # get the flipped bits in each string
    cs1_bits = [index for index, gene in enumerate(cs1) if gene == "1"]
    cs2_bits = [index for index, gene in enumerate(cs2) if gene == "1"]
    if len(cs1_bits) != len(cs2_bits):
        raise Exception("Candidate solutions input have different number of flipped bits.")
    index: int = random.randint(0, len(cs1_bits))
    sol1_bits, sol2_bits = cs1_bits[:index] + cs2_bits[index:], cs2_bits[:index] + cs1_bits[index:]
    output_1 = ""
    output_2 = ""
    for i in range(len(cs1)):
        if i in sol1_bits:
            output_1 += "1"
        else:
            output_1 += "0"
        if i in sol2_bits:
            output_2 += "1"
        else:
            output_2 += "0"
    return output_1, output_2

Example input/output for OPs solution.

# Input
"111000000000000000000000000000000000000", "000000000000000000000000000000000000111"
# Output
'110000000000000000000000000000000000001', '001000000000000000000000000000000000110'

How to perform standard crossover

You perform crossover in a genetic algorithm by selecting a random index along the length of the number of values, in your instance, you will choose a value between 0-38 (39 options).

You will then split both of the inputs and join the front of cs1 onto the back of cs2 and vice versa.

from typing import Union
import random
def crossover(cs1: str, cs2: str) -> Union[str, str]:
    index: int = random.randint(0, len(cs1))
    return cs1[:index] + cs2[index:], cs2[:index] + cs1[index:]

If you have the values:

cs1 = "111000000000000000000000000000000000000"
cs2 = "000000000000000000000000000000000000111"

Crossing over with an index of 1 will return:

output_1 = "100000000000000000000000000000000000111"
output_2 = "011000000000000000000000000000000000000"

Crossing over with an index of 5 will return:

output_1 = "111000000000000000000000000000000000111"
output_2 = "000000000000000000000000000000000000000"
Jeremy Savage
  • 944
  • 5
  • 14
  • Can you also suggest me how to 'mutate` `cs1 = "111000000000000000000000000000000000000"` in a good and organized way? Just like cross-over? –  Oct 05 '22 at 20:45
  • Ask another question, reply to me here when you have done so and I will answer it for you. – Jeremy Savage Oct 05 '22 at 20:48
  • I have posted another question for mutation. Please have a look. This is my question (https://stackoverflow.com/questions/73966258/mutation-with-string-encoded-chromosomes-genetic-algorithm) –  Oct 05 '22 at 20:57
  • I have question. If we look at the `output_1` = `"111000000000000000000000000000000000111"`, I am getting `six` `1's`. However, it is a must for me to only keep `3bits` (only 3 ambulances) after a cross-over. What should I do? –  Oct 06 '22 at 17:28
  • @JeremySavage I think unform-crossover can solve such problems. This solution will mostly result in illegal offspring. – ExploringAI Oct 06 '22 at 17:44
  • I have updated to return only 3 bits - sorry I did not read your question correctly. I have left the original solution below as it may be useful for someone else. – Jeremy Savage Oct 06 '22 at 20:16
  • @JeremySavage Your solution code is based on a `One Point Crossover`, `Multi-Point Crossover`, or `Uniform Crossover`? – ExploringAI Oct 07 '22 at 14:39
  • The solution is a variation of a `one-point` crossover. An `index` is chosen and then bits on either side of the index are swapped over. As you have only 3 possible solutions selected at a time I think `one-point` makes sense. You could also use a `uniform crossover` to solve this, but a `multi-point crossover` would not make sense due to the lack of solutions available. – Jeremy Savage Oct 07 '22 at 21:00