CSharp遗传算法求解背包问题

时间:2023-03-09 07:01:19
CSharp遗传算法求解背包问题

断断续续写了四天,感觉背包问题是最适合了解遗传算法的问题模型

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();
}
}
}