前言
标题该算法针对高速铁路列车开行方案设计,在VS2017 .NETFramework 4.7.1平台 RAM 8G 配置上跑了173分钟。优化模型未包含在论文中,暂不能公布。说明的一点是,算法约束用的是简单的罚函数–内点法,未采用拉格朗日罚函数。精通算法的前辈大佬若扫到该文,如能提出复杂度更低的优化算法,晚辈感激不尽!初衷不变,以便日后查看。
窗体应用程序+Chart控件,该算法可复制。
代码
1.编写LinkExcel类,针对特点Excel表进行存取
public class LinkExcel
{
string[] sheetName = new string[] { };//客流数据表
/// <summary>
/// 连接EXCEL并读取客流数据
/// </summary>
/// <param name="filePath">客流数据表路径</param>
/// <returns>数据集</returns>
public DataSet LoadDataFormExcel(string filePath)
{
try
{
string strConn;
strConn = "Provider=Microsoft.Ace.OleDb.12.0;Data Source=" + filePath + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=1'";
OleDbConnection oleConn = new OleDbConnection(strConn);
oleConn.Open();
string sql="";
OleDbDataAdapter oleDaExcel;
DataSet oleDsExcel = new DataSet();
for (int i = 0; i < sheetName.Length; i++)
{
if (i < 3)
{
sql = "SELECT * FROM [" + sheetName[i] + "$] where OD is not null";
}
else
{
sql = "SELECT Factors,1,2,3,4 FROM [" + sheetName[i] + "$] where Factors is not null";
}
oleDaExcel = new OleDbDataAdapter(sql, oleConn);
oleDaExcel.Fill(oleDsExcel, sheetName[i]);
}
oleConn.Close();
return oleDsExcel;
}
catch (Exception err)
{
MessageBox.Show("数据绑定Excel失败!!\n失败原因:" + err.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
}
/// <summary>
/// 更新Excel中数据
/// </summary>
/// <param name="filePath">客流数据路径</param>
/// <param name="dataTable">待传入数据表</param>
/// <param name="strSheet">待修改数据表表名</param>
public void DSToExcel(string filePath, DataTable dataTable, string strSheet)
{
string strCon = "Provider=Microsoft.Ace.OleDb.12.0;" + "data source=" + filePath + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=0'";
using (OleDbConnection myConn = new OleDbConnection(strCon))
{
myConn.Open();
using (OleDbCommand dbComm = myConn.CreateCommand())
{
for (int i = 0; i < dataTable.Rows.Count; i++)
{
for (int j = 1; j < dataTable.Columns.Count; j++)
{
dbComm.CommandText = "update [" + strSheet + "$] " + "set " + j.ToString() +
"=" + dataTable.Rows[i][j]+" where Factors="+(i+1).ToString();
dbComm.ExecuteNonQuery();
}
}
//MessageBox.Show("数据更新成功!!", "操作成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
/// <summary>
/// 将数据写入Excel中--重载
/// </summary>
/// <param name="filePath">路径</param>
/// <param name="dataSet">数据集</param>
public void DSToExcel(string filePath, DataSet dataSet)
{
string strCon = "Provider=Microsoft.Ace.OleDb.12.0;" + "data source=" + filePath + ";Extended Properties='Excel 12.0;HDR=Yes;IMEX=0'";
using (OleDbConnection myConn = new OleDbConnection(strCon))
{
myConn.Open();
for (int k = 0; k < dataSet.Tables.Count; k++)
{
using (OleDbCommand dbComm = myConn.CreateCommand())
{
for (int i = 0; i < dataSet.Tables[k].Rows.Count; i++)
{
for (int j = 1; j < dataSet.Tables[k].Columns.Count; j++)
{
dbComm.CommandText = "update [" + dataSet.Tables[k].TableName + "$] " + "set " + j.ToString() +
"=" + dataSet.Tables[k].Rows[i][j] + " where Factors=" + (i + 1).ToString();
dbComm.ExecuteNonQuery();
}
}
//MessageBox.Show("数据更新成功!!", "操作成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
}
/// <summary>
/// 构造函数
/// </summary>
public LinkExcel()
{
StringBuilder strb = new StringBuilder();
for (int i = 1; i <= 21; i++)
{
for (int j = i+1; j <= 22; j++)
{
for (int k = 1; k <= 3; k++)
{
strb.AppendLine(i + "-" + j + "g" + k + "Customer");
}
}
}
string str = strb.ToString();
string[] tempStr = str.Split(new char[] { '\n', '\r', ' ' }, StringSplitOptions.RemoveEmptyEntries);
sheetName = new string[tempStr.Length + 3];
sheetName[0] = "g1Customer";
sheetName[1] = "g2Customer";
sheetName[2] = "g3Customer";
for (int i = 0; i < tempStr.Length; i++)
{
sheetName[i + 3] = tempStr[i];
}
}
}
2.编写NAGA-Ⅱ算法,各算子针对模型设计
//染色体--解结构
public struct Chromosome
{
//解的数据
public int[][] x;//二进制解
public double[] f;//目标函数数组
//解的Pareto属性
public int n;//强帕累托支配该解的解个数
public int[] S;//被该解强帕累托支配的解集合--运用索引下标进行访问;
public double N;//拥挤度
//开行频率
public int[,] Frequent;
}
//上层非支配排序算法
public class NSGA_Ⅱ
{
//全局变量
public static int popsize = 100;//种群规模
public static int f_num = 2;//目标函数个数
double pc = 0.95;//交叉概率
double pm = 0.01;//变异概率
internal Chromosome[] chromosomes = new Chromosome[popsize];//种群数组--粒子集合
internal Chromosome[][] f_sort;//父代非支配排序交错数组--存储分层后的粒子
internal Chromosome[][] c_sort;//子代非支配排序交错数组--存储分层后的粒子
Random rand = new Random(DateTime.Now.Millisecond);//随机产生器
LinkExcel linkExcel = new LinkExcel();//Excel连接器--读取数据
internal DataSet dS = new DataSet();//数据集--存储从Excel中读取的数据
internal DataSet dSCustomer = new DataSet();//数据集--存储下层客流博弈结果
string strDataPath = "客流数据.xlsx";//"E:\\CajDocuments\\高速铁路开行方案\\客流数据.xlsx";
//NAGA-Ⅱ特有方法(非支配排序、拥挤度、精英保留策略)
/// <summary>
/// 初始化种群
/// </summary>
internal void UpperInitation()
{
dS = linkExcel.LoadDataFormExcel(strDataPath);//加载Excel数据
//初始化g1Customer、g2Customer、g3Customer数组
for (int i = 0; i < dS.Tables[0].Rows.Count; i++)
{
for (int j = 1; j < dS.Tables[0].Columns.Count; j++)
{
g1Customer[i, j - 1] = Convert.ToInt32(dS.Tables[0].Rows[i][j]);
g2Customer[i, j - 1] = Convert.ToInt32(dS.Tables[1].Rows[i][j]);
g3Customer[i, j - 1] = Convert.ToInt32(dS.Tables[2].Rows[i][j]);
}
}
//初始化开行区段
trainDepartureSection[0] = new int[5] { 1, 2, 3, 4, 5 };//开行区段1
trainDepartureSection[1] = new int[9] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };//开行区段2
trainDepartureSection[2] = new int[14] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 };//开行区段3
trainDepartureSection[3] = new int[22] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 };//开行区段4
trainDepartureSection[4] = new int[3] { 20, 21, 22 };//开行区段5
trainDepartureSection[5] = new int[6] { 17, 18, 19, 20, 21, 22 };//开行区段6
//初始化上层解x并满足停站率约束
for (int i = 0; i < popsize; i++)
{
chromosomes[i].x = new int[trainDepartureSection.GetLength(0)][];
for (int j = 0; j < trainDepartureSection.GetLength(0); j++)
{
chromosomes[i].x[j] = new int[trainDepartureSection[j].Length];
chromosomes[i].x[j][0] = 1;//始发站停车
chromosomes[i].x[j][trainDepartureSection[j].Length - 1] = 1;//终到站停车
for (int k = 1; k < trainDepartureSection[j].Length - 1; k++)
{
chromosomes[i].x[j][k] = rand.Next(2);
}
int istrue = 0;//停站次数
List<int> listIndexPassing = new List<int>();//不停站站点下标集合
for (int k = 0; k < chromosomes[i].x[j].Length; k++)
{
if (chromosomes[i].x[j][k] == 1)
{
istrue++;
}
else
{
listIndexPassing.Add(k);
}
}
double _beta = istrue * 1.0 / chromosomes[i].x[j].Length;
while (_beta < beta)
{
chromosomes[i].x[j][listIndexPassing[0]] = 1;
listIndexPassing.RemoveAt(0);
istrue++;
_beta = istrue * 1.0 / chromosomes[i].x[j].Length;
}
}
//chromosomes[i].f = new double[f_num];
//chromosomes[i].f[0] = F1Object(chromosomes[i]);
//chromosomes[i].f[1] = F2Object(chromosomes[i]);
}
}
/// <summary>
/// 非支配排序
/// </summary>
/// <param name="chromosome">父代种群</param>
internal void NonDominationSort(Chromosome[] chromosome)
{
f_sort = new Chromosome[popsize][];
List<Chromosome> tempList = new List<Chromosome>();//临时存储同一层粒子个体
List<int> tempS = new List<int>();//临时存储被粒子支配的个体集合
//计算种群中每个个体被支配个数n和被该个体支配的解集合S
int less;//解劣于粒子chromosome[i]的个体数目
int equal;//解无差别于粒子chromosome[i]的个体数目
int greater;//解优于粒子chromosome[i]的个体数目
for (int i = 0; i < popsize; i++)
{
for (int j = 0; j < popsize; j++)
{
less = 0;
equal = 0;
greater = 0;
for (int k = 0; k < f_num; k++)
{
if (k == 0)//k=0表示铁路运输企业的净收益函数
{
if (chromosome[i].f[k] > chromosome[j].f[k])
less += 1;
else if (chromosome[i].f[k] == chromosome[j].f[k])
equal += 1;
else
greater += 1;
}
else
{
if (chromosome[i].f[k] < chromosome[j].f[k])
less += 1;
else if (chromosome[i].f[k] == chromosome[j].f[k])
equal += 1;
else
greater += 1;
}
}
if (less == 0 && equal != f_num)
{
chromosome[i].n += 1;
}
else if (greater == 0 && equal != f_num)
{
tempS.Add(j);
}
}
chromosome[i].S = new int[tempS.Count];
for (int j = 0; j < tempS.Count; j++)
{
chromosome[i].S[j] = tempS[j];
}
if (chromosome[i].n == 0)
tempList.Add(chromosome[i]);
tempS.Clear();
}
int pareto_rank = 1;//初始化Pareto等级
//Pareto等级为1的层级
f_sort[pareto_rank - 1] = new Chromosome[tempList.Count];
for (int i = 0; i < tempList.Count; i++)
{
f_sort[pareto_rank - 1][i] = tempList[i];
}
//Pareto等级为i(i>1)的层级
while (f_sort[pareto_rank - 1] != null)
{
if (pareto_rank == popsize)//若非支配排序层级达到种群规模,则退出循环,防止死循环
break;
tempList.Clear();//清空操作,为存储下一层粒子做准备
for (int i = 0; i < f_sort[pareto_rank - 1].Length; i++)
{
for (int j = 0; j < f_sort[pareto_rank - 1][i].S.Length; j++)
{
chromosome[f_sort[pareto_rank - 1][i].S[j]].n -= 1;
if (chromosome[f_sort[pareto_rank - 1][i].S[j]].n == 0)
{
tempList.Add(chromosome[f_sort[pareto_rank - 1][i].S[j]]);
}
}
}
pareto_rank += 1;
if (tempList.Count > 0)
{
f_sort[pareto_rank - 1] = new Chromosome[tempList.Count];
for (int j = 0; j < tempList.Count; j++)
{
f_sort[pareto_rank - 1][j] = tempList[j];
}
}
}
}
/// <summary>
/// 非支配排序
/// </summary>
/// <param name="childchromosome">子代种群</param>
internal void ChildNonDominationSort(Chromosome[] childchromosome)
{
c_sort = new Chromosome[popsize][];
int pareto_rank = 1;//初始化Pareto等级
List<Chromosome> tempList = new List<Chromosome>();//临时存储同一层粒子个体
List<int> tempS = new List<int>();//临时存储被粒子支配的个体集合
//计算种群中每个个体被支配个数n和被该个体支配的解集合S
for (int i = 0; i < popsize; i++)
{
for (int j = 0; j < popsize; j++)
{
int less = 0;//解劣于粒子chromosome[i]的个体数目
int equal = 0;//解无差别于粒子chromosome[i]的个体数目
int greater = 0;//解优于粒子chromosome[i]的个体数目
for (int k = 0; k < f_num; k++)
{
if (k == 0)//k=0表示铁路运输企业的净收益函数
{
if (childchromosome[i].f[k] > childchromosome[j].f[k])
less += 1;
else if (childchromosome[i].f[k] == childchromosome[j].f[k])
equal += 1;
else
greater += 1;
}
else
{
if (childchromosome[i].f[k] < childchromosome[j].f[k])
less += 1;
else if (childchromosome[i].f[k] == childchromosome[j].f[k])
equal += 1;
else
greater += 1;
}
}
if (less == 0 && equal != f_num)
{
childchromosome[i].n += 1;
}
else if (greater == 0 && equal != f_num)
{
tempS.Add(j);
}
}
childchromosome[i].S = new int[tempS.Count];
for (int j = 0; j < tempS.Count; j++)
{
childchromosome[i].S[j] = tempS[j];
}
if (childchromosome[i].n == 0)
tempList.Add(childchromosome[i]);
tempS.Clear();
}
//Pareto等级为1的层级
c_sort[pareto_rank - 1] = new Chromosome[tempList.Count];
for (int i = 0; i < tempList.Count; i++)
{
c_sort[pareto_rank - 1][i] = tempList[i];
}
//Pareto等级为i(i>1)的层级
while (c_sort[pareto_rank - 1] != null)
{
if (pareto_rank == popsize)
break;
tempList.Clear();
for (int i = 0; i < c_sort[pareto_rank - 1].Length; i++)
{
if (c_sort[pareto_rank - 1][i].S.Length > 0)
{
for (int j = 0; j < c_sort[pareto_rank - 1][i].S.Length; j++)
{
childchromosome[c_sort[pareto_rank - 1][i].S[j]].n -= 1;
if (childchromosome[c_sort[pareto_rank - 1][i].S[j]].n == 0)
{
tempList.Add(childchromosome[c_sort[pareto_rank - 1][i].S[j]]);
}
}
}
}
pareto_rank += 1;
if (tempList.Count > 0)
{
c_sort[pareto_rank - 1] = new Chromosome[tempList.Count];
for (int i = 0; i < tempList.Count; i++)
{
c_sort[pareto_rank - 1][i] = tempList[i];
}
}
}
}
/// <summary>
/// 拥挤度
/// </summary>
/// <param name="f_sort">非支配排序后的粒子集合</param>
internal void CrowdingDistanceSort(Chromosome[][] _sort)
{
int rank = -1;//记录非空层级
//计算层数及对相应层级拥挤度赋初值0--后期优化
for (int i = 0; i < _sort.GetLength(0); i++)
{
if (_sort[i] != null)
{
rank += 1;
for (int j = 0; j < _sort[i].Length; j++)
{
_sort[i][j].N = 0;
}
}
else
break;
}
//交错数组二维化
double[,] arrayThreeDimension = new double[popsize, f_num + 2];
for (int i = 0; i < _sort[0].Length; i++)
{
arrayThreeDimension[i, 0] = i;//存储粒子对应层级--此处存储第一层级
arrayThreeDimension[i, 1] = _sort[0][i].f[0];//存储粒子对应的第一个目标函数值
arrayThreeDimension[i, 2] = _sort[0][i].f[1];//存储粒子对应的第二个目标函数值
}
int intTempLength = 0;
for (int i = 1; i < rank + 1; i++)
{
intTempLength = 0;
for (int j = 0; j < i; j++)
{
intTempLength += _sort[j].Length;
}
for (int j = 0; j < _sort[i].Length; j++)
{
arrayThreeDimension[intTempLength + j, 0] = intTempLength + j;
arrayThreeDimension[intTempLength + j, 1] = _sort[i][j].f[0];
arrayThreeDimension[intTempLength + j, 2] = _sort[i][j].f[1];
}
}
//拥挤度计算
for (int k = 0; k < f_num; k++)
{
//按照第k个目标函数升序排序
int arrMin;
for (int i = 0; i < arrayThreeDimension.GetLength(0) - 1; i++)
{
arrMin = i;
for (int j = i + 1; j < arrayThreeDimension.GetLength(0); j++)
{
if (arrayThreeDimension[j, k + 1] < arrayThreeDimension[arrMin, k + 1])
{
arrMin = j;
}
}
double douTemp1 = arrayThreeDimension[arrMin, 0],
douTemp2 = arrayThreeDimension[arrMin, 1],
douTemp3 = arrayThreeDimension[arrMin, 2];
arrayThreeDimension[arrMin, 0] = arrayThreeDimension[i, 0];
arrayThreeDimension[arrMin, 1] = arrayThreeDimension[i, 1];
arrayThreeDimension[arrMin, 2] = arrayThreeDimension[i, 2];
arrayThreeDimension[i, 0] = douTemp1;
arrayThreeDimension[i, 1] = douTemp2;
arrayThreeDimension[i, 2] = douTemp3;
}
//边界点拥挤度为无穷大
arrayThreeDimension[0, 3] = arrayThreeDimension[popsize - 1, 3] = double.MaxValue;
//计算其它各点拥挤度
double douMinCrowding = arrayThreeDimension[0, k + 1];
double douMaxCrowding = arrayThreeDimension[popsize - 1, k + 1];
for (int i = 1; i < popsize - 1; i++)
{
arrayThreeDimension[i, 3] += Math.Abs(arrayThreeDimension[i - 1, k + 1] - arrayThreeDimension[i + 1, k + 1]) * 1.0 / (douMaxCrowding - douMinCrowding);
}
}
//填充具有拥挤度值的_sort[][]
for (int i = 0; i < arrayThreeDimension.GetLength(0); i++)
{
intTempLength = 0;
for (int j = 0; j < rank + 1; j++)
{
intTempLength += _sort[j].Length;
if (arrayThreeDimension[i, 0] < intTempLength)
{
if (j != 0)
{
int intColumn = (int)arrayThreeDimension[i, 0] % (intTempLength - _sort[j].Length);
_sort[j][intColumn].N = arrayThreeDimension[i, 3];
break;
}
else
{
int intColumn = (int)arrayThreeDimension[i, 0];
_sort[j][intColumn].N = arrayThreeDimension[i, 3];
break;
}
}
}
}
}
//遗传算子(模拟二进制交叉(Simulated Binary Crossover,SBX)、多项式变异(Polynomial Mutation)、锦标赛选择(Tournament Selection))
/// <summary>
/// 锦标赛法选择算子
/// </summary>
/// <param name="chromosome">上一代群体</param>
/// <returns>从前代种群中选择出较优种群</returns>
internal Chromosome[] TournamentSelection(Chromosome[] chromosome)
{
int childIndex1;//选择个体1
int childIndex2;//选择个体2
Chromosome[] chromoselect = new Chromosome[popsize];//选择的解个体集合
for (int i = 0; i < popsize; i++)
{
childIndex1 = rand.Next(0, chromosome.Length);
childIndex2 = rand.Next(0, chromosome.Length);
while (childIndex1 == childIndex2)
{
childIndex2 = rand.Next(0, chromosome.Length);
}
if ((chromosome[childIndex1].f[0] >= chromosome[childIndex2].f[0]) ||
(chromosome[childIndex1].f[1] <= chromosome[childIndex2].f[1]))
{
chromoselect[i].x = new int[trainDepartureSection.GetLength(0)][];
for (int j = 0; j < trainDepartureSection.GetLength(0); j++)
{
chromoselect[i].x[j] = new int[trainDepartureSection[j].Length];
for (int k = 0; k < trainDepartureSection[j].Length; k++)
{
chromoselect[i].x[j][k] = chromosome[childIndex1].x[j][k];
}
}
chromoselect[i].f = new double[f_num];
chromoselect[i].f[0] = chromosome[childIndex1].f[0];
chromoselect[i].f[1] = chromosome[childIndex1].f[1];
}
else
{
chromoselect[i].x = new int[trainDepartureSection.GetLength(0)][];
for (int j = 0; j < trainDepartureSection.GetLength(0); j++)
{
chromoselect[i].x[j] = new int[trainDepartureSection[j].Length];
for (int k = 0; k < trainDepartureSection[j].Length; k++)
{
chromoselect[i].x[j][k] = chromosome[childIndex2].x[j][k];
}
}
chromoselect[i].f = new double[f_num];
chromoselect[i].f[0] = chromosome[childIndex2].f[0];
chromoselect[i].f[1] = chromosome[childIndex2].f[1];
}
}
return chromoselect;
}
/// <summary>
/// 交叉、变异算子
/// </summary>
/// <param name="preChromosome">由锦标赛选择出来的种群</param>
internal void NewChromosomes(Chromosome[] preChromosome)
{
Chromosome[] tempNewChildren = new Chromosome[popsize];
int randPL = 0;//开行区段
int randGene = 0;//基因位
int randParent1 = 0;//父代索引1
int randParent2 = 0;//父代索引2
double doueta = 2;//SBX算子中的参数η
double dougamma;//SBX算子中的参数γ
for (int i = 0; i < popsize; i++)
{
//二进制交叉
randParent1 = rand.Next(0, preChromosome.Length);
randParent2 = rand.Next(0, preChromosome.Length);
while (randParent1 == randParent2)
randParent2 = rand.Next(0, preChromosome.Length);
Chromosome _child1 = new Chromosome();
Chromosome _child2 = new Chromosome();
_child1.x = new int[preChromosome[randParent1].x.GetLength(0)][];
_child2.x = new int[preChromosome[randParent2].x.GetLength(0)][];
for (int j = 0; j < preChromosome[randParent1].x.GetLength(0); j++)
{
_child1.x[j] = new int[preChromosome[randParent1].x[j].Length];
_child2.x[j] = new int[preChromosome[randParent1].x[j].Length];
for (int k = 0; k < preChromosome[randParent1].x[j].Length; k++)
{
_child1.x[j][k] = preChromosome[randParent1].x[j][k];
_child2.x[j][k] = preChromosome[randParent2].x[j][k];
}
}
_child1.f = new double[f_num];
_child2.f = new double[f_num];
_child1.f[0] = preChromosome[randParent1].f[0];
_child1.f[1] = preChromosome[randParent1].f[1];
_child2.f[0] = preChromosome[randParent2].f[0];
_child2.f[1] = preChromosome[randParent2].f[1];
int temp1 = 0;//父代1交叉基因位数值
int temp2 = 0;//父代2交叉基因位数值
double x1 = 0;//父代1基因位更新后数值
double x2 = 0;//父代2基因位更新后数值
double _rand = rand.NextDouble();
if (_rand < pc)
{
randPL = rand.Next(0, _child1.x.GetLength(0));
randGene = rand.Next(0, _child1.x[randPL].Length);
for (int j = randGene; j < _child1.x[randPL].Length; j++)
{
temp1 = _child1.x[randPL][j];
temp2 = _child2.x[randPL][j];
_rand = rand.NextDouble();
if (_rand < 0.5)
{
dougamma = Math.Pow(2 * _rand, 1.0 / (doueta + 1));
}
else
{
dougamma = Math.Pow(1.0 / (2 * (1 - _rand)), 1.0 / (doueta + 1));
}
x1 = 0.5 * ((1 + dougamma) * temp1 + (1 - dougamma) * temp2);
x2 = 0.5 * ((1 - dougamma) * temp1 + (1 + dougamma) * temp2);
temp1 = (int)Math.Round(x1);
temp2 = (int)Math.Round(x2);
_child1.x[randPL][j] = temp1;
_child2.x[randPL][j] = temp2;
}
//计算_child1对应函数值
upperSolutionIndex = 0;
ds[upperSolutionIndex] = new DataSet();
for (int j = 1; j < stationNum; j++)//客流博弈分配
{
for (int k = j + 1; k <= stationNum; k++)
{
customersAssigned(_child1, g1Customer[j - 1, k - 1],
g2Customer[j - 1, k - 1], g3Customer[j - 1, k - 1], j, k);
}
}
//根据旅客分配情况确定列车开行频率
_child1.Frequent = new int[pLNum, trainType];
_child1.Frequent = TrainRunningFrequency(ds[upperSolutionIndex]);
//根据旅客分配情况确定上层各函数值
_child1.f = new double[f_num];
dSCustomer = ds[upperSolutionIndex];
_child1.f[0] =
F1Object(_child1);
_child1.f[1] =
F2Object(_child1);
//计算_child2对应函数值
ds[upperSolutionIndex] = new DataSet();
for (int j = 1; j < stationNum; j++)//客流博弈分配
{
for (int k = j + 1; k <= stationNum; k++)
{
customersAssigned(_child2, g1Customer[j - 1, k - 1],
g2Customer[j - 1, k - 1], g3Customer[j - 1, k - 1], j, k);
}
}
//根据旅客分配情况确定列车开行频率
_child2.Frequent = new int[pLNum, trainType];
_child2.Frequent = TrainRunningFrequency(ds[upperSolutionIndex]);
//根据旅客分配情况确定上层各函数值
_child2.f = new double[f_num];
dSCustomer = ds[upperSolutionIndex];
_child2.f[0] =
F1Object(_child2);
_child2.f[1] =
F2Object(_child2);
//选取较优解
if (_child1.f[0] > _child2.f[0] && _child1.f[1] < _child2.f[1])
{
tempNewChildren[i] = _child1;
}
else
{
tempNewChildren[i] = _child2;
}
}
else
{
if (_child1.f[0] > _child2.f[0] && _child1.f[1] < _child2.f[1])
{
tempNewChildren[i] = _child1;
}
else
{
tempNewChildren[i] = _child2;
}
}
//变异
if (rand.NextDouble() < pm)
{
randPL = rand.Next(0, tempNewChildren[i].x.GetLength(0));
randGene = rand.Next(0, tempNewChildren[i].x[randPL].Length);
tempNewChildren[i].x[randPL][randGene] = 1 - tempNewChildren[i].x[randPL][randGene];
//计算tempNewChildren[i]对应函数值
upperSolutionIndex = 0;
ds[upperSolutionIndex] = new DataSet();
for (int j = 1; j < stationNum; j++)//客流博弈分配
{
for (int k = j + 1; k <= stationNum; k++)
{
customersAssigned(tempNewChildren[i], g1Customer[j - 1, k - 1],
g2Customer[j - 1, k - 1], g3Customer[j - 1, k - 1], j, k);
}
}
//根据旅客分配情况确定列车开行频率
tempNewChildren[i].Frequent = new int[pLNum, trainType];
tempNewChildren[i].Frequent = TrainRunningFrequency(ds[upperSolutionIndex]);
//根据旅客分配情况确定上层各函数值
tempNewChildren[i].f = new double[f_num];
dSCustomer = ds[upperSolutionIndex];
tempNewChildren[i].f[0] =
F1Object(tempNewChildren[i]);
tempNewChildren[i].f[1] =
F2Object(tempNewChildren[i]);
}
}
ChildNonDominationSort(tempNewChildren);
CrowdingDistanceSort(c_sort);
}
/// <summary>
/// 新一代群体(精英保留策略)
/// </summary>
/// <param name="f_sort">父代种群</param>
/// <param name="c_sort">子代种群</param>
internal void Elitism(Chromosome[][] f_sort, Chromosome[][] c_sort)
{
Chromosome[][] _Chromosome;
List<Chromosome> listChromosome = new List<Chromosome>();//存储精英解
int rankf = 0;//父代层级数
int rankc = 0;//子代层级数
int rankmax = 0;//最大层级数
for (int i = 0; i < f_sort.GetLength(0); i++)
{
if (f_sort[i] != null)
rankf++;
else
break;
}
for (int i = 0; i < c_sort.GetLength(0); i++)
{
if (c_sort[i] != null)
rankc++;
else
break;
}
if (rankf > rankc)
{
rankmax = rankf;
}
else
{
rankmax = rankc;
}
_Chromosome = new Chromosome[rankmax][];
for (int i = 0; i < rankmax; i++)
{
listChromosome.Clear();
if (f_sort[i] != null)
{
for (int j = 0; j < f_sort[i].Length; j++)
{
listChromosome.Add(f_sort[i][j]);
}
}
if (c_sort[i] != null)
{
for (int j = 0; j < c_sort[i].Length; j++)
{
listChromosome.Add(c_sort[i][j]);
}
}
_Chromosome[i] = new Chromosome[listChromosome.Count];
_Chromosome[i] = listChromosome.ToArray();
}
int currentNum = 0;//已存储解个体数目
int remainNum = 0;//仍缺解个体数目
int index = 0;//种群索引下标
for (int i = 0; i < _Chromosome.GetLength(0); i++)
{
if (currentNum < popsize)
{
if (_Chromosome[i].Length + currentNum <= popsize)
{
for (int j = 0; j < _Chromosome[i].Length; j++)
{
chromosomes[index++] = _Chromosome[i][j];
}
currentNum += _Chromosome[i].Length;
}
else
{
remainNum = popsize - currentNum;
ChromSort(_Chromosome[i]);
for (int j = 0; j < remainNum; j++)
{
chromosomes[index++] = _Chromosome[i][_Chromosome[i].Length - 1 - j];
}
currentNum += remainNum;
}
}
else
break;
}
}
//其它方法
/// <summary>
/// 选择排序(重载)--拥挤度
/// </summary>
/// <param name="chromosome">解个体</param>
void ChromSort(Chromosome[] chromosome)
{
int min;
for (int i = 0; i < chromosome.Length - 1; i++)
{
min = i;
for (int j = i + 1; j < chromosome.Length; j++)
{
if (chromosome[j].N < chromosome[min].N)
{
min = j;
}
}
Chromosome temp = new Chromosome();
temp = chromosome[min];
chromosome[min] = chromosome[i];
chromosome[i] = temp;
}
}
/// <summary>
/// 选择排序--非支配序
/// </summary>
/// <param name="chromosome">待排序同层级个体集合</param>
/// <param name="k">指示函数,k=1代表对第一个目标函数进行排序,k=2表示对第二个目标函数进行排序</param>
/// <returns>排序后同层级个体集合</returns>
void ChromSort(Chromosome[] chromosome, int k)
{
int min;
if (k == 1)
{
for (int i = 0; i < chromosome.Length - 1; ++i)
{
min = i;
for (int j = i + 1; j < chromosome.Length; j++)
{
if (chromosome[j].f[k - 1] < chromosome[i].f[k - 1])
{
min = j;
}
}
Chromosome temp = chromosome[min];
chromosome[min] = chromosome[i];
chromosome[i] = temp;
}
}
else
{
for (int i = 0; i < chromosome.Length - 1; ++i)
{
min = i;
for (int j = i + 1; j < chromosome.Length; j++)
{
if (chromosome[j].f[k - 1] < chromosome[i].f[k - 1])
{
min = j;
}
}
Chromosome temp = chromosome[min];
chromosome[min] = chromosome[i];
chromosome[i] = temp;
}
}
}
internal static int stationNum = 22;//单线高速铁路客运站点数量
internal static int trainType = 4;//列车种类--一站直达、大站停、择站停、站站停
internal static int pLNum = 6;//开行区段数量
public int[][] trainDepartureSection = new int[pLNum][];//列车开行区段
double[] stationsDistance
= new double[] { 87, 45, 31, 25, 43, 55, 105, 64, 35, 46, 49, 61, 21, 126, 163, 261, 249, 32, 91, 158, 9 };//站间距
double cT = 500;//列车公里费用
double cTFix = 1000;//列车固定使用费用
//int g = 3;//客流层次
double[,] rateTicket = new double[,]
{ { 0.9, 0.8, 0.7, 0.6 },{ 0.6, 0.5, 0.4, 0.3 },{0.4,0.3,0.2,0.1 } };//票价率
internal double alphMax = 1.1;//最大上座率
internal double alphMin = 0.6;//最小上座率
internal int seatNum = 90;//列车座位数
internal double douCustomerFluctuateRate = 1.3;//客流波动系数
internal int[,] g1Customer = new int[stationNum, stationNum];//消费层次为g1的铁路旅客集合
internal int[,] g2Customer = new int[stationNum, stationNum];//消费层次为g2的铁路旅客集合
internal int[,] g3Customer = new int[stationNum, stationNum];//消费层次为g3的铁路旅客集合
int[,] g1customerTrainSelection = new int[pLNum, trainType];//客流分配表(i,j)
int[,] g2customerTrainSelection = new int[pLNum, trainType];
int[,] g3customerTrainSelection = new int[pLNum, trainType];
int[,] customerTrainSelection = new int[pLNum, trainType];//选择各类列车的总旅客数
int[] stationCapcity = new int[] { 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200 };//站点通过能力
int[] sectionCapcity = new int[] { 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200 };//区间通过能力
double beta = 0.6;//停站率
double violationFactor = 500000;//罚因子
/// <summary>
/// 铁路净收益目标函数
/// </summary>
/// <param name="chromosome">解粒子</param>
/// <returns>带惩罚值的函数值</returns>
internal double F1Object(Chromosome chromosome)
{
//各费用、票价函数值
double costT = 0;//列车公里费用
double costTFix = 0;//列车固定使用费用
double benefitTicket = 0;//客票收入
double _distance;//距离
int q;//各类列车总数
for (int i = 0; i < trainDepartureSection.GetLength(0); i++)
{
_distance = 0;
q = 0;
for (int j = 0; j < trainType; j++)
{
q += chromosome.Frequent[i, j];
}
_distance = IJDistance(trainDepartureSection[i][0], trainDepartureSection[i][trainDepartureSection[i].Length - 1]);
costT += _distance * q * cT;
costTFix += q * cTFix;
}
string strTableName1 = "";//表名
string strTableName2 = "";
string strTableName3 = "";
double[] _douCustomerSum = new double[3];//乘坐同一种类列车的旅客人数
for (int i = 1; i < stationNum; i++)
{
for (int j = i + 1; j <= stationNum; j++)
{
_distance = IJDistance(i, j);
strTableName1 = i + "-" + j + "g1Customer";
strTableName2 = i + "-" + j + "g2Customer";
strTableName3 = i + "-" + j + "g3Customer";
for (int k = 1; k <= trainType; k++)
{
_douCustomerSum[0] = 0;
_douCustomerSum[1] = 0;
_douCustomerSum[2] = 0;
for (int m = 0; m < pLNum; m++)
{
_douCustomerSum[0] += Convert.ToInt32(dSCustomer.Tables[strTableName1].Rows[m][k]);
_douCustomerSum[1] += Convert.ToInt32(dSCustomer.Tables[strTableName2].Rows[m][k]);
_douCustomerSum[2] += Convert.ToInt32(dSCustomer.Tables[strTableName3].Rows[m][k]);
}
benefitTicket += (_douCustomerSum[0] * rateTicket[0, k - 1] + _douCustomerSum[1] * rateTicket[1, k - 1] +
_douCustomerSum[1] * rateTicket[1, k - 1]) * _distance;
}
}
}
//判断解是否可行
double violationConstraints1 = 0;//违反停站率的惩罚值
double violationConstraints2 = 0;//违反通过能力的惩罚值
for (int i = 0; i < chromosome.x.GetLength(0); i++)//判断解是否满足停站率约束
{
int istrue = 0;//停站次数
for (int j = 0; j < chromosome.x[i].Length; j++)
{
if (chromosome.x[i][j] == 1)
{
istrue++;
}
}
double _beta = istrue * 1.0 / chromosome.x[i].Length;
if (_beta < beta)
violationConstraints1 += violationFactor * (beta - _beta) * (beta - _beta);
else
violationConstraints1 += 0;
}
List<int> tempListStationIndex = new List<int>();//存储站点可能所在区段下标
for (int i = 2; i < stationNum; i++) //判断解是否满足站点通过能力约束
{
tempListStationIndex.Clear();
for (int j = 0; j < trainDepartureSection.GetLength(0); j++)
{
for (int k = 0; k < trainDepartureSection[j].Length; k++)
{
if (i == trainDepartureSection[j][k])
{
tempListStationIndex.Add(j);
break;
}
}
}
int int_qT = 0;//开行频率总数
for (int j = 0; j < tempListStationIndex.Count; j++)
{
for (int k = 0; k < trainType; k++)
{
int_qT += chromosome.Frequent[tempListStationIndex[j], k];
}
}
if (int_qT <= stationCapcity[i - 1])
violationConstraints2 += 0;
else
violationConstraints2 += violationFactor * (int_qT - stationCapcity[i - 1]) * (int_qT - stationCapcity[i - 1]);
}
List<int> tempListSectionIndex = new List<int>();//存储站间可能所在区段下标
for (int i = 1; i < stationNum; i++)//判断解是否满足区间通过能力
{
tempListStationIndex.Clear();
for (int j = 0; j < trainDepartureSection.GetLength(0); j++)
{
for (int k = 0; k < trainDepartureSection[j].Length - 1; k++)
{
if (i == trainDepartureSection[j][k])
{
tempListSectionIndex.Add(j);
break;
}
}
}
int int_qT = 0;//区间列车开行频率总和
for (int j = 0; j < tempListSectionIndex.Count; j++)
{
for (int k = 0; k < trainType; k++)
{
int_qT += chromosome.Frequent[tempListSectionIndex[j], k];
}
}
if (int_qT <= sectionCapcity[i - 1])
violationConstraints2 += 0;
else
violationConstraints2 += violationFactor * (int_qT - sectionCapcity[i - 1]) * (int_qT - sectionCapcity[i - 1]);
}
return benefitTicket - costT - costTFix - violationConstraints1 - violationConstraints2;
}
/// <summary>
/// 列车空座位走行公里
/// </summary>
/// <param name="chromosome">解粒子</param>
/// <returns>带惩罚值的函数值</returns>
internal double F2Object(Chromosome chromosome)
{
double douSeatValue = 0;//上座率值
int[] sectionStation;//开行区段站点集合
int[] sectionCustomer;//区间客流数集合
for (int i = 0; i < trainDepartureSection.GetLength(0); i++)
{
sectionStation = new int[trainDepartureSection[i].Length];
sectionCustomer = new int[trainDepartureSection[i].Length - 1];
for (int j = 0; j < sectionStation.Length; j++)
{
sectionStation[j] = trainDepartureSection[i][j];
}
int douValueCustomer;//区间客流总和
string strTableName1 = "";//表名
string strTableName2 = "";
string strTableName3 = "";
for (int j = 0; j < sectionCustomer.Length; j++)
{
douValueCustomer = 0;
for (int k = 0; k <= j; k++)
{
for (int m = j + 1; m < sectionStation.Length; m++)
{
strTableName1 = sectionStation[k].ToString() + "-" +
sectionStation[m].ToString() + "g1Customer";
strTableName2 = sectionStation[k].ToString() + "-" +
sectionStation[m].ToString() + "g2Customer";
strTableName3 = sectionStation[k].ToString() + "-" +
sectionStation[m].ToString() + "g3Customer";
for (int l = 0; l < trainType; l++)
{
douValueCustomer += Convert.ToInt32(dSCustomer.Tables[strTableName1].Rows[i][l + 1]) +
Convert.ToInt32(dSCustomer.Tables[strTableName2].Rows[i][l + 1]) +
Convert.ToInt32(dSCustomer.Tables[strTableName3].Rows[i][l + 1]);
}
}
}
sectionCustomer[j] = douValueCustomer;
}
double douQ = 0;//区段列车开行频率总和
for (int j = 0; j < trainType; j++)
{
douQ += chromosome.Frequent[i, j];
}
for (int j = 0; j < sectionCustomer.Length; j++)
{
douSeatValue += IJDistance(sectionStation[j], sectionStation[j + 1]) *
(sectionCustomer[j] - douQ * seatNum * 1.0 * (alphMax + alphMin) / 2) *
(sectionCustomer[j] - douQ * seatNum * 1.0 * (alphMax + alphMin) / 2);
}
}
return douSeatValue;
}
/// <summary>
/// 站间距
/// </summary>
/// <param name="startPoint">起始站点</param>
/// <param name="endPoint">终到站点</param>
/// <returns>距离</returns>
internal double IJDistance(int startPoint, int endPoint)
{
double _distance = 0;
for (int i = startPoint - 1; i < endPoint - 1; i++)
{
_distance += stationsDistance[i];
}
return _distance;
}
internal List<Chromosome> iterValue = new List<Chromosome>();//输出对象
public struct Particles //定义粒子的结构体
{
public int x;//粒子当前位置(选择的列车种类)
public double fitness;//粒子的当前位置适应值
}
//全局变量定义
static int popsize1;//消费水平层次为1的群体规模
static int popsize2;//消费水平层次为2的群体规模
static int popsize3;//消费水平层次为3的群体规模
Particles[] g1Particles;//消费水平层次为1的客流个体集合
Particles[] g2Particles;//消费水平层次为2的客流个体集合
Particles[] g3Particles;//消费水平层次为3的客流个体集合
int[] gbest1;//消费层次为1的客流局势
int[] gbest2;//消费层次为2的客流局势
int[] gbest3;//消费层次为3的客流局势
double gbestfitness1;//消费水平层次为1的赢得函数值
double gbestfitness2;//消费水平层次为2的赢得函数值
double gbestfitness3;//消费水平层次为3的赢得函数值
LinkExcel _linkExcel = new LinkExcel();//表读取对象
internal int upperSolutionIndex = 0;//上层解粒子下标索引
DataTable dt = new DataTable();//数据表
internal DataSet[] ds;//数据集
//string _strDataPath = "客流数据.xlsx";//数据所在相对位置
//下层客流博弈分配全局变量
double w1 = 200, w2 = 100, w3 = 50;//各消费层次客流时间价值系数
double lamda11 = 0.1, lamda12 = 0.9;//消费层次等级为1的客流的权重系数
double lamda21 = 0.5, lamda22 = 0.5;//消费层次等级为2的客流的权重系数
double lamda31 = 0.9, lamda32 = 0.1;//消费层次等级为3的客流的权重系数
//double violationM = 50000;//惩罚函数值
double velocity = 250;//列车速度值
double timeAverage = 4;//在站停留平均时间
int[] bigStation = new int[] { 1, 5, 22 };//客流量较大站点集合
double[,] ticketRate = new double[,] { { 0.9, 0.8, 0.7, 0.6 }, { 0.6, 0.5, 0.4, 0.3 }, { 0.4, 0.3, 0.2, 0.1 } };//票价率
//方法定义
int sectionIndex = 0;//客流博弈所在开行区段下标
List<int> sectionListIndexSets = new List<int>();//始发、终到站均含于相同开行区段的开行区段下标集合
List<int> strategySets = new List<int>();//策略集
/// <summary>
/// OD客流选择列车出行博弈方法
/// </summary>
/// <param name="xchromosome">上层解粒子</param>
/// <param name="g1CustomerNum">消费层次为1的OD客流规模</param>
/// <param name="g2CustomerNum">消费层次为2的OD客流规模</param>
/// <param name="g3CustomerNum">消费层次为3的OD客流规模</param>
/// <param name="startStation">O点</param>
/// <param name="endStation">D点</param>
internal void customersAssigned(Chromosome xchromosome, int g1CustomerNum, int g2CustomerNum,
int g3CustomerNum, int startStation, int endStation)
{
sectionIndex = 0;//开行区段索引赋初值
sectionListIndexSets.Clear();//清空开行区段索引集合
strategySets.Clear();//清空策略集
for (int i = 0; i < xchromosome.x.GetLength(0); i++)//填充均包含O、D的开行区段下标集合
{
if (trainDepartureSection[i][0] <= startStation &&
trainDepartureSection[i][xchromosome.x[i].Length - 1] >= endStation)
{
sectionListIndexSets.Add(i);
}
}
//随机选择一个同时包含起始、终点站的列车开行区段
sectionIndex = sectionListIndexSets[rand.Next(sectionListIndexSets.Count)];
//填充策略集StrategySets
//--一站直达
if (startStation == trainDepartureSection[sectionIndex][0] &&
endStation == trainDepartureSection[sectionIndex][trainDepartureSection[sectionIndex].Length - 1])
{
strategySets.Add(1);
}
//--大站停
int isAllbigStation = 0;//指标--指示OD客流是否可以乘坐大站停列车完成出现
for (int i = 0; i < bigStation.Length; i++)
{
if (startStation == bigStation[i])
{
isAllbigStation += 1;
continue;
}
if (endStation == bigStation[i])
{
isAllbigStation += 1;
break;
}
}
if (isAllbigStation == 2)
{
strategySets.Add(2);
}
//--择站停
int startStationIndex = 0;//客流出发站的站点在x解集中对应的下标
int endStationIndex = 0;//客流终到站的站点在x解集中对应的下标
for (int i = 0; i < trainDepartureSection[sectionIndex].Length; i++)
{
if (trainDepartureSection[sectionIndex][i] == startStation)
{
startStationIndex = i;
continue;
}
if (trainDepartureSection[sectionIndex][i] == endStation)
{
endStationIndex = i;
break;
}
}
if (xchromosome.x[sectionIndex][startStationIndex] == 1 && xchromosome.x[sectionIndex][endStationIndex] == 1)
strategySets.Add(3);
//--站站停:对OD(始发站为startStation,终点站为endStation)来说,站站停列车为必备策略
strategySets.Add(4);
//客流列车分配初始化
popsize1 = g1CustomerNum;//初始化各消费层次客流规模
popsize2 = g2CustomerNum;
popsize3 = g3CustomerNum;
g1Particles = new Particles[popsize1];//创建各消费层次客流集合
g2Particles = new Particles[popsize2];
g3Particles = new Particles[popsize3];
gbest1 = new int[popsize1];//创建各消费层次客流局势
gbest2 = new int[popsize2];
gbest3 = new int[popsize3];
//分情况初始化各消费层次客流出行列车选择
if (strategySets.Count == 1)
{
//消费层次为1的客流初始化
g1Particles[0].x = strategySets[0];
gbest1[0] = g1Particles[0].x;
g1Particles[0].fitness = SatisficationValue(g1Particles[0].x, 1, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
for (int i = 1; i < popsize1; i++)
{
g1Particles[i].x = g1Particles[0].x;
g1Particles[i].fitness = g1Particles[0].fitness;
gbest1[i] = g1Particles[i].x;
}
//消费层次为2的客流初始化
g2Particles[0].x = strategySets[0];
gbest2[0] = g2Particles[0].x;
g2Particles[0].fitness = SatisficationValue(g2Particles[0].x, 2, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
for (int i = 1; i < popsize2; i++)
{
g2Particles[i].x = g2Particles[0].x;
g2Particles[i].fitness = g2Particles[0].fitness;
gbest2[i] = g2Particles[i].x;
}
//消费层次为3的客流初始化
g3Particles[0].x = strategySets[0];
gbest3[0] = g3Particles[0].x;
g3Particles[0].fitness = SatisficationValue(g3Particles[0].x, 3, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
for (int i = 1; i < popsize3; i++)
{
g3Particles[i].x = g3Particles[0].x;
g3Particles[i].fitness = g3Particles[0].fitness;
gbest3[i] = g3Particles[i].x;
}
}
else
{
//消费层次为1的客流初始化
double douValue = 0;
for (int i = 0; i < popsize1; i++)
{
g1Particles[i].x = strategySets[rand.Next(strategySets.Count)];
g1Particles[i].fitness = SatisficationValue(g1Particles[i].x, 1, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
gbest1[i] = g1Particles[i].x;
douValue += g1Particles[i].fitness;
}
//消费层次为2的客流初始化
douValue = 0;
for (int i = 0; i < popsize2; i++)
{
g2Particles[i].x = strategySets[rand.Next(strategySets.Count)];
g2Particles[i].fitness = SatisficationValue(g2Particles[i].x, 2, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
gbest2[i] = g2Particles[i].x;
douValue += g2Particles[i].fitness;
}
//消费层次为3的客流初始化
douValue = 0;
for (int i = 0; i < popsize3; i++)
{
g3Particles[i].x = strategySets[rand.Next(strategySets.Count)];
g3Particles[i].fitness = SatisficationValue(g3Particles[i].x, 3, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
gbest3[i] = g3Particles[i].x;
douValue += g3Particles[i].fitness;
}
}
//算法开始迭代
RunIteration(g1Particles, 1, strategySets, sectionIndex, startStationIndex, endStationIndex,
startStation, endStation, xchromosome);
RunIteration(g2Particles, 2, strategySets, sectionIndex, startStationIndex, endStationIndex,
startStation, endStation, xchromosome);
RunIteration(g3Particles, 3, strategySets, sectionIndex, startStationIndex, endStationIndex,
startStation, endStation, xchromosome);
}
/// <summary>
/// 铁路旅客满意度评价函数
/// </summary>
/// <param name="_trainType">列车种类</param>
/// <param name="_costLevel">消费层次</param>
/// <param name="_sectionIndex">博弈区段下标</param>
/// <param name="_startStationIndex">O点对应数组下标</param>
/// <param name="_endStationIndex">D点对应数组下标</param>
/// <param name="_oStation">O点</param>
/// <param name="_dStation">D点</param>
/// <param name="_xchromosome">上层解个体</param>
/// <returns>满意度值</returns>
double SatisficationValue(int _trainType, int _costLevel, int _sectionIndex, int _startStationIndex,
int _endStationIndex, int _oStation, int _dStation, Chromosome _xchromosome)
{
double ticketSatiVal = 0;//票价满意度
double timeSatiVal = 0;//时间满意度
double distance = IJDistance(_oStation, _dStation);//OD距离
//若为一站直达列车
if (_trainType == 1)
{
ticketSatiVal = ticketRate[_costLevel - 1, _trainType - 1] * distance;
if (_costLevel == 1)
{
timeSatiVal = w1 * 1.0 * distance / velocity;
return lamda11 * ticketSatiVal + lamda12 * timeSatiVal;
}
else if (_costLevel == 2)
{
timeSatiVal = w2 * 1.0 * distance / velocity;
return lamda21 * ticketSatiVal + lamda22 * timeSatiVal;
}
else
{
timeSatiVal = w3 * 1.0 * distance / velocity;
return lamda31 * ticketSatiVal + lamda32 * timeSatiVal;
}
}
//若为大站停列车
else if (_trainType == 2)
{
int middleStop = 0;
for (int i = 0; i < bigStation.Length; i++)
{
if (_oStation < bigStation[i] && bigStation[i] < _dStation)
{
middleStop += 1;
}
}
ticketSatiVal = ticketRate[_costLevel - 1, _trainType - 1] * distance;
if (_costLevel == 1)
{
timeSatiVal = w1 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda11 * ticketSatiVal + lamda12 * timeSatiVal;
}
else if (_costLevel == 2)
{
timeSatiVal = w2 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda21 * ticketSatiVal + lamda22 * timeSatiVal;
}
else
{
timeSatiVal = w3 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda31 * ticketSatiVal + lamda32 * timeSatiVal;
}
}
//若为择站停列车
else if (_trainType == 3)
{
int middleStop = 0;
for (int i = _startStationIndex + 1; i < _endStationIndex; i++)
{
if (_xchromosome.x[_sectionIndex][i] == 1)
{
middleStop += 1;
}
}
ticketSatiVal = ticketRate[_costLevel - 1, _trainType - 1] * distance;
if (_costLevel == 1)
{
timeSatiVal = w1 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda11 * ticketSatiVal + lamda12 * timeSatiVal;
}
else if (_costLevel == 2)
{
timeSatiVal = w2 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda21 * ticketSatiVal + lamda22 * timeSatiVal;
}
else
{
timeSatiVal = w3 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda31 * ticketSatiVal + lamda32 * timeSatiVal;
}
}
//若为站站停列车
else
{
int middleStop = 0;
if (_xchromosome.x[_sectionIndex].Length == 2)
middleStop = 0;
else
middleStop = _endStationIndex - _startStationIndex - 1;
ticketSatiVal = ticketRate[_costLevel - 1, _trainType - 1] * distance;
if (_costLevel == 1)
{
timeSatiVal = w1 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda11 * ticketSatiVal + lamda12 * timeSatiVal;
}
else if (_costLevel == 2)
{
timeSatiVal = w2 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda21 * ticketSatiVal + lamda22 * timeSatiVal;
}
else
{
timeSatiVal = w3 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda31 * ticketSatiVal + lamda32 * timeSatiVal;
}
}
}
/// <summary>
/// QPSO程序迭代器
/// </summary>
/// <param name="_particles">粒子种群</param>
/// <param name="_costLevel">消费层次</param>
/// <param name="_strategySets">可选策略集</param>
/// <param name="_sectionIndex">开行区段索引下标</param>
/// <param name="_startStationIndex">O点对应数组下标</param>
/// <param name="_endStationIndex">D点对应数组下标</param>
/// <param name="_oStation">O点</param>
/// <param name="_dStation">D点</param>
/// <param name="_xchromosome">上层解个体</param>
void RunIteration(Particles[] _particles, int _costLevel, List<int> _strategySets,
int _sectionIndex, int _startStationIndex, int _endStationIndex, int _oStation,
int _dStation, Chromosome _xchromosome)
{
//字段
double a;//QPSO迭代式中的收缩-扩张系数值
double douMax;//群体最大值
int douMaxIndex;//群体最大值下标
double douGest;//客流个体的较优策略--QPSO迭代式中的局部吸引子
double douMBest;//QPSO迭代式中的平均最好位置
double u;//QPSO迭代式中的随机变量,服从U(0,1)
double b;//QPSO迭代式中的特征长度
double v;//QPSO迭代式中的Log值
double z;//迭代结果小数部分
//循环迭代
double[] douBestStrategy = new double[_strategySets.Count];//各个策略对应赢得函数值
double douValueStrategy = double.MaxValue;//最优策略函数值
int douIndexStrategy = -1;//最优策略
for (int i = 0; i < douBestStrategy.Length; i++)//寻找最优策略及其下标
{
douBestStrategy[i] = SatisficationValue(_strategySets[i], _costLevel,
_sectionIndex, _startStationIndex, _endStationIndex, _oStation,
_dStation, _xchromosome);
if (douBestStrategy[i] < douValueStrategy)
{
douValueStrategy = douBestStrategy[i];
douIndexStrategy = i;
}
}
int t = 0;
while (t <= int.MaxValue)//循环迭代,寻找纳什均衡策略
{
a = (1.0 - 0.5) * (int.MaxValue - t) / int.MaxValue + 0.5;//收缩-扩张系数值
douMax = _particles[0].fitness;
douMaxIndex = 0;
//寻找适应度值最差粒子
for (int i = 1; i < _particles.Length; i++)
{
if (_particles[i].fitness > douMax)
{
douMax = _particles[i].fitness;
douMaxIndex = i;
}
}
//迭代公式
douGest = 0;
douMBest = 0;
if (_costLevel == 1)
{
douGest = gbest1[douMaxIndex];
}
else if (_costLevel == 2)
{
douGest = gbest2[douMaxIndex];
}
else
{
douGest = gbest3[douMaxIndex];
}
for (int i = 0; i < _particles.Length; i++)
{
douMBest += _particles[i].x;
}
douMBest = douMBest * 1.0 / _particles.Length;
u = rand.NextDouble();
b = 2 * a * Math.Abs(douMBest - _particles[douMaxIndex].x);
v = Math.Log(1.0 / u);
z = ((douGest + (b / 2) * v) * 1.0) % Math.Floor(douGest + (b / 2) * v);
//更新粒子位置
if (z > rand.NextDouble())
_particles[douMaxIndex].x = (int)Math.Floor(douGest + b * v);
else
_particles[douMaxIndex].x = (int)Math.Floor(douGest - b * v);
//粒子位置限制在搜索范围内
bool inContainStrategySets = false;//粒子更新解是否包含在策略空间中
//若粒子更新解不在策略空间中,则在策略空间中选择较优策略
for (int i = 0; i < _strategySets.Count; i++)
{
if (_particles[douMaxIndex].x == _strategySets[i])
{
inContainStrategySets = true;
break;
}
}
if (inContainStrategySets == false)
{
_particles[douMaxIndex].x = _strategySets[douIndexStrategy];
}
_particles[douMaxIndex].fitness = SatisficationValue(_particles[douMaxIndex].x,
_costLevel, _sectionIndex, _startStationIndex, _endStationIndex, _oStation,
_dStation, _xchromosome);
if (_costLevel == 1)
{
gbestfitness1 = SatisficationValue(gbest1[douMaxIndex],
_costLevel, _sectionIndex, _startStationIndex, _endStationIndex, _oStation,
_dStation, _xchromosome);
if (_particles[douMaxIndex].fitness < gbestfitness1)
{
gbest1[douMaxIndex] = _particles[douMaxIndex].x;
}
else
{
gbest1[douMaxIndex] = _strategySets[douIndexStrategy];
}
}
else if (_costLevel == 2)
{
gbestfitness2 = SatisficationValue(gbest2[douMaxIndex],
_costLevel, _sectionIndex, _startStationIndex, _endStationIndex, _oStation,
_dStation, _xchromosome);
if (_particles[douMaxIndex].fitness < gbestfitness2)
{
gbest2[douMaxIndex] = _particles[douMaxIndex].x;
}
else
{
gbest2[douMaxIndex] = _strategySets[douIndexStrategy];
}
}
else
{
gbestfitness3 = SatisficationValue(gbest3[douMaxIndex],
_costLevel, _sectionIndex, _startStationIndex, _endStationIndex, _oStation,
_dStation, _xchromosome);
if (_particles[douMaxIndex].fitness < gbestfitness3)
{
gbest3[douMaxIndex] = _particles[douMaxIndex].x;
}
else
{
gbest3[douMaxIndex] = _strategySets[douIndexStrategy];
}
}
bool intNashNum = true;//判断是否实现了纳什均衡
if (_costLevel == 1)
{
for (int i = 1; i < _particles.Length; i++)
{
if (gbest1[i] != gbest1[0])
{
intNashNum = false;
break;
}
}
}
else if (_costLevel == 2)
{
for (int i = 1; i < _particles.Length; i++)
{
if (gbest2[i] != gbest2[0])
{
intNashNum = false;
break;
}
}
}
else
{
for (int i = 1; i < _particles.Length; i++)
{
if (gbest3[i] != gbest3[0])
{
intNashNum = false;
break;
}
}
}
if (intNashNum == false)
{
t++;
}
else
{
break;
}
}
//写入数据集ds中
dt = new DataTable();
//构建表结构
dt.Columns.Add("Factors", typeof(Int32));
dt.Columns.Add("1", typeof(Int32));
dt.Columns.Add("2", typeof(Int32));
dt.Columns.Add("3", typeof(Int32));
dt.Columns.Add("4", typeof(Int32));
DataRow dr;
for (int i = 0; i < trainDepartureSection.GetLength(0); i++)
{
dr = dt.NewRow();
dr[0] = i + 1;
for (int j = 1; j < dt.Columns.Count; j++)
{
dr[j] = 0;
}
dt.Rows.Add(dr);
}
int intColumn = 0;
if (_costLevel == 1)
{
intColumn = gbest1[0];
}
else if (_costLevel == 2)
{
intColumn = gbest2[0];
}
else
{
intColumn = gbest3[0];
}
dt.Rows[_sectionIndex][intColumn] = _particles.Length;
ds[upperSolutionIndex].Tables.Add(dt);
ds[upperSolutionIndex].Tables[ds[upperSolutionIndex].Tables.Count - 1].TableName =
_oStation.ToString() + "-" + _dStation + "g" + _costLevel.ToString() + "Customer";
}
/// <summary>
/// 列车开行频率
/// </summary>
/// <returns>列车开行数量</returns>
internal int[,] TrainRunningFrequency(DataSet _ds)
{
int[,] intqT = new int[NSGA_Ⅱ.pLNum, NSGA_Ⅱ.trainType];//列车开行频率
int intMaxValue;//区间最大客流量
int[] sectionStation;//开行区段站点集合
int[] sectionCustomer;//乘坐某一类列车的各区间客流数集合
for (int i = 0; i < trainDepartureSection.GetLength(0); i++)
{
intMaxValue = 0;
sectionStation = new int[trainDepartureSection[i].Length];
sectionCustomer = new int[trainDepartureSection[i].Length - 1];
for (int j = 0; j < sectionStation.Length; j++)
{
sectionStation[j] = trainDepartureSection[i][j];
}
for (int m = 0; m < intqT.GetLength(1); m++)
{
int douValueCustomer;//区间客流总和
string strTableName1 = "";//表名
string strTableName2 = "";
string strTableName3 = "";
for (int j = 0; j < sectionCustomer.Length; j++)
{
douValueCustomer = 0;
for (int k = 0; k <= j; k++)
{
for (int l = j + 1; l < sectionStation.Length; l++)
{
strTableName1 = sectionStation[k].ToString() + "-" +
sectionStation[l].ToString() + "g1Customer";
strTableName2 = sectionStation[k].ToString() + "-" +
sectionStation[l].ToString() + "g2Customer";
strTableName3 = sectionStation[k].ToString() + "-" +
sectionStation[l].ToString() + "g3Customer";
for (int p = 0; p < intqT.GetLength(0); p++)
{
douValueCustomer += Convert.ToInt32(_ds.Tables[strTableName1].Rows[p][m + 1]) +
Convert.ToInt32(_ds.Tables[strTableName2].Rows[p][m + 1]) +
Convert.ToInt32(_ds.Tables[strTableName3].Rows[p][m + 1]);
}
}
}
sectionCustomer[j] = douValueCustomer;
}
intMaxValue = sectionCustomer[0];
for (int j = 1; j < sectionCustomer.Length; j++)
{
if (sectionCustomer[j] > intMaxValue)
{
intMaxValue = sectionCustomer[j];
}
}
intqT[i, m] = Convert.ToInt32(Math.Floor(intMaxValue * douCustomerFluctuateRate / (seatNum * (alphMax + alphMin) / 2)));
}
}
return intqT;
}
}
3.编写求解下层非合作博弈的QPSO算法,各算子针对模型设计
public class LowerCustomerAssigned
{
internal List<Chromosome> iterValue = new List<Chromosome>();//输出对象
public struct Particles //定义粒子的结构体
{
public int x;//粒子当前位置(选择的列车种类)
public double fitness;//粒子的当前位置适应值
}
//全局变量定义
static int popsize1;//消费水平层次为1的群体规模
static int popsize2;//消费水平层次为2的群体规模
static int popsize3;//消费水平层次为3的群体规模
Particles[] g1Particles;//消费水平层次为1的客流个体集合
Particles[] g2Particles;//消费水平层次为2的客流个体集合
Particles[] g3Particles;//消费水平层次为3的客流个体集合
int[] gbest1;//消费层次为1的客流局势
int[] gbest2;//消费层次为2的客流局势
int[] gbest3;//消费层次为3的客流局势
double gbestfitness1;//消费水平层次为1的赢得函数值
double gbestfitness2;//消费水平层次为2的赢得函数值
double gbestfitness3;//消费水平层次为3的赢得函数值
Random rand = new Random();//随机数产生器
LinkExcel _linkExcel = new LinkExcel();//表读取对象
internal int upperSolutionIndex = 0;//上层解粒子下标索引
DataTable dt = new DataTable();//数据表
internal DataSet[] ds;//数据集
//string _strDataPath = "客流数据.xlsx";//数据所在相对位置
//下层客流博弈分配全局变量
double w1 = 200, w2 = 100, w3 = 50;//各消费层次客流时间价值系数
double lamda11 = 0.1, lamda12 = 0.9;//消费层次等级为1的客流的权重系数
double lamda21 = 0.5, lamda22 = 0.5;//消费层次等级为2的客流的权重系数
double lamda31 = 0.9, lamda32 = 0.1;//消费层次等级为3的客流的权重系数
//double violationM = 50000;//惩罚函数值
double velocity = 250;//列车速度值
double timeAverage = 4;//在站停留平均时间
int[] bigStation = new int[] { 1, 5, 22 };//客流量较大站点集合
double[,] ticketRate = new double[,] { { 0.9, 0.8, 0.7, 0.6 }, { 0.6, 0.5, 0.4, 0.3 }, { 0.4, 0.3, 0.2, 0.1 } };//票价率
internal NSGA_Ⅱ upperObject = new NSGA_Ⅱ();//上层对象
//方法定义
int sectionIndex = 0;//客流博弈所在开行区段下标
List<int> sectionListIndexSets = new List<int>();//始发、终到站均含于相同开行区段的开行区段下标集合
List<int> strategySets = new List<int>();//策略集
/// <summary>
/// OD客流选择列车出行博弈方法
/// </summary>
/// <param name="xchromosome">上层解粒子</param>
/// <param name="g1CustomerNum">消费层次为1的OD客流规模</param>
/// <param name="g2CustomerNum">消费层次为2的OD客流规模</param>
/// <param name="g3CustomerNum">消费层次为3的OD客流规模</param>
/// <param name="startStation">O点</param>
/// <param name="endStation">D点</param>
internal void customersAssigned(Chromosome xchromosome, int g1CustomerNum, int g2CustomerNum,
int g3CustomerNum, int startStation, int endStation)
{
sectionIndex = 0;//开行区段索引赋初值
sectionListIndexSets.Clear();//清空开行区段索引集合
strategySets.Clear();//清空策略集
for (int i = 0; i < xchromosome.x.GetLength(0); i++)//填充均包含O、D的开行区段下标集合
{
if (upperObject.trainDepartureSection[i][0] <= startStation &&
upperObject.trainDepartureSection[i][xchromosome.x[i].Length - 1] >= endStation)
{
sectionListIndexSets.Add(i);
}
}
//随机选择一个同时包含起始、终点站的列车开行区段
sectionIndex = sectionListIndexSets[rand.Next(sectionListIndexSets.Count)];
//填充策略集StrategySets
//--一站直达
if (startStation == upperObject.trainDepartureSection[sectionIndex][0] &&
endStation == upperObject.trainDepartureSection[sectionIndex][upperObject.trainDepartureSection[sectionIndex].Length - 1])
{
strategySets.Add(1);
}
//--大站停
int isAllbigStation = 0;//指标--指示OD客流是否可以乘坐大站停列车完成出现
for (int i = 0; i < bigStation.Length; i++)
{
if (startStation == bigStation[i])
{
isAllbigStation += 1;
continue;
}
if (endStation == bigStation[i])
{
isAllbigStation += 1;
break;
}
}
if (isAllbigStation == 2)
{
strategySets.Add(2);
}
//--择站停
int startStationIndex = 0;//客流出发站的站点在x解集中对应的下标
int endStationIndex = 0;//客流终到站的站点在x解集中对应的下标
for (int i = 0; i < upperObject.trainDepartureSection[sectionIndex].Length; i++)
{
if (upperObject.trainDepartureSection[sectionIndex][i] == startStation)
{
startStationIndex = i;
continue;
}
if (upperObject.trainDepartureSection[sectionIndex][i] == endStation)
{
endStationIndex = i;
break;
}
}
if (xchromosome.x[sectionIndex][startStationIndex] == 1 && xchromosome.x[sectionIndex][endStationIndex] == 1)
strategySets.Add(3);
//--站站停:对OD(始发站为startStation,终点站为endStation)来说,站站停列车为必备策略
strategySets.Add(4);
//客流列车分配初始化
popsize1 = g1CustomerNum;//初始化各消费层次客流规模
popsize2 = g2CustomerNum;
popsize3 = g3CustomerNum;
g1Particles = new Particles[popsize1];//创建各消费层次客流集合
g2Particles = new Particles[popsize2];
g3Particles = new Particles[popsize3];
gbest1 = new int[popsize1];//创建各消费层次客流局势
gbest2 = new int[popsize2];
gbest3 = new int[popsize3];
//分情况初始化各消费层次客流出行列车选择
if (strategySets.Count == 1)
{
//消费层次为1的客流初始化
g1Particles[0].x = strategySets[0];
gbest1[0] = g1Particles[0].x;
g1Particles[0].fitness = SatisficationValue(g1Particles[0].x, 1, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
for (int i = 1; i < popsize1; i++)
{
g1Particles[i].x = g1Particles[0].x;
g1Particles[i].fitness = g1Particles[0].fitness;
gbest1[i] = g1Particles[i].x;
}
//消费层次为2的客流初始化
g2Particles[0].x = strategySets[0];
gbest2[0] = g2Particles[0].x;
g2Particles[0].fitness = SatisficationValue(g2Particles[0].x, 2, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
for (int i = 1; i < popsize2; i++)
{
g2Particles[i].x = g2Particles[0].x;
g2Particles[i].fitness = g2Particles[0].fitness;
gbest2[i] = g2Particles[i].x;
}
//消费层次为3的客流初始化
g3Particles[0].x = strategySets[0];
gbest3[0] = g3Particles[0].x;
g3Particles[0].fitness = SatisficationValue(g3Particles[0].x, 3, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
for (int i = 1; i < popsize3; i++)
{
g3Particles[i].x = g3Particles[0].x;
g3Particles[i].fitness = g3Particles[0].fitness;
gbest3[i] = g3Particles[i].x;
}
}
else
{
//消费层次为1的客流初始化
double douValue = 0;
for (int i = 0; i < popsize1; i++)
{
g1Particles[i].x = strategySets[rand.Next(strategySets.Count)];
g1Particles[i].fitness = SatisficationValue(g1Particles[i].x, 1, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
gbest1[i] = g1Particles[i].x;
douValue += g1Particles[i].fitness;
}
//消费层次为2的客流初始化
douValue = 0;
for (int i = 0; i < popsize2; i++)
{
g2Particles[i].x = strategySets[rand.Next(strategySets.Count)];
g2Particles[i].fitness = SatisficationValue(g2Particles[i].x, 2, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
gbest2[i] = g2Particles[i].x;
douValue += g2Particles[i].fitness;
}
//消费层次为3的客流初始化
douValue = 0;
for (int i = 0; i < popsize3; i++)
{
g3Particles[i].x = strategySets[rand.Next(strategySets.Count)];
g3Particles[i].fitness = SatisficationValue(g3Particles[i].x, 3, sectionIndex, startStationIndex,
endStationIndex, startStation, endStation, xchromosome);
gbest3[i] = g3Particles[i].x;
douValue += g3Particles[i].fitness;
}
}
//算法开始迭代
RunIteration(g1Particles, 1, strategySets, sectionIndex, startStationIndex, endStationIndex,
startStation, endStation, xchromosome);
RunIteration(g2Particles, 2, strategySets, sectionIndex, startStationIndex, endStationIndex,
startStation, endStation, xchromosome);
RunIteration(g3Particles, 3, strategySets, sectionIndex, startStationIndex, endStationIndex,
startStation, endStation, xchromosome);
}
/// <summary>
/// 铁路旅客满意度评价函数
/// </summary>
/// <param name="_trainType">列车种类</param>
/// <param name="_costLevel">消费层次</param>
/// <param name="_sectionIndex">博弈区段下标</param>
/// <param name="_startStationIndex">O点对应数组下标</param>
/// <param name="_endStationIndex">D点对应数组下标</param>
/// <param name="_oStation">O点</param>
/// <param name="_dStation">D点</param>
/// <param name="_xchromosome">上层解个体</param>
/// <returns>满意度值</returns>
double SatisficationValue(int _trainType, int _costLevel, int _sectionIndex, int _startStationIndex,
int _endStationIndex, int _oStation, int _dStation, Chromosome _xchromosome)
{
double ticketSatiVal = 0;//票价满意度
double timeSatiVal = 0;//时间满意度
double distance = upperObject.IJDistance(_oStation, _dStation);//OD距离
//若为一站直达列车
if (_trainType == 1)
{
ticketSatiVal = ticketRate[_costLevel - 1, _trainType - 1] * distance;
if (_costLevel == 1)
{
timeSatiVal = w1 * 1.0 * distance / velocity;
return lamda11 * ticketSatiVal + lamda12 * timeSatiVal;
}
else if (_costLevel == 2)
{
timeSatiVal = w2 * 1.0 * distance / velocity;
return lamda21 * ticketSatiVal + lamda22 * timeSatiVal;
}
else
{
timeSatiVal = w3 * 1.0 * distance / velocity;
return lamda31 * ticketSatiVal + lamda32 * timeSatiVal;
}
}
//若为大站停列车
else if (_trainType == 2)
{
int middleStop = 0;
for (int i = 0; i < bigStation.Length; i++)
{
if (_oStation < bigStation[i] && bigStation[i] < _dStation)
{
middleStop += 1;
}
}
ticketSatiVal = ticketRate[_costLevel - 1, _trainType - 1] * distance;
if (_costLevel == 1)
{
timeSatiVal = w1 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda11 * ticketSatiVal + lamda12 * timeSatiVal;
}
else if (_costLevel == 2)
{
timeSatiVal = w2 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda21 * ticketSatiVal + lamda22 * timeSatiVal;
}
else
{
timeSatiVal = w3 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda31 * ticketSatiVal + lamda32 * timeSatiVal;
}
}
//若为择站停列车
else if (_trainType == 3)
{
int middleStop = 0;
for (int i = _startStationIndex + 1; i < _endStationIndex; i++)
{
if (_xchromosome.x[_sectionIndex][i] == 1)
{
middleStop += 1;
}
}
ticketSatiVal = ticketRate[_costLevel - 1, _trainType - 1] * distance;
if (_costLevel == 1)
{
timeSatiVal = w1 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda11 * ticketSatiVal + lamda12 * timeSatiVal;
}
else if (_costLevel == 2)
{
timeSatiVal = w2 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda21 * ticketSatiVal + lamda22 * timeSatiVal;
}
else
{
timeSatiVal = w3 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda31 * ticketSatiVal + lamda32 * timeSatiVal;
}
}
//若为站站停列车
else
{
int middleStop = 0;
if (_xchromosome.x[_sectionIndex].Length == 2)
middleStop = 0;
else
middleStop = _endStationIndex - _startStationIndex - 1;
ticketSatiVal = ticketRate[_costLevel - 1, _trainType - 1] * distance;
if (_costLevel == 1)
{
timeSatiVal = w1 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda11 * ticketSatiVal + lamda12 * timeSatiVal;
}
else if (_costLevel == 2)
{
timeSatiVal = w2 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda21 * ticketSatiVal + lamda22 * timeSatiVal;
}
else
{
timeSatiVal = w3 * (1.0 * distance / velocity + timeAverage * middleStop);
return lamda31 * ticketSatiVal + lamda32 * timeSatiVal;
}
}
}
/// <summary>
/// QPSO程序迭代器
/// </summary>
/// <param name="_particles">粒子种群</param>
/// <param name="_costLevel">消费层次</param>
/// <param name="_strategySets">可选策略集</param>
/// <param name="_sectionIndex">开行区段索引下标</param>
/// <param name="_startStationIndex">O点对应数组下标</param>
/// <param name="_endStationIndex">D点对应数组下标</param>
/// <param name="_oStation">O点</param>
/// <param name="_dStation">D点</param>
/// <param name="_xchromosome">上层解个体</param>
void RunIteration(Particles[] _particles, int _costLevel, List<int> _strategySets,
int _sectionIndex, int _startStationIndex, int _endStationIndex, int _oStation,
int _dStation, Chromosome _xchromosome)
{
//字段
double a;//QPSO迭代式中的收缩-扩张系数值
double douMax;//群体最大值
int douMaxIndex;//群体最大值下标
double douGest;//客流个体的较优策略--QPSO迭代式中的局部吸引子
double douMBest;//QPSO迭代式中的平均最好位置
double u;//QPSO迭代式中的随机变量,服从U(0,1)
double b;//QPSO迭代式中的特征长度
double v;//QPSO迭代式中的Log值
double z;//迭代结果小数部分
//循环迭代
double[] douBestStrategy = new double[_strategySets.Count];//各个策略对应赢得函数值
double douValueStrategy = double.MaxValue;//最优策略函数值
int douIndexStrategy = -1;//最优策略
for (int i = 0; i < douBestStrategy.Length; i++)//寻找最优策略及其下标
{
douBestStrategy[i] = SatisficationValue(_strategySets[i], _costLevel,
_sectionIndex, _startStationIndex, _endStationIndex, _oStation,
_dStation, _xchromosome);
if (douBestStrategy[i] < douValueStrategy)
{
douValueStrategy = douBestStrategy[i];
douIndexStrategy = i;
}
}
int t = 0;
while (t <= int.MaxValue)//循环迭代,寻找纳什均衡策略
{
a = (1.0 - 0.5) * (int.MaxValue - t) / int.MaxValue + 0.5;//收缩-扩张系数值
douMax = _particles[0].fitness;
douMaxIndex = 0;
//寻找适应度值最差粒子
for (int i = 1; i < _particles.Length; i++)
{
if (_particles[i].fitness > douMax)
{
douMax = _particles[i].fitness;
douMaxIndex = i;
}
}
//迭代公式
douGest = 0;
douMBest = 0;
if (_costLevel == 1)
{
douGest = gbest1[douMaxIndex];
}
else if (_costLevel == 2)
{
douGest = gbest2[douMaxIndex];
}
else
{
douGest = gbest3[douMaxIndex];
}
for (int i = 0; i < _particles.Length; i++)
{
douMBest += _particles[i].x;
}
douMBest = douMBest * 1.0 / _particles.Length;
u = rand.NextDouble();
b = 2 * a * Math.Abs(douMBest - _particles[douMaxIndex].x);
v = Math.Log(1.0 / u);
z = ((douGest + (b / 2) * v) * 1.0) % Math.Floor(douGest + (b / 2) * v);
//更新粒子位置
if (z > rand.NextDouble())
_particles[douMaxIndex].x = (int)Math.Floor(douGest + b * v);
else
_particles[douMaxIndex].x = (int)Math.Floor(douGest - b * v);
//粒子位置限制在搜索范围内
bool inContainStrategySets = false;//粒子更新解是否包含在策略空间中
//若粒子更新解不在策略空间中,则在策略空间中选择较优策略
for (int i = 0; i < _strategySets.Count; i++)
{
if (_particles[douMaxIndex].x == _strategySets[i])
{
inContainStrategySets = true;
break;
}
}
if (inContainStrategySets == false)
{
_particles[douMaxIndex].x = _strategySets[douIndexStrategy];
}
_particles[douMaxIndex].fitness = SatisficationValue(_particles[douMaxIndex].x,
_costLevel, _sectionIndex, _startStationIndex, _endStationIndex, _oStation,
_dStation, _xchromosome);
if (_costLevel == 1)
{
gbestfitness1 = SatisficationValue(gbest1[douMaxIndex],
_costLevel, _sectionIndex, _startStationIndex, _endStationIndex, _oStation,
_dStation, _xchromosome);
if (_particles[douMaxIndex].fitness < gbestfitness1)
{
gbest1[douMaxIndex] = _particles[douMaxIndex].x;
}
else
{
gbest1[douMaxIndex] = _strategySets[douIndexStrategy];
}
}
else if (_costLevel == 2)
{
gbestfitness2 = SatisficationValue(gbest2[douMaxIndex],
_costLevel, _sectionIndex, _startStationIndex, _endStationIndex, _oStation,
_dStation, _xchromosome);
if (_particles[douMaxIndex].fitness < gbestfitness2)
{
gbest2[douMaxIndex] = _particles[douMaxIndex].x;
}
else
{
gbest2[douMaxIndex] = _strategySets[douIndexStrategy];
}
}
else
{
gbestfitness3 = SatisficationValue(gbest3[douMaxIndex],
_costLevel, _sectionIndex, _startStationIndex, _endStationIndex, _oStation,
_dStation, _xchromosome);
if (_particles[douMaxIndex].fitness < gbestfitness3)
{
gbest3[douMaxIndex] = _particles[douMaxIndex].x;
}
else
{
gbest3[douMaxIndex] = _strategySets[douIndexStrategy];
}
}
bool intNashNum = true;//判断是否实现了纳什均衡
if (_costLevel == 1)
{
for (int i = 1; i < _particles.Length; i++)
{
if (gbest1[i] != gbest1[0])
{
intNashNum = false;
break;
}
}
}
else if (_costLevel == 2)
{
for (int i = 1; i < _particles.Length; i++)
{
if (gbest2[i] != gbest2[0])
{
intNashNum = false;
break;
}
}
}
else
{
for (int i = 1; i < _particles.Length; i++)
{
if (gbest3[i] != gbest3[0])
{
intNashNum = false;
break;
}
}
}
if (intNashNum == false)
{
t++;
}
else
{
break;
}
}
//写入数据集ds中
dt = new DataTable();
//构建表结构
dt.Columns.Add("Factors", typeof(Int32));
dt.Columns.Add("1", typeof(Int32));
dt.Columns.Add("2", typeof(Int32));
dt.Columns.Add("3", typeof(Int32));
dt.Columns.Add("4", typeof(Int32));
DataRow dr;
for (int i = 0; i < upperObject.trainDepartureSection.GetLength(0); i++)
{
dr = dt.NewRow();
dr[0] = i + 1;
for (int j = 1; j < dt.Columns.Count; j++)
{
dr[j] = 0;
}
dt.Rows.Add(dr);
}
int intColumn = 0;
if (_costLevel == 1)
{
intColumn = gbest1[0];
}
else if (_costLevel == 2)
{
intColumn = gbest2[0];
}
else
{
intColumn = gbest3[0];
}
dt.Rows[_sectionIndex][intColumn] = _particles.Length;
ds[upperSolutionIndex].Tables.Add(dt);
ds[upperSolutionIndex].Tables[ds[upperSolutionIndex].Tables.Count - 1].TableName =
_oStation.ToString() + "-" + _dStation + "g" + _costLevel.ToString() + "Customer";
}
/// <summary>
/// 双层规划算法迭代
/// </summary>
public void BiLevelAlgorithmRunning()
{
//下层数据集个数--数量与种群规模一致
ds = new DataSet[upperObject.chromosomes.Length];
//上层解粒子索引
upperSolutionIndex = 0;
//上层解集初始化
upperObject.UpperInitation();
//针对每一个上层解,求下层客流分配纳什均衡解及上层函数
for (int i = 0; i < upperObject.chromosomes.Length; i++)
{
upperSolutionIndex = i;//记录当前上层解粒子索引
ds[upperSolutionIndex] = new DataSet();
for (int j = 1; j < NSGA_Ⅱ.stationNum; j++)//客流博弈分配
{
for (int k = j + 1; k <= NSGA_Ⅱ.stationNum; k++)
{
customersAssigned(upperObject.chromosomes[upperSolutionIndex], upperObject.g1Customer[j - 1, k - 1],
upperObject.g2Customer[j - 1, k - 1], upperObject.g3Customer[j - 1, k - 1], j, k);
}
}
//根据旅客分配情况确定列车开行频率
upperObject.chromosomes[upperSolutionIndex].Frequent = new int[NSGA_Ⅱ.pLNum, NSGA_Ⅱ.trainType];
upperObject.chromosomes[upperSolutionIndex].Frequent = TrainRunningFrequency(ds[upperSolutionIndex]);
//根据旅客分配情况确定上层各函数值
upperObject.chromosomes[upperSolutionIndex].f = new double[NSGA_Ⅱ.f_num];
upperObject.dSCustomer = ds[upperSolutionIndex];
upperObject.chromosomes[upperSolutionIndex].f[0] =
upperObject.F1Object(upperObject.chromosomes[upperSolutionIndex]);
upperObject.chromosomes[upperSolutionIndex].f[1] =
upperObject.F2Object(upperObject.chromosomes[upperSolutionIndex]);
}
//非支配排序算子
upperObject.NonDominationSort(upperObject.chromosomes);
//拥挤度算子
upperObject.CrowdingDistanceSort(upperObject.f_sort);
//锦标赛选择算子
Chromosome[] chro = new Chromosome[upperObject.chromosomes.Length];
chro = upperObject.TournamentSelection(upperObject.chromosomes);
//交叉、变异算子
upperObject.NewChromosomes(chro);
//下一代种群形成
upperObject.Elitism(upperObject.f_sort, upperObject.c_sort);
double d = 0;
//_linkExcel.DSToExcel(_strDataPath, ds);
}
/// <summary>
/// 列车开行频率
/// </summary>
/// <returns>列车开行数量</returns>
internal int[,] TrainRunningFrequency(DataSet _ds)
{
int[,] intqT = new int[NSGA_Ⅱ.pLNum, NSGA_Ⅱ.trainType];//列车开行频率
int intMaxValue;//区间最大客流量
int[] sectionStation;//开行区段站点集合
int[] sectionCustomer;//乘坐某一类列车的各区间客流数集合
for (int i = 0; i < upperObject.trainDepartureSection.GetLength(0); i++)
{
intMaxValue = 0;
sectionStation = new int[upperObject.trainDepartureSection[i].Length];
sectionCustomer = new int[upperObject.trainDepartureSection[i].Length - 1];
for (int j = 0; j < sectionStation.Length; j++)
{
sectionStation[j] = upperObject.trainDepartureSection[i][j];
}
for (int m = 0; m < intqT.GetLength(1); m++)
{
int douValueCustomer;//区间客流总和
string strTableName1 = "";//表名
string strTableName2 = "";
string strTableName3 = "";
for (int j = 0; j < sectionCustomer.Length; j++)
{
douValueCustomer = 0;
for (int k = 0; k <= j; k++)
{
for (int l = j + 1; l < sectionStation.Length; l++)
{
strTableName1 = sectionStation[k].ToString() + "-" +
sectionStation[l].ToString() + "g1Customer";
strTableName2 = sectionStation[k].ToString() + "-" +
sectionStation[l].ToString() + "g2Customer";
strTableName3 = sectionStation[k].ToString() + "-" +
sectionStation[l].ToString() + "g3Customer";
for (int p = 0; p < intqT.GetLength(0); p++)
{
douValueCustomer += Convert.ToInt32(_ds.Tables[strTableName1].Rows[p][m + 1]) +
Convert.ToInt32(_ds.Tables[strTableName2].Rows[p][m + 1]) +
Convert.ToInt32(_ds.Tables[strTableName3].Rows[p][m + 1]);
}
}
}
sectionCustomer[j] = douValueCustomer;
}
intMaxValue = sectionCustomer[0];
for (int j = 1; j < sectionCustomer.Length; j++)
{
if (sectionCustomer[j] > intMaxValue)
{
intMaxValue = sectionCustomer[j];
}
}
intqT[i, m] = Convert.ToInt32(Math.Floor(intMaxValue * upperObject.douCustomerFluctuateRate / (upperObject.seatNum * (upperObject.alphMax + upperObject.alphMin) / 2)));
}
}
return intqT;
}
}
3.运行程序
private void Form1_Load(object sender, EventArgs e)
{
this.Text = "QPSO(Test)";
this.Icon = new Icon(@"E:\VS2017\Icon\1.ico");
QPSO_Test qPSO_Test = new QPSO_Test();
qPSO_Test.RunAlgorithm();
double[] value = qPSO_Test.Value();
double[] gvalue = qPSO_Test.GValue();
chart1.ChartAreas["ChartArea1"].Name = "MyChartArea";
chart1.ChartAreas["MyChartArea"].AxisX.Interval = 4;
chart1.Series[0].ChartArea = "MyChartArea";
chart1.Series[0].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
chart1.Series[0].Name = "每次运行结果";
chart1.Series.Add("MSeries");
chart1.Series["MSeries"].ChartArea = "MyChartArea";
chart1.Series["MSeries"].ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.FastPoint;
chart1.Series["MSeries"].Color = Color.Red;
chart1.Series["MSeries"].Name = "种群迭代结果";
chart1.Series[1].YAxisType = System.Windows.Forms.DataVisualization.Charting.AxisType.Secondary;
chart1.ChartAreas[0].AxisY2.MajorGrid.Enabled = false;
chart1.ChartAreas[0].AxisY.MajorGrid.Enabled = false;
chart1.ChartAreas[0].AxisX.MajorGrid.Enabled = false;
chart1.Titles.Add("量子粒子群测试");
chart1.Titles[0].Alignment = ContentAlignment.TopCenter;
chart1.Titles[0].Font = new Font(new FontFamily("Arial"), 12, FontStyle.Bold);
chart1.ChartAreas["MyChartArea"].AxisY2.Title = "第50次运行时种群迭代最佳适应值";
chart1.ChartAreas["MyChartArea"].AxisY.Title = "每次运行种群最佳适应值";
chart1.ChartAreas["MyChartArea"].AxisX.Title = "迭代次数";
for (int i = 0; i < 50; i++)
{
chart1.Series[0].Points.AddXY(i + 1, value[i]);
chart1.Series[1].Points.AddXY(i + 1, gvalue[i]);
}
}