C#中XML文档生成实例:Elevator Scheduler测试文件的生成详解

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

完整的源码下载(VS2010):http://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)

转载于:https://www.cnblogs.com/codingcrazy/archive/2010/12/11/1902932.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值