Genetic algorithm fitness function for scheduling For Job shop scheduling, I built a fitness function:

def makespan_timeCalculation(lot_size, RHS, setup_time, processing_time, sequence, mc_op):    
    machine_assigne_time =[[0 for i in range(mc_op[k])] for k in range(len(mc_op))]
    max_c = [0 for i in range(len(lot_size))]  # Equal number of job
    completion_time = [0 for i in range(len(RHS))]    

    # Check all indices of RHS (Step 2 + 3 + 6)
    for r in range(len(RHS)):
        procTime = run_time(r, lot_size, RHS, sequence, processing_time) + setup_time[RHS[r][2]]

        if lot_size[RHS[r][0]][RHS[r][1]] &gt; 0:                                    # Lot size not zero (Step 4)
            if (machine_assigne_time[RHS[r][2]][RHS[r][3]] == 0 and RHS[r][2] == sequence[RHS[r][0]][0]):
                # Step 5.1: First assignment to machine m and operation equal first operation in sequence

                completion_time[r] = setup_time[RHS[r][2]] + procTime
                machine_assigne_time[RHS[r][2]][RHS[r][3]] +=1

            elif (machine_assigne_time[RHS[r][2]][RHS[r][3]] == 0 and RHS[r][2] != sequence[RHS[r][0]][0]):
                # Step 5.2: First assignment to machine m and operation over first operation in sequence

                curent_sequence_index = sequence[RHS[r][0]].index(RHS[r][2])                              # Calculate index sequence of current chromosome
                prev_sequence = sequence[RHS[r][0]][curent_sequence_index-1]                              # Return previous sequence operation of current chromosome
                prev_operation_comp_index = [i[0:3] for i in RHS].index([RHS[r][0], RHS[r][1], prev_sequence])      # Return previous chromosome of current job + sublot

                completion_time[r] = max(setup_time[RHS[r][2]], completion_time[prev_operation_comp_index]) + procTime
                machine_assigne_time[RHS[r][2]][RHS[r][3]] +=1
                #print(curent_sequence_index, RHS[r])    
            elif (machine_assigne_time[RHS[r][2]][RHS[r][3]] &gt; 0 and RHS[r][2] == sequence[RHS[r][0]][0]):
                # Step 5.3: First operation in sequence and machine m assignment &gt; 1 (dung de xem xet khi co su khac nhau giua setup time ban dau, va setup time doi part) 
                prev_op_mc_RHS_index = max([i for i, al in enumerate(RHS[:r]) if RHS[r][2:] == al[2:]])
                completion_time[r] = completion_time[prev_op_mc_RHS_index] + procTime
                machine_assigne_time[RHS[r][2]][RHS[r][3]] +=1

            elif (machine_assigne_time[RHS[r][2]][RHS[r][3]] &gt; 0 and RHS[r][2] != sequence[RHS[r][0]][0]):
                # Step 5.4 Operation over first operation in sequence and machine m assignment &gt; 1

                curent_sequence_index = sequence[RHS[r][0]].index(RHS[r][2])                              # Calculate index sequence of current chromosome
                prev_sequence = sequence[RHS[r][0]][curent_sequence_index-1]                              # Return previous sequence operation of current chromosome
                prev_operation_comp_index = [i[0:3] for i in RHS].index([RHS[r][0], RHS[r][1], prev_sequence])      # Return previous chromosome of current job + sublot              
                prev_op_mc_RHS_index = max([i for i, al in enumerate(RHS[:r]) if RHS[r][2:] == al[2:]])                
                completion_time[r] = max(completion_time[prev_operation_comp_index], completion_time[prev_op_mc_RHS_index]) + procTime
                machine_assigne_time[RHS[r][2]][RHS[r][3]] +=1

        max_c[RHS[r][0]] = max(max_c[RHS[r][0]], completion_time[r])

    return max(max_c)


The result is fine but speed is very slow. Could you help to have a look and advise on improvement?
I think the biggest boost to readability will come from giving things proper names. You currently have a lot of RHS[r][i] going on, with i = 0, 1, 2, 3. For someone who does not know what these things are (including possibly you in a few months), this makes the code basically unreadable.

I would start by making the iteration look like this:

for r, (a, b, c, d) in enumerate(RHS):
    ...


Where a, b, c, d are actual sensible names (like name, length, or whatever is actually at those positions).

Next, your setup code can be simplified using the fact that e.g. [0] * 3 == [0, 0, 0] (but don't do it with nested loops, see below):

machine_assigne_time = [[0] * op] for op in mc_op]
max_c = [0] * len(lot_size)  # Equal number of job
completion_time = [0] * len(RHS)


And finally, without being able to run your code, the most obvious case for the slow down are your repeated calls to list.index. This is very slow (\$\mathcal{O}(n)\$ in the worst case). I would try to find a more efficient data structure for this (dictionaries?).