function crossover(p_int1::Vector{Int64},p_float1::Matrix{Float64},
    p_int2::Vector{Int64},p_float2::Matrix{Float64})
        
    p_int3 = zeros(Int,size(p_int1,1)*size(p_int2,1))
    p_float3 = zeros((size(p_float1,1)*size(p_float2,1),size(p_float1,2)))

    add_on = 0

    min_index = min(size(p_int1,1),size(p_int2,1))
    max_index = max(size(p_int1,1),size(p_int2,1))


    for i in 1:min_index
        if rand() < 0.5
            p_int3[i] = p_int1[i]
            p_float3[i:i,:] = p_float1[i:i,:]
        else
            p_int3[i] = p_int2[i]
            p_float3[i:i,:] = p_float2[i:i,:]
        end
    end
        
    if min_index < size(p_int2,1)
        
        p_int3[min_index+1:max_index] = p_int2[min_index+1:max_index]
        p_float3[min_index+1:max_index,:] = p_float2[min_index+1:max_index,:]
        
        p_int3 = p_int3[1:max_index + add_on]
        p_float3 = p_float3[1:max_index + add_on,:]
        
    elseif min_index < size(p_int1,1)
        
        p_int3[min_index+1:max_index] = p_int1[min_index+1:max_index]
        p_float3[min_index+1:max_index,:] = p_float1[min_index+1:max_index,:]
        
        p_int3 = p_int3[1:max_index + add_on]
        p_float3 = p_float3[1:max_index + add_on,:]
        
    else        
        p_int3 = p_int3[1:max_index + add_on]
        p_float3 = p_float3[1:max_index + add_on,:]
    end
        
    return p_int3,p_float3
end

function duplication_mutation(p_float::Matrix{Float64},p_int::Vector{Int64},p::Float64)
    if rand() < p
        idx = rand(1:size(p_int,1))
        c_int = [p_int;p_int[idx]]
        c_float = [p_float;p_float[idx:idx,:]]
        
        return c_int,c_float
    else
        return p_int,p_float
    end
end

function deletion_mutation(p_float::Matrix{Float64},p_int::Vector{Int64},save::Int,p::Float64)
    if rand() < p
        idx = rand(save+1:size(p_int,1))
        c_int = p_int[1:size(p_int,1) .!= idx]
        c_float = p_float[1:size(p_float,1) .!= idx,: ]
        
        return c_int,c_float
    else
        return p_int,p_float
    end
end

function creep_mutation!(p_float::Matrix{Float64},p::Float64)
    if rand() < p
        idx = rand(1:size(p_float,1))
        idx_val = rand(1:size(p_float,2))
        p_float[idx,idx_val] += randn()
    end
end

function copy_mutation!(p_float::Matrix{Float64},p::Float64)
    if rand() < p      
        idx,donor = sample(1:size(p_float,1),2, replace = false)  
        if (rand()<=0.5)
            p_float[idx:idx,1:3] = p_float[donor:donor,4:6]
        else
            p_float[donor:donor,1:3] = p_float[idx:idx,4:6]
        end
    end
end

function copy_mutation_env!(p_float::Matrix{Float64},p_int::Vector{Int64},p::Float64)
    if rand() < p      
        idx = rand(1:size(p_float,1))
        donor = sample(findall(x->x==4, p_int),1)[1]
        
        if (rand()<=0.5)
            p_float[idx:idx,1:3] = p_float[donor:donor,4:6]
        else
            p_float[donor:donor,1:3] = p_float[idx:idx,4:6]
        end
    end
end

function copy_receptor_mutation!(p_float::Matrix{Float64},p_int::Vector{Int64},p::Float64)
    if rand() < p      
        idx_receptor = rand(1:4)
        idx_env = sample(findall(x->x==4, p_int),1)[1]        
        p_float[idx_env:idx_env,4:6] = p_float[idx_receptor:idx_receptor,1:3] # coding 1-3 promoter 4-6
    
    end
end

function type_mutation!(p_int::Vector{Int64},save::Int,p::Float64)
    if rand() < p
        idx = rand(save+1:size(p_int,1))
        p_int[idx] = rand(1:4)
    end
end

function create_child(p_int1::Vector{Int64},p_float1::Matrix{Float64},p_int2::Vector{Int64},p_float2::Matrix{Float64})    
    
    c_int,c_float = crossover(p_int1,p_float1,p_int2,p_float2)
    
    return c_int,c_float
end

function create_child(p_int1::Vector{Int64},p_float1::Matrix{Float64},evo_config::Union{POOLConfig,EMAPConfig})    
    
    n_mut = 7 
    
    p = n_mut*rand()
    
    if p < 1
        c_int,c_float = duplication_mutation(p_float1,p_int1,1.)
    elseif p < 2
        c_int,c_float = deletion_mutation(p_float1,p_int1,evo_config.genome_preserve,1.)
    elseif p < 3
        c_int = copy(p_int1)
        c_float = copy(p_float1)
        creep_mutation!(c_float,1.)
    elseif p < 4
        c_int = copy(p_int1)
        c_float = copy(p_float1)
        copy_receptor_mutation!(c_float,c_int,1.)
    elseif p < 5
        c_int = copy(p_int1)
        c_float = copy(p_float1)
        copy_mutation!(c_float,1.)
    elseif p < 6
        c_int = copy(p_int1)
        c_float = copy(p_float1)
        copy_mutation_env!(c_float,c_int,1.)
    else
        c_int = copy(p_int1)
        c_float = copy(p_float1)
        type_mutation!(c_int,evo_config.genome_preserve,1.)
    end

    return c_int,c_float
end