CSharp遗传算法求解背包问题
Posted 鸡毛巾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSharp遗传算法求解背包问题相关的知识,希望对你有一定的参考价值。
断断续续写了四天,感觉背包问题是最适合了解遗传算法的问题模型
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Bag { /// <summary> /// 背包类 /// </summary> public class Bag { public int Size { get; } public Bag(int Size) { this.Size = Size; } } /// <summary> /// 货物类 /// </summary> public class Goods { public int Weight { set; get; } public int Value { set; get; } /// <summary> /// 这里随机生成货物属性 /// </summary> public Goods() { this.Weight = APP.Rd.Next() % 200 + 10; this.Value = APP.Rd.Next() % 1000 + 50; } } /// <summary> /// 测试结果,编号,总重与总价 /// </summary> public class Total { public int Index { set; get; } public long TotalWeight { set; get; } public long TotalValue { get; set; } public Total(int Index, long TotalWeight, long TotalValue) { this.Index = Index; this.TotalWeight = TotalWeight; this.TotalValue = TotalValue; } } public class Chromosome { private bool[] _GeneList = new bool[APP.GoodsNumber]; public bool[] GeneList { get { return this._GeneList; } } public Chromosome() { for (int i = 0; i < APP.GoodsNumber; ++i) { this._GeneList[i] = ((APP.Rd.Next() % 2) == 0); } } public Chromosome(Chromosome Father, Chromosome Mother) { int CutPoint = (APP.Rd.Next() % (APP.GoodsNumber - 1)) + 1; Array.Copy(Father._GeneList, 0, this._GeneList, 0, CutPoint); Array.Copy(Mother._GeneList, CutPoint, this._GeneList, CutPoint, APP.GoodsNumber - CutPoint); if ((APP.Rd.Next() % APP.Mutation) == 0) { var MutationIndexList = APP.RandomSelect(APP.MutationNumber); foreach (var Index in MutationIndexList) { this._GeneList[Index] = !this._GeneList[Index]; } } } } public class Population { private Chromosome[] _ChromosomeList = new Chromosome[APP.PopulationSize]; public Chromosome[] ChromosomeList { get { return this._ChromosomeList; } } private Total Test(int Index, Chromosome pChromosome, Goods[] pGoodsList) { long WeightSum = 0; long ValueSum = 0; int i = 0; foreach (var BValue in pChromosome.GeneList) { if (BValue) { WeightSum += pGoodsList[i].Weight; ValueSum += pGoodsList[i].Value; } ++i; } return new Total(Index, WeightSum, ValueSum); } public Population() { for (int i = 0; i < APP.PopulationSize; ++i) { this._ChromosomeList[i] = new Chromosome(); } } /// <summary> /// 随机选取一个繁殖对象 /// </summary> /// <returns></returns> public int Select() { for (int i = 0; i < APP.PopulationSize; ++i) { if (APP.Rd.Next() % 2 == 0) { return i; } } return APP.PopulationSize - 1; } /// <summary> /// 随机选取两个不同的繁殖对象 /// </summary> /// <param name="Index1"></param> /// <param name="Index2"></param> public void SelectDouble(out int Index1, out int Index2) { int I1 = -1, I2 = -1; while (I1 == I2) { I1 = Select(); I2 = Select(); } Index1 = I1; Index2 = I2; } /// <summary> /// 总群演化方法 /// </summary> /// <param name="pBag">背包</param> /// <param name="pGoodsList">商品清单</param> /// <returns></returns> public Total[] Evolution(Bag pBag, Goods[] pGoodsList) { Total[] TotalList = new Total[this.ChromosomeList.Count()]; for (int i = 0; i < this.ChromosomeList.Count(); ++i) { TotalList[i] = Test(i, this.ChromosomeList[i], pGoodsList); } var OkList = TotalList.Where(p => p.TotalWeight <= pBag.Size).OrderByDescending(p => p.TotalValue); var OutList = TotalList.Where(p => p.TotalWeight > pBag.Size).OrderByDescending(p => { double BaseA = (double)p.TotalValue / p.TotalWeight; double BaseB = ((double)pBag.Size * pBag.Size) / ((double)p.TotalWeight * p.TotalWeight); return BaseA * BaseB; }); var NewList = OkList.Concat(OutList).ToArray(); var SubChromosomeList = new Chromosome[APP.PopulationSize]; int FatherIndex; int MotherIndex; SelectDouble(out FatherIndex, out MotherIndex); var Father = this.ChromosomeList[NewList[FatherIndex].Index]; var Mother = this.ChromosomeList[NewList[MotherIndex].Index]; for (int i = 0; i < SubChromosomeList.Count(); ++i) { if (i % 2 == 0) { SubChromosomeList[i] = new Chromosome(Father, Mother); } else { SubChromosomeList[i] = new Chromosome(Mother, Father); SelectDouble(out FatherIndex, out MotherIndex); Father = this.ChromosomeList[TotalList[FatherIndex].Index]; Mother = this.ChromosomeList[TotalList[MotherIndex].Index]; } } this._ChromosomeList = SubChromosomeList; return NewList; } } public class APP { //伪随机数产生器 public static Random Rd = new Random(); //货物个数,对应染色体基因长度 public static int GoodsNumber = 200; //突变比率倒数 public static int Mutation = 10; //突变基因数量 public static int MutationNumber = 2; //种群大小 public static int PopulationSize = 1000; /// <summary> /// 从列表之中随机选取一定数量的元素 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="pList">源列表</param> /// <param name="pLen">随机选取的元素列表长度</param> /// <returns></returns> public static List<T> GetRandomList<T>(IEnumerable<T> pList, int pLen) { if (pLen > pList.Count()) { pLen = pList.Count(); } List<T> TmpList = pList.ToList<T>(); List<T> DstList = new List<T>(); for (int i = 0; i < pLen && TmpList.Count() > 1; ++i) { int Index = APP.Rd.Next() % TmpList.Count(); DstList.Add(TmpList[Index]); TmpList.RemoveAt(Index); } return DstList; } /// <summary> /// 随机选取一定数量的Index序列 /// </summary> /// <param name="Num">数量</param> /// <returns></returns> public static List<int> RandomSelect(int Num) { int[] NumList = new int[APP.GoodsNumber]; for (int i = 0; i < APP.GoodsNumber; ++i) { NumList[i] = i; } return GetRandomList<int>(NumList, Num); } public APP() { #region 初始化背包与货物列表 Bag MyBag = new Bag(10000); Goods[] GoodsList = new Goods[APP.GoodsNumber]; for (int i = 0; i < GoodsList.Count(); ++i) { GoodsList[i] = new Goods(); } #endregion #region 创建总群与进行演化 Population iPopulation = new Population(); Total MaxTotal = null; while (true) { var Fst = iPopulation.Evolution(MyBag, GoodsList).First(); if (MaxTotal == null) { MaxTotal = Fst; } else { if (Fst.TotalValue > MaxTotal.TotalValue) { MaxTotal = Fst; } } //这里没有保存染色体,仅仅是取出当前总群的最优结果显示 Console.WriteLine("Value: " + MaxTotal.TotalValue + " Weight: " + MaxTotal.TotalWeight); } #endregion } } public class Program { static void Main(string[] args) { APP App = new APP(); } } }
以上是关于CSharp遗传算法求解背包问题的主要内容,如果未能解决你的问题,请参考以下文章