由于作为软件工程课pair project II (电梯调度程序)的志愿者,我负责为大家产生至关重要的用于最后评定各个pair的调度程序性能的测试数据(压力好大Disappointed smile)。

完整的源码下载(VS2010):https://files.cnblogs.com/codingcrazy/GenerateElevTestData.rar

1. 要求

详细要求http://www.cnblogs.com/xinz/archive/2010/11/28/1890300.html

3. Testing

TA will simulate a “rush hour” test. The “rush hour” test is to simulate the come-to-work and leave-work scenario in a business building, which has the following 2 parts (they can be run next to each other).

1) Simple test. 20 passengers

    20 people going thru random floors within 5 minutes.

2) Come-to-work.  1000 total passengers

    a) 80% of them goes from floor 0 and 1 to all other floors, the destination is distributed evenly. 

         The time each passenger arrives at the elevator can be emulated as a normal distribution.

    b) 20% of them are going between any 2 floors of [2, 20],  Very few people travel between 2 adjacent floors

         (e.g. from floor 5 to 4).  Other than this, the distribution is also even.

3) Leave-work.  1000 total passengers

    a) 90% of them go from other floors to floor1 or floor0.

    b) 10% of them travel between floors [2, 20], again, Very few people travel between 2 adjacent floors.

测试数据文件格式:XML文档描述的乘客信息,如下:

<?xml version="1.0" encoding="utf-8" ?>

<passengers
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd
="http://www.w3.org/2001/XMLSchema"
xmlns
="http://tempuri.org/passengers.xsd">
<passenger name="SENXIANG" comingtime="50" fromfloor="10" tofloor="20" weight="60" />
<passenger name="Piggy" comingtime="100" fromfloor="1" tofloor="15" weight="75" />
<passenger name="Later" comingtime="10000" fromfloor="99" tofloor="15" weight="45" />
</passengers>

 

2. 正态分布随机数的产生

      根据要求,需要模拟上班时和下班时的电梯乘客情况,使其满足正态分布:即在规定上班之前(下班时间之后)某个时间点乘客达到最高峰,两边依近似正态分布递减。因此,这里的核心需求是:如何产生满足正态分布的随机数?

      这里使用Marsaglia方法(见维基百科:http://en.wikipedia.org/wiki/Normal_distribution,小节:Generating values from normal distribution)。

      原理:Box-Muller方法:设有两个服从均匀分布U(0,1)的独立随机变量U和V,那么由下式得到的X和Y也是独立随机变量,并且都服从正态分布N(0,1)。

\begin{align}
    & X = \sqrt{- 2 \ln U} \, \cos(2 \pi V) , \\
    & Y = \sqrt{- 2 \ln U} \, \sin(2 \pi V) .
  \end{align}

               Marsaglia对Box-Muller方法进行了改进,使其不再需要进行三角函数的计算。Marsaglia使用的U和V是两个服从均匀分布U(-1,1)的独立随机变量,令

S = U2 + V2,如果S>=1则重新计算S,否则下面的X和Y就是服从标准正态分布N(0,1)的独立随机变量:


    X = U\sqrt{\frac{-2\ln S}{S}}, \qquad  Y = V\sqrt{\frac{-2\ln S}{S}}

       下面是按以上算法产生正态分布随机数的类:

//
// Gaussian Random Number Generator class
// ref. http://blog.csdn.net/holym/archive/2006/05/16/741074.aspx
//
public class GaussianRNG
{
int iset;
double gset;
Random r1, r2;

public GaussianRNG()
{
// use unchecked to disable overflow check
r1 = new Random(unchecked((int)DateTime.Now.Ticks));
r2
= new Random(~unchecked((int)DateTime.Now.Ticks));
iset
= 0;
}

// generate Gaussian random numbers of N(0,1)
public double Next()
{
double fac, rsq, v1, v2;
if (iset == 0)
{
do
{
v1
= 2.0 * r1.NextDouble() - 1.0;
v2
= 2.0 * r2.NextDouble() - 1.0;
rsq
= v1 * v1 + v2 * v2;
}
while (rsq >= 1.0 || rsq == 0.0);

fac
= Math.Sqrt(-2.0 * Math.Log(rsq) / rsq);
gset
= v1 * fac;
iset
= 1;
return v2 * fac;
}
else
{
iset
= 0;
return gset;
}
}

// generate Gaussian random numbers of N(mu,sigma)
// Note: the return values are constrained to between (mu-sigma) and (mu+sigma)
public double Next(double mu, double sigma)
{
double x = Next();
while (x < -1 || x > 1)
{
x
= Next();
}
return (mu + x * sigma);
}
}

  

3. XML文件的产生

由于原来测试程序框架中需要在XML中声明命名空间(因为要根据预先定义的xsd文件进行反序列化生成所需的passenger对象)。我没有找到在XML文件中直接写入命名空间的语句。因此偷懒先生成简单的XML文件,再用StreamReader将文件读入,用StreamWriter将其连同命名空间声明一同写入到目标XML文件。如果你有好的方法,请告诉我。下面是生成Come to work测试文件的代码:

static void GenerateData_ComeToWork()
{
Random rnd
= new Random();
GaussianRNG rnd_gaussian
= new GaussianRNG();
int fromfloor;
int tofloor;
int highestFloor = 20;

try
{
using (XmlTextWriter writer = new XmlTextWriter("temp2.xml", null))
{
writer.Formatting
= Formatting.Indented;
writer.WriteStartDocument();
writer.WriteStartElement(
"passengers");
// Generate passenger info
for (int i = 1; i <= 800; i++)
{
writer.WriteStartElement(
"passenger");
writer.WriteAttributeString(
"name", string.Format("Xiao_{0}", i));
// passenger come to work in 1 hour
writer.WriteAttributeString("comingtime", Math.Ceiling(rnd_gaussian.Next(1800, 1800)).ToString());
// fromfloor: 0 or 1
writer.WriteAttributeString("fromfloor", rnd.Next(2).ToString());
// tofloor: [2...20]
writer.WriteAttributeString("tofloor", rnd.Next(2, highestFloor + 1).ToString());
// passenger weight form 45 to 120, average 70
writer.WriteAttributeString("weight", rnd.Next((i <= 400) ? 45 : 70, (i <= 400) ? 70 : 120).ToString());
writer.WriteEndElement();
}
for (int i = 801; i <= 1000; i++)
{
writer.WriteStartElement(
"passenger");
writer.WriteAttributeString(
"name", string.Format("Xiao_{0}", i));
// passenger come to work in 1 hour
writer.WriteAttributeString("comingtime", Math.Ceiling(rnd_gaussian.Next(1800, 1800)).ToString());
// Request: fromfloor != tofloor, very few people travel between adjacent floors
fromfloor = rnd.Next(2, highestFloor + 1);
while ((tofloor = rnd.Next(2, highestFloor + 1)) == fromfloor)
;
if (Math.Abs(fromfloor - tofloor) == 1 && (rnd.Next(101) / 100) < 80)
{
fromfloor
= rnd.Next(2, highestFloor + 1);
while ((tofloor = rnd.Next(2, highestFloor + 1)) == fromfloor)
;
}
writer.WriteAttributeString(
"fromfloor", fromfloor.ToString());
writer.WriteAttributeString(
"tofloor", tofloor.ToString());
// passenger weight form 45 to 120, average 70
writer.WriteAttributeString("weight", rnd.Next((i <= 900) ? 45 : 70, (i <= 900) ? 70 : 120).ToString());
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.Flush();
writer.Close();
}
using (StreamWriter sw = new StreamWriter("passenger2.xml"))
{
sw.Write(
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n<passengers \r\n xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \r\n xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" \r\n xmlns=\"http://tempuri.org/passengers.xsd\">\r\n");
using (StreamReader sr = new StreamReader("temp2.xml"))
{
sr.ReadLine();
sr.ReadLine();
while (sr.Peek() > 0)
{
sw.WriteLine(sr.ReadLine());
}
}
}
Console.WriteLine(
"\nThe following file has been successfully created: passenger2.xml");
}
catch (Exception)
{
throw;
}
}

 

by Xiaobin(v-xxu@microsoft.com)

posted on 2010-12-11 13:16  CodingCrazy 小组  阅读(724)  评论(0编辑  收藏  举报