/*
 * TSPPartiallyMapped.java
 *
 * Created on May 23, 2006, 8:31 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package cz.pcland.ga.crossover;
import cz.pcland.ga.BaseIndividual;
import cz.pcland.ga.MyRand;
import cz.pcland.ga.TSPIntegerIndividual;
import java.util.*;
/**
 *
 * @author petr
 */
public class TSPPartiallyMapped implements CrossoverOpearator{
    
    /** Creates a new instance of TSPPartiallyMapped */
    public TSPPartiallyMapped() {
    }
    
     public String toString() {
        return "Partially mapped";
    }
    
    public BaseIndividual[] crossOver(BaseIndividual i1, BaseIndividual i2, int strLen) {
        int cutpoint1 = Math.abs(MyRand.getInt())%strLen;
        int cutpoint2 = Math.abs(MyRand.getInt())%strLen;

        
        if(cutpoint1 > cutpoint2){
            int tmp = cutpoint1;
            cutpoint1 = cutpoint2;
            cutpoint2 = tmp;
        }
        
        int[] integer1 = ((TSPIntegerIndividual)i1).getString();
        int[] integer2 = ((TSPIntegerIndividual)i2).getString();
        
        

        int off1 [] = new int[strLen];
        int off2 [] = new int[strLen];
        
        int[] positions1 = new int[strLen];
        int[] positions2 = new int[strLen];
        //int[] off1_positions = new int[strLen];
        //int[] off2_positions = new int[strLen];
        
        for(int i=0;i<strLen;i++) {
            positions1[i] = -1;
            positions2[i] = -1;
        }
        
        for(int i=0;i<strLen;i++) {
            if(i >= cutpoint1 && i <= cutpoint2) {
                off1[i] = integer1[i];
                off2[i] = integer2[i];
            } else {
                off1[i] = -1;
                off2[i] = -1;
            }
                            
            positions1[integer1[i]] = i;
            positions2[integer2[i]] = i;
        }
        
        for(int i=cutpoint1;i<=cutpoint2;i++) {
            //if number between cutpoints of second parent is not in off1 
            if(positions1[integer2[i]] < cutpoint1 || positions1[integer2[i]] > cutpoint2) {
                int j=positions2[integer1[i]];
                while(j >= cutpoint1 && j <= cutpoint2){
                    j = positions2[integer1[j]];
                }
                
                off1[j] = integer2[i];
            }
            
            if(positions2[integer1[i]] < cutpoint1 || positions2[integer1[i]] > cutpoint2) {
                int j=positions1[integer2[i]];
                while(j >= cutpoint1 && j <= cutpoint2){
                    j = positions1[integer2[j]];
                }
                
                off2[j] = integer1[i];
            }
        }
        
        for(int i=0;i<strLen;i++){
            if(off1[i] == -1) off1[i] = integer2[i];
            if(off2[i] == -1) off2[i] = integer1[i];
        }
        
       
        
        TSPIntegerIndividual[] ret = {new TSPIntegerIndividual(strLen), new TSPIntegerIndividual(strLen)};
        ret[0].setString(off1);
        ret[1].setString(off2);

        
        return ret;
    }
    
    
}
