智能优化算法|遗传算法求解背包0-1问题|C#

adcb6b348dfdc147b7acf0d5e351255a.png

求解结果

视频

背包问题

背包问题(Knapsack problem)是一种组合优化的NP完全问题。问题可以描述为:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,我们如何选择,才能使得物品的总价格最高。问题的名称来源于如何选择最合适的物品放置于给定背包中。

相似问题经常出现在商业、组合数学,计算复杂性理论、密码学和应用数学等领域中。

也可以将背包问题描述为决定性问题,即在总重量不超过W的前提下,总价值是否能达到V。

遗传算法

3a90e0fb7d443076f889f2105dce9634.png

        遗传算法(Genetic Algorithm,GA)最早是由美国的 John holland于20世纪70年代提出,该算法是根据大自然中生物体进化规律而设计提出的。是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型,是一种通过模拟自然进化过程搜索最优解的方法。该算法通过数学的方式,利用计算机仿真运算,将问题的求解过程转换成类似生物进化中的染色体基因的交叉、变异等过程。在求解较为复杂的组合优化问题时,相对一些常规的优化算法,通常能够较快地获得较好的优化结果。遗传算法已被人们广泛地应用于组合优化、机器学习、信号处理、自适应控制和人工生命等领域。20世纪80年代后,遗传算法进入兴盛发展时期,被广泛应用于自动控制、生产计划、图像处理、机器人等研究领域。 

    遗传操作包括以下三个基本遗传算子(genetic operator):选择(selection);交叉(crossover);变异(mutation)。

        遗传算法是解决搜索问题的一种通用算法,对于各种通用问题都可以使用。搜索算法的共同特征为:

(1) 首先组成一组候选解 

(2)依据某些适应性条件测算这些候选解的适应度 

(3)根据适应度保留某些候选解,放弃其他候选解

(4) 对保留的候选解进行某些操作,生成新的候选解。

不足之处 

(1)编码不规范及编码存在表示的不准确性。  

(2)单一的遗传算法编码不能全面地将优化问题的约束表示出来。考虑约束的一个方法就是对不可行解采用阈值,这样,计算的时间必然增加。 

(3)遗传算法通常的效率比其他传统的优化方法低。 

(4)遗传算法容易过早收敛。 

(5)遗传算法对算法的精度、可行度、计算复杂性等方面,还没有有效的定量分析方法。 

应用

        由于遗传算法的整体搜索策略和优化搜索方法在计算时不依赖于梯度信息或其它辅助知识,而只需要影响搜索方向的目标函数和相应的适应度函数,所以遗传算法提供了一种求解复杂系统问题的通用框架,它不依赖于问题的具体领域,对问题的种类有很强的鲁棒性,所以广泛应用于许多科学,下面我们将介绍遗传算法的一些主要应用领域:

函数优化

函数优化是遗传算法的经典应用领域,也是遗传算法进行性能评价的常用算例,许多人构造出了各种各样复杂形式的测试函数:连续函数和离散函数、凸函数和凹函数、低维函数和高维函数、单峰函数和多峰函数等。对于一些非线性、多模型、多目标的函数优化问题,用其它优化方法较难求解,而遗传算法可以方便的得到较好的结果。 

组合优化

随着问题规模的增大,组合优化问题的搜索空间也急剧增大,有时在计算上用枚举法很难求出最优解。对这类复杂的问题,人们已经意识到应把主要精力放在寻求满意解上,而遗传算法是寻求这种满意解的最佳工具之一。实践证明,遗传算法对于组合优化中的NP问题非常有效。例如遗传算法已经在求解旅行商问题、 背包问题、装箱问题、图形划分问题等方面得到成功的应用。 

此外,GA也在生产调度问题、自动控制、机器人学、图象处理、人工生命、遗传编码和机器学习等方面获得了广泛的运用。 

车间调度

车间调度问题是一个典型的NP-Hard问题,遗传算法作为一种经典的智能算法广泛用于车间调度中,很多学者都致力于用遗传算法解决车间调度问题,现今也取得了十分丰硕的成果。从最初的传统车间调度(JSP)问题到柔性作业车间调度问题(FJSP),遗传算法都有优异的表现,在很多算例中都得到了最优或近优解。 

附部分源码:

//遗传算法主程序:0-1背包问题
        public void RunGA()
        {
            // RUN ALL AT ONCE 一次性运行
            Setup();//设置输入参数
            int _RepeatFit = 0;//重复适应度次数
            double _LastBestFit = 0;//上一代计算的 个体最佳适应度值
            //迭代未达最大次数,且重复匹配次数小于设定的终止条件
            while ((GA_GCount <= GA_MAXGENERATION) && (_RepeatFit <= GA_GSTOP))
            {
                RunGeneration();   //生成下一代
                //Populacao 是根据个体总价值由高到低进行排序的 种群
                if (Populacao[1].getFitness() == _LastBestFit)  // 计算 BestFit 重复的次数。.
                {
                    _RepeatFit++;//更新最佳适应度值重复次数
                }
                else
                {
                    _RepeatFit = 0;//重置最佳适应度值重复次数
                    _LastBestFit = Populacao[1].getFitness();//更新上一代计算的 个体最佳适应度值
                }


            }
        }
//迭代一次
        public void RunGeneration()
        {
            // RUN ONE STEP
            // 运行一步
            int EliteSize = (int)(GA_POPSIZE * GA_ELITRATE); //种群数量*精英概率=精英数量(要保留的个体或染色体)
            for (int i = EliteSize; i < (GA_POPSIZE); i++)//种群数量-精英数量=要进行交叉的数量,进行交叉操作 
            {
                int iPai = 1 + (int)(EliteSize * rand.NextDouble()); //随机取一个精英  --索引(取整 )
                int iMae = 1 + (int)(EliteSize * rand.NextDouble());//随机取一个精英 --索引
                int corte = 1 + (int)(N * rand.NextDouble()); //随机生成保留的染色体项数,作为不交叉的片段数


                // 父母之间的交叉产生一个孩子
                Individuo filho = Populacao[iPai].copy(); //孩子:  复制 精英iPai的染色体
                //
                for (int ic = corte; ic < N; ic++)//遍历 交叉的项数
                {
                    filho.setItem(ic, Populacao[iMae].getItem(ic));//将交叉部位设置为iMae的染色体, 生成下一代的一个交叉染色体
                }
                if (rand.NextDouble() < GA_MUTATIONRATE) //该新个体是否发生随机变异
                {//随机数小于 设定的变异概率,则发生随机变异
                    int _id = 1 + (int)(N * rand.NextDouble());// 随机生成染色体变异的位置
                    if (rand.NextDouble() <= 0.5)//一般概率变异为0
                    {
                        filho.setItem(_id, 0);
                    }
                    else//一般概率变异为1
                    {
                        filho.setItem(_id, 1);
                    }
                }
                //计算个体的适应度值(超出额定载重置为0)
                filho.setFitness(filho.CalcFitness(Litens, N));
                Populacao[i] = filho;//交叉后变异的新生代个体 加入人口
                //Populacao[i].Calc_Fitness(C0, K)
            }
            GA_GCount++; //遗传算法迭代次数++
            Populacao = SortElite(Populacao, N);//对新一代人口进行排序
            New2Log("G = " + GA_GCount.ToString("000") +  //迭代次数
                     " Best Fit = " + Populacao[1].getFitness().ToString("00.00") + //新生代人口中 最佳个体适应度值
                     " P = " + Populacao[1].CalculaPeso(Litens, N).ToString("00.00"));  //个体总重量
            ListaSacola(Populacao[1]);//列出最佳适应度值的新生代个体
        }

参考:

https://zh.wikipedia.org/wiki/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98   维基百科:背包问题

https://baike.baidu.com/item/%E9%81%97%E4%BC%A0%E7%AE%97%E6%B3%95/838140  百度百科:遗传算法

The End

  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值