public void Crossover(LGPPop pop, LGPProgram child1, LGPProgram child2)
        {
            if (worker == null)
            {
                var attrname = schema.Crossover;
                switch (attrname)
                {
                case LGPSchema.CrossoverType.linear:
                    worker = new LGPCrossoverInstruction_Linear(schema);
                    break;

                case LGPSchema.CrossoverType.one_point:
                    worker = new LGPCrossoverInstruction_OnePoint(schema);
                    break;

                case LGPSchema.CrossoverType.one_seg:
                    worker = new LGPCrossoverInstruction_OneSegment(schema);
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            worker.Crossover(pop, child1, child2);
        }
コード例 #2
0
        public override void Initialize(LGPPop pop)
        {
            // CSChen says:
            // specified here is a variable length initialization that selects initial program
            // lengths from a uniform distribution within a specified range of m_iInitialMinProgLength - m_iIinitialMaxProgLength
            // the method is recorded in chapter 7 section 7.6 page 164 of Linear Genetic Programming 2004
            int iPopulationSize = pop.PopulationSize;

            // CSChen says:
            // the program generated in this way will have program length as small as
            // iMinProgLength and as large as iMaxProgLength
            // the program length is distributed uniformly between iMinProgLength and iMaxProgLength
            for (int i = 0; i < iPopulationSize; i++)
            {
                int iProgLength = m_iInitialMinProgLength + DistributionModel.NextInt(m_iInitialMaxProgLength - m_iInitialMinProgLength + 1);
                //Console.WriteLine("Prog Length: {0}", iProgLength);
                LGPProgram lgp = pop.CreateProgram(iProgLength, pop.Environment);
                pop.AddProgram(lgp);

                //Console.WriteLine("Min Length: {0}", m_iInitialMinProgLength);
                //Console.WriteLine("LGP: {0}", lgp.InstructionCount);

                if (lgp.InstructionCount < m_iInitialMinProgLength)
                {
                    throw new ArgumentNullException();
                }
                if (lgp.InstructionCount > m_iInitialMaxProgLength)
                {
                    throw new ArgumentNullException();
                }
            }
        }
コード例 #3
0
 public void Mutate(LGPPop pop, LGPProgram child1, LGPProgram child2)
 {
     if (mCurrentMacroMutation != null)
     {
         mCurrentMacroMutation.Mutate(pop, child1, child2);
     }
 }
コード例 #4
0
 public virtual LGPProgram Select(LGPPop pop)
 {
     if (mCurrentInstruction != null)
     {
         return(mCurrentInstruction.Select(pop));
     }
     return(null);
 }
コード例 #5
0
        static void Main(string[] args)
        {
            DataTable table = LoadData();

            LGPConfig config = new LGPConfig();

            LGPPop pop = new LGPPop(config);

            pop.OperatorSet.AddOperator(new LGPOperator_Plus());
            pop.OperatorSet.AddOperator(new LGPOperator_Minus());
            pop.OperatorSet.AddOperator(new LGPOperator_Division());
            pop.OperatorSet.AddOperator(new LGPOperator_Multiplication());
            pop.OperatorSet.AddOperator(new LGPOperator_Power());
            pop.OperatorSet.AddIfltOperator();

            pop.CreateFitnessCase += (index) =>
            {
                MexicanHatFitnessCase fitness_case = new MexicanHatFitnessCase();
                fitness_case.X1 = double.Parse(table.Rows[index]["X1"].ToString());
                fitness_case.X2 = double.Parse(table.Rows[index]["X2"].ToString());
                fitness_case.Y  = double.Parse(table.Rows[index]["Y"].ToString());


                return(fitness_case);
            };

            pop.GetFitnessCaseCount += () =>
            {
                return(table.Rows.Count);
            };

            pop.EvaluateCostFromAllCases += (fitness_cases) =>
            {
                double cost = 0;
                for (int i = 0; i < fitness_cases.Count; i++)
                {
                    MexicanHatFitnessCase fitness_case = (MexicanHatFitnessCase)fitness_cases[i];
                    double correct_y  = fitness_case.Y;
                    double computed_y = fitness_case.PredictedY;
                    cost += (correct_y - computed_y) * (correct_y - computed_y);
                }

                return(cost);
            };


            pop.BreedInitialPopulation();


            while (!pop.IsTerminated)
            {
                pop.Evolve();
                Console.WriteLine("Mexican Hat Symbolic Regression Generation: {0}", pop.CurrentGeneration);
                Console.WriteLine("Global Fitness: {0}\tCurrent Fitness: {1}", pop.GlobalBestProgram.Fitness.ToString("0.000"), pop.FindFittestProgramInCurrentGeneration().Fitness.ToString("0.000"));
            }

            Console.WriteLine(pop.GlobalBestProgram.ToString());
        }
コード例 #6
0
        static void Main(string[] args)
        {
            DataTable table = LoadData("dataset.txt");

            LGPConfig config = new LGPConfig();

            LGPPop pop = new LGPPop(config);

            pop.OperatorSet.AddOperator(new LGPOperator_Plus());
            pop.OperatorSet.AddOperator(new LGPOperator_Minus());
            pop.OperatorSet.AddOperator(new LGPOperator_Division());
            pop.OperatorSet.AddOperator(new LGPOperator_Multiplication());
            pop.OperatorSet.AddOperator(new LGPOperator_Sin());
            pop.OperatorSet.AddOperator(new LGPOperator_Cos());
            pop.OperatorSet.AddIfgtOperator();

            pop.CreateFitnessCase += (index) =>
            {
                SpiralFitnessCase fitness_case = new SpiralFitnessCase();
                fitness_case.X     = double.Parse(table.Rows[index]["X"].ToString());
                fitness_case.Y     = double.Parse(table.Rows[index]["Y"].ToString());
                fitness_case.Label = int.Parse(table.Rows[index]["Label"].ToString());

                return(fitness_case);
            };

            pop.GetFitnessCaseCount += () =>
            {
                return(table.Rows.Count);
            };

            pop.EvaluateCostFromAllCases += (fitness_cases) =>
            {
                double fitness = 0;
                for (int i = 0; i < fitness_cases.Count; i++)
                {
                    SpiralFitnessCase fitness_case = (SpiralFitnessCase)fitness_cases[i];
                    int correct_y  = fitness_case.Label;
                    int computed_y = fitness_case.ComputedLabel;
                    fitness += (correct_y == computed_y) ? 0 : 1;
                }

                return(fitness);
            };


            pop.BreedInitialPopulation();


            while (!pop.IsTerminated)
            {
                pop.Evolve();
                Console.WriteLine("Spiral Classification Generation: {0}", pop.CurrentGeneration);
                Console.WriteLine("Global Fitness: {0}\tCurrent Fitness: {1}", pop.GlobalBestProgram.Fitness, pop.FindFittestProgramInCurrentGeneration().Fitness);
            }

            Console.WriteLine(pop.GlobalBestProgram.ToString());
        }
コード例 #7
0
 public override LGPProgram Compete(LGPPop pop, LGPProgram weak_program_in_current_pop, LGPProgram child_program)
 {
     if (child_program.IsBetterThan(weak_program_in_current_pop))
     {
         pop.Replace(weak_program_in_current_pop, child_program);
         return(weak_program_in_current_pop);
     }
     return(child_program);
 }
コード例 #8
0
        public void TestSymbolicRegression()
        {
            List <LGPFitnessCase> table  = mexican_hat();
            LGPSchema             config = new LGPSchema();

            LGPPop pop = new LGPPop(config);

            pop.OperatorSet.AddOperator(new LGPOperator_Plus());
            pop.OperatorSet.AddOperator(new LGPOperator_Minus());
            pop.OperatorSet.AddOperator(new LGPOperator_Division());
            pop.OperatorSet.AddOperator(new LGPOperator_Multiplication());
            pop.OperatorSet.AddOperator(new LGPOperator_Power());
            pop.OperatorSet.AddIfltOperator();

            config.ConstantRegisters.Add(new KeyValuePair <double, double>(1, 1));
            config.ConstantRegisters.Add(new KeyValuePair <double, double>(2, 1));
            config.ConstantRegisters.Add(new KeyValuePair <double, double>(3, 1));
            config.ConstantRegisters.Add(new KeyValuePair <double, double>(4, 1));
            config.ConstantRegisters.Add(new KeyValuePair <double, double>(5, 1));
            config.ConstantRegisters.Add(new KeyValuePair <double, double>(6, 1));
            config.ConstantRegisters.Add(new KeyValuePair <double, double>(7, 1));
            config.ConstantRegisters.Add(new KeyValuePair <double, double>(8, 1));
            config.ConstantRegisters.Add(new KeyValuePair <double, double>(9, 1));

            config.RegisterCount = 6;


            pop.CreateFitnessCase += (index) => table[index];

            pop.GetFitnessCaseCount += () => table.Count;

            pop.EvaluateFitnessFromAllCases += (fitness_cases) =>
            {
                double fitness = 0;
                for (int i = 0; i < fitness_cases.Count; i++)
                {
                    MexicanHatFitnessCase fitness_case = (MexicanHatFitnessCase)fitness_cases[i];
                    double correct_y  = fitness_case.Y;
                    double computed_y = fitness_case.ComputedY;
                    fitness += (correct_y - computed_y) * (correct_y - computed_y);
                }

                return(fitness);
            };


            pop.BreedInitialPopulation();


            while (!pop.IsTerminated)
            {
                pop.Evolve();
                Console.WriteLine("Mexican Hat Symbolic Regression Generation: {0}", pop.CurrentGeneration);
                Console.WriteLine("Global Fitness: {0}\tCurrent Fitness: {1}", pop.GlobalBestProgram.Fitness.ToString("0.000"), pop.FindFittestProgramInCurrentGeneration().Fitness.ToString("0.000"));
            }
        }
コード例 #9
0
 public virtual void Select(LGPPop pop, ref KeyValuePair <LGPProgram, LGPProgram> best_pair, ref KeyValuePair <LGPProgram, LGPProgram> worst_pair)
 {
     if (mCurrentInstruction != null)
     {
         mCurrentInstruction.Select(pop, ref best_pair, ref worst_pair);
     }
     else
     {
         throw new ArgumentNullException();
     }
 }
 public void Crossover(LGPPop pop, LGPProgram child1, LGPProgram child2)
 {
     if (mCurrentCrossover != null)
     {
         mCurrentCrossover.Crossover(pop, child1, child2);
     }
     else
     {
         throw new ArgumentNullException();
     }
 }
コード例 #11
0
 public virtual LGPProgram Compete(LGPPop pop, LGPProgram weak_program_in_current_pop, LGPProgram child_program)
 {
     if (mCurrentInstruction != null)
     {
         return(mCurrentInstruction.Compete(pop, weak_program_in_current_pop, child_program));
     }
     else
     {
         throw new ArgumentNullException();
     }
 }
コード例 #12
0
 public void Mutate(LGPPop pop, LGPProgram child)
 {
     if (mCurrentMacroMutation != null)
     {
         mCurrentMacroMutation.Mutate(pop, child);
     }
     else
     {
         throw new ArgumentNullException();
     }
 }
コード例 #13
0
 public virtual void Initialize(LGPPop pop)
 {
     if (mCurrentInstruction != null)
     {
         mCurrentInstruction.Initialize(pop);
     }
     else
     {
         throw new ArgumentNullException();
     }
 }
        public override LGPProgram Compete(LGPPop pop, LGPProgram weak_program_in_current_pop, LGPProgram child_program)
        {
            double r = DistributionModel.GetUniform();

            if (r < m_reproduction_probability)
            {
                //Console.WriteLine("replacing...");
                pop.Replace(weak_program_in_current_pop, child_program);
                return(weak_program_in_current_pop);
            }

            return(child_program);
        }
        public override LGPProgram Select(LGPPop pop)
        {
            HashSet <LGPProgram> tournament = new HashSet <LGPProgram>();

            while (tournament.Count < mTournamentSize)
            {
                int r = DistributionModel.NextInt(pop.ProgramCount);
                tournament.Add(pop.FindProgramByIndex(r));
            }

            List <LGPProgram> programs = tournament.ToList();

            programs = programs.OrderByDescending(o => o.Fitness).ToList();

            return(programs[0]);
        }
コード例 #16
0
        public override void Initialize(LGPPop pop)
        {
            // CSChen says:
            // specified here is a variable length initialization that selects initial program
            // lengths from a uniform distribution within a specified range of m_iInitialMinProgLength - m_iIinitialMaxProgLength
            // the method is recorded in chapter 7 section 7.6 page 164 of Linear Genetic Programming 2004
            int iPopulationSize = pop.PopulationSize;

            // CSChen says:
            // the program generated in this way will have program length as small as
            // iMinProgLength and as large as iMaxProgLength
            // the program length is distributed uniformly between iMinProgLength and iMaxProgLength
            for (int i = 0; i < iPopulationSize; i++)
            {
                LGPProgram lgp = pop.CreateProgram(mConstantProgramLength, pop.Environment);
                pop.AddProgram(lgp);
            }
        }
        public override void Select(LGPPop pop, ref KeyValuePair <LGPProgram, LGPProgram> best_pair, ref KeyValuePair <LGPProgram, LGPProgram> worst_pair)
        {
            List <LGPProgram> tournament1 = new List <LGPProgram>();
            List <LGPProgram> tournament2 = new List <LGPProgram>();
            int tournament_size2          = mTournamentSize * 2;

            if (tournament_size2 > pop.ProgramCount)
            {
                tournament_size2 = pop.ProgramCount;
                int tournament_size = tournament_size2 / 2;
                pop.RandomShuffle();
                for (int i = 0; i < tournament_size; i++)
                {
                    tournament1.Add(pop.FindProgramByIndex(i));
                }
                for (int i = tournament_size; i < tournament_size2; i++)
                {
                    tournament2.Add(pop.FindProgramByIndex(i));
                }
            }
            else
            {
                pop.RandomShuffle();
                for (int i = 0; i < mTournamentSize; i++)
                {
                    tournament1.Add(pop.FindProgramByIndex(i));
                }
                for (int i = mTournamentSize; i < tournament_size2; i++)
                {
                    tournament2.Add(pop.FindProgramByIndex(i));
                }
            }

            tournament1 = tournament1.OrderByDescending(o => o.Fitness).ToList();
            tournament2 = tournament2.OrderByDescending(o => o.Fitness).ToList();

            //Console.WriteLine("tournament 1: {0}", tournament1.Count);
            //Console.WriteLine("tournament 2: {0}", tournament2.Count);

            best_pair  = new KeyValuePair <LGPProgram, LGPProgram>(tournament1[0], tournament2[0]);
            worst_pair = new KeyValuePair <LGPProgram, LGPProgram>(tournament1[tournament1.Count - 1], tournament2[tournament2.Count - 1]);
        }
コード例 #18
0
 public virtual void Mutate(LGPPop pop, LGPProgram child1, LGPProgram child2)
 {
     Mutate(pop, child1);
     Mutate(pop, child2);
 }
コード例 #19
0
 public abstract void Crossover(LGPPop pop, LGPProgram child1, LGPProgram child2);
コード例 #20
0
 public abstract void Select(LGPPop lgpPop, ref KeyValuePair <LGPProgram, LGPProgram> best_pair, ref KeyValuePair <LGPProgram, LGPProgram> worst_pair);
コード例 #21
0
 public abstract LGPProgram Select(LGPPop pop);
コード例 #22
0
 // Xianshun says:
 // this method return the pointer of the program that is to be deleted (loser in the competition for survival)
 public abstract LGPProgram Compete(LGPPop pop, LGPProgram weak_program_in_current_pop, LGPProgram child_program);
コード例 #23
0
 public abstract void Initialize(LGPPop pop);
コード例 #24
0
        public override void Crossover(LGPPop pop, LGPProgram child1, LGPProgram child2)
        {
            // Xianshun says:
            // this implementation is derived from Algorithm 5.1 in Section 5.7.1 of Linear
            // Genetic Programming

            LGPProgram gp1 = child1;
            LGPProgram gp2 = child2;

            // length(gp1) <= length(gp2)
            if (gp1.InstructionCount > gp2.InstructionCount)
            {
                gp1 = child2;
                gp2 = child1;
            }

            // select i1 from gp1 and i2 from gp2 such that abs(i1-i2) <= max_crossover_point_distance
            // max_crossover_point_distance=min{length(gp1) - 1, m_max_distance_of_crossover_points}
            int i1 = DistributionModel.NextInt(gp1.InstructionCount);
            int i2 = DistributionModel.NextInt(gp2.InstructionCount);
            int cross_point_distance         = (i1 > i2) ? (i1 - i2) : (i2 - i1);
            int max_crossover_point_distance = (gp1.InstructionCount - 1 > mMaxDistanceOfCrossoverPoints ? mMaxDistanceOfCrossoverPoints : gp1.InstructionCount - 1);

            while (cross_point_distance > max_crossover_point_distance)
            {
                i1 = DistributionModel.NextInt(gp1.InstructionCount);
                i2 = DistributionModel.NextInt(gp2.InstructionCount);
                cross_point_distance = (i1 > i2) ? (i1 - i2) : (i2 - i1);
            }

            int s1_max = (gp1.InstructionCount - i1) > mMaxDifferenceOfSegmentLength ? mMaxDifferenceOfSegmentLength : (gp1.InstructionCount - i1);
            int s2_max = (gp2.InstructionCount - i2) > mMaxDifferenceOfSegmentLength ? mMaxDifferenceOfSegmentLength : (gp2.InstructionCount - i2);

            // select s1 from gp1 (start at i1) and s2 from gp2 (start at i2)
            // such that length(s1) <= length(s2)
            // and abs(length(s1) - length(s2)) <= m_max_difference_of_segment_length)
            int ls1 = 1 + DistributionModel.NextInt(s1_max);
            int ls2 = 1 + DistributionModel.NextInt(s2_max);
            int lsd = (ls1 > ls2) ? (ls1 - ls2) : (ls2 - ls1);

            while ((ls1 > ls2) && (lsd > mMaxDifferenceOfSegmentLength))
            {
                ls1 = 1 + DistributionModel.NextInt(s1_max);
                ls2 = 1 + DistributionModel.NextInt(s2_max);
                lsd = (ls1 > ls2) ? (ls1 - ls2) : (ls2 - ls1);
            }

            if (((gp2.InstructionCount - (ls2 - ls1)) < mMinProgramLength || ((gp1.InstructionCount + (ls2 - ls1)) > mMaxProgramLength)))
            {
                if (DistributionModel.GetUniform() < 0.5)
                {
                    ls2 = ls1;
                }
                else
                {
                    ls1 = ls2;
                }
                if ((i1 + ls1) > gp1.InstructionCount)
                {
                    ls1 = ls2 = gp1.InstructionCount - 1;
                }
            }

            List <LGPInstruction> instructions1 = gp1.Instructions;
            List <LGPInstruction> instructions2 = gp2.Instructions;

            List <LGPInstruction> instructions1_1 = new List <LGPInstruction>();
            List <LGPInstruction> instructions1_2 = new List <LGPInstruction>();
            List <LGPInstruction> instructions1_3 = new List <LGPInstruction>();

            List <LGPInstruction> instructions2_1 = new List <LGPInstruction>();
            List <LGPInstruction> instructions2_2 = new List <LGPInstruction>();
            List <LGPInstruction> instructions2_3 = new List <LGPInstruction>();

            for (int i = 0; i < i1; ++i)
            {
                instructions1_1.Add(instructions1[i]);
            }
            for (int i = i1; i < i1 + ls1; ++i)
            {
                instructions1_2.Add(instructions1[i]);
            }
            for (int i = i1 + ls1; i < instructions1.Count; ++i)
            {
                instructions1_3.Add(instructions1[i]);
            }

            for (int i = 0; i < i2; ++i)
            {
                instructions2_1.Add(instructions2[i]);
            }
            for (int i = i2; i < i2 + ls2; ++i)
            {
                instructions2_2.Add(instructions2[i]);
            }
            for (int i = i2 + ls2; i < instructions2.Count; ++i)
            {
                instructions2_3.Add(instructions2[i]);
            }

            instructions1.Clear();
            instructions2.Clear();

            for (int i = 0; i < i1; ++i)
            {
                instructions1.Add(instructions1_1[i]);
            }
            for (int i = 0; i < ls2; ++i)
            {
                instructions1.Add(instructions2_2[i]);
                instructions2_2[i].Program = gp1;
            }
            for (int i = 0; i < instructions1_3.Count; ++i)
            {
                instructions1.Add(instructions1_3[i]);
            }

            for (int i = 0; i < i2; ++i)
            {
                instructions2.Add(instructions2_1[i]);
            }
            for (int i = 0; i < ls1; ++i)
            {
                instructions2.Add(instructions1_2[i]);
                instructions1_2[i].Program = gp2;
            }
            for (int i = 0; i < instructions2_3.Count; ++i)
            {
                instructions2.Add(instructions2_3[i]);
            }

            gp1.TrashFitness();
            gp2.TrashFitness();
        }
コード例 #25
0
 public abstract void Mutate(LGPPop lgpPop, LGPProgram child);
 public override void Crossover(LGPPop pop, LGPProgram child1, LGPProgram child2)
 {
     CrossoverOneSegment(child1, child2);
     CrossoverOneSegment(child2, child1);
 }
コード例 #27
0
        public override void Mutate(LGPPop lgpPop, LGPProgram child)
        {
            // CSChen says:
            // This is derived from Algorithm 6.1 (Section 6.2.1) of Linear Genetic Programming
            // Macro instruction mutations either insert or delete a single instruction.
            // In doing so, they change absolute program length with minimum step size on the
            // level of full instructions, the macro level. On the functional level , a single
            // node is inserted in or deleted from the program graph, together with all
            // its connecting edges.
            // Exchanging an instruction or change the position of an existing instruction is not
            // regarded as macro mutation. Both of these variants are on average more
            // destructive, i.e. they imply a larger variation step size, since they include a deletion
            // and an insertion at the same time. A further, but important argument against
            // substitutios of single instructions is that these do not vary program length. If
            // single instruction would only be exchanged there would be no code growth.

            double r = DistributionModel.GetUniform();
            List <LGPInstruction> instructions = child.Instructions;

            if (child.InstructionCount < _macroMutateMaxProgramLength && ((r < _macroMutateInsertionRate) || child.InstructionCount == _macroMutateMinProgramLength))
            {
                LGPInstruction inserted_instruction = new LGPInstruction(child);
                inserted_instruction.Create();
                int loc = DistributionModel.NextInt(child.InstructionCount);
                if (loc == child.InstructionCount - 1)
                {
                    instructions.Add(inserted_instruction);
                }
                else
                {
                    instructions.Insert(loc, inserted_instruction);
                }

                if (_effectiveMutation)
                {
                    while (instructions[loc].IsConditionalConstruct && loc < instructions.Count)
                    {
                        loc++;
                    }
                    if (loc < instructions.Count)
                    {
                        HashSet <int> Reff = new HashSet <int>();
                        child.MarkStructuralIntrons(loc, Reff);
                        if (Reff.Count > 0)
                        {
                            int iRegisterIndex = -1;
                            foreach (int Reff_value in Reff)
                            {
                                if (iRegisterIndex == -1)
                                {
                                    iRegisterIndex = Reff_value;
                                }
                                else if (DistributionModel.GetUniform() < 0.5)
                                {
                                    iRegisterIndex = Reff_value;
                                }
                            }
                            instructions[loc].DestinationRegister = child.RegisterSet.FindRegisterByIndex(iRegisterIndex);
                        }
                    }
                }
            }
            else if (child.InstructionCount > _macroMutateMinProgramLength && ((r > _macroMutateInsertionRate) || child.InstructionCount == _macroMutateMaxProgramLength))
            {
                int loc = DistributionModel.NextInt(instructions.Count);
                if (_effectiveMutation)
                {
                    for (int i = 0; i < 10; i++)
                    {
                        loc = DistributionModel.NextInt(instructions.Count);
                        if (!instructions[loc].IsStructuralIntron)
                        {
                            break;
                        }
                    }
                }


                instructions.RemoveAt(loc);
            }

            child.TrashFitness();
        }
        public override void Crossover(LGPPop pop, LGPProgram child1, LGPProgram child2)
        {
            // Xianshun says:
            // this implementation is derived from Algorithm 5.1 in Section 5.7.1 of Linear
            // Genetic Programming

            LGPProgram gp1 = child1;
            LGPProgram gp2 = child2;

            // length(gp1) <= length(gp2)
            if (gp1.InstructionCount > gp2.InstructionCount)
            {
                gp1 = child2;
                gp2 = child1;
            }

            int max_distance_of_crossover_points = (gp1.InstructionCount - 1) < mMaxDistanceOfCrossoverPoints ? mMaxDistanceOfCrossoverPoints : (gp1.InstructionCount - 1);

            int i1 = DistributionModel.NextInt(gp1.InstructionCount);
            int i2 = DistributionModel.NextInt(gp2.InstructionCount);

            int crossover_point_distance = (i1 > i2) ? (i1 - i2) : (i2 - i1);

            int ls1 = gp1.InstructionCount - i1;
            int ls2 = gp2.InstructionCount - i2;

            // 1. assure abs(i1-i2) <= max_distance_of_crossover_points
            // 2. assure l(s1) <= l(s2)
            bool not_feasible = true;

            while (not_feasible)
            {
                not_feasible = false;
                // ensure that the maximum distance between two crossover points is not exceeded
                if (crossover_point_distance > max_distance_of_crossover_points)
                {
                    not_feasible             = true;
                    i1                       = DistributionModel.NextInt(gp1.InstructionCount);
                    i2                       = DistributionModel.NextInt(gp2.InstructionCount);
                    crossover_point_distance = (i1 > i2) ? (i1 - i2) : (i2 - i1);
                }
                else
                {
                    ls1 = gp1.InstructionCount - i1;
                    ls2 = gp2.InstructionCount - i2;
                    // assure than l(s1) <= l(s2)
                    if (ls1 > ls2)
                    {
                        not_feasible             = true;
                        i1                       = DistributionModel.NextInt(gp1.InstructionCount);
                        i2                       = DistributionModel.NextInt(gp2.InstructionCount);
                        crossover_point_distance = (i1 > i2) ? (i1 - i2) : (i2 - i1);
                    }
                    else
                    {
                        // assure the length of the program after crossover do not exceed the maximum program length or below minimum program length
                        if ((gp2.InstructionCount - (ls2 - ls1)) < mMinProgramLength || (gp1.InstructionCount + (ls2 - ls1)) > mMaxProgramLength)
                        {
                            not_feasible = true;
                            // when the length constraint is not satisfied, make the segments to be exchanged the same length
                            if (gp1.InstructionCount >= gp2.InstructionCount)
                            {
                                i1 = i2;
                            }
                            else
                            {
                                i2 = i1;
                            }
                            crossover_point_distance = 0;
                        }
                        else
                        {
                            not_feasible = false;
                        }
                    }
                }

                List <LGPInstruction> instructions1 = gp1.Instructions;
                List <LGPInstruction> instructions2 = gp2.Instructions;

                List <LGPInstruction> instructions1_1 = new List <LGPInstruction>();
                List <LGPInstruction> instructions1_2 = new List <LGPInstruction>();

                List <LGPInstruction> instructions2_1 = new List <LGPInstruction>();
                List <LGPInstruction> instructions2_2 = new List <LGPInstruction>();

                for (int i = 0; i < i1; ++i)
                {
                    instructions1_1.Add(instructions1[i]);
                }
                for (int i = i1; i < instructions1.Count; ++i)
                {
                    instructions1_2.Add(instructions1[i]);
                }

                for (int i = 0; i < i2; ++i)
                {
                    instructions2_1.Add(instructions2[i]);
                }
                for (int i = i2; i < instructions2.Count; ++i)
                {
                    instructions2_2.Add(instructions2[i]);
                }

                instructions1.Clear();
                instructions2.Clear();

                for (int i = 0; i < i1; ++i)
                {
                    instructions1.Add(instructions1_1[i]);
                }
                for (int i = 0; i < instructions2_2.Count; ++i)
                {
                    instructions1.Add(instructions2_2[i]);
                    instructions2_2[i].Program = gp1;
                }

                for (int i = 0; i < i2; ++i)
                {
                    instructions2.Add(instructions2_1[i]);
                }

                for (int i = 0; i < instructions1_2.Count; ++i)
                {
                    instructions2.Add(instructions1_2[i]);
                    instructions1_2[i].Program = gp2;
                }

                gp1.TrashFitness();
                gp2.TrashFitness();
            }
        }