我正试图为随机数生成器编写停车场测试的实现。以下是我从:Intel math library documentationPage 4 of this paper获得测试信息的来源,以及列出的概率密度的phi函数。
我用c编写了一个测试的实现。它使用一个100x100网格,其值最初设置为空。然后,我使用随机数生成器为x和y生成随机整数。如果网格的索引及其邻居为空,则该索引设置为1。否则,什么也不会发生,因为有一个“崩溃”。
我用C系统运行的。随机发生器。我不相信结果是正确的,因为我总是停在3079点附近,这比我应该得到的平均值少了500点。它的p值也是2.21829146215425e-90。
我的代码在下面。有没有人有过这样的经验,或者有人能看到我在实现过程中可能做的不正确的事情?任何帮助都将不胜感激。

  private void RunParkingLotTest()
    {
        points = new int?[100,100];
        int parked = 0;

        for (int i = 0; i < 12000; i++)
        {
            int x = random.Next(100);
            int y = random.Next(100);

            if (IsSafeToPark(x, y))
            {
                points[x, y] = 1;
                parked++;
            }

        }
        Console.WriteLine("Parked: " + parked + "\nP value: " + PhiFunction((parked-3523)/21.9));
    }

    private bool IsSafeToPark(int x, int y)
    {
        return PointIsEmpty(x, y)
            && LeftOfPointIsEmpty(x, y)
            && RightOfPointIsEmpty(x, y)
            && BelowPointIsEmpty(x, y)
            && AbovePointIsEmpty(x, y);
    }

    private bool AbovePointIsEmpty(int x, int y)
    {
        if (y == 99)
        {
            return true;
        }
        else
            return points[x, y + 1] == null;
    }

    private bool BelowPointIsEmpty(int x, int y)
    {
        if (y == 0)
        {
            return true;
        }
        else
            return points[x, y - 1] == null;
    }

    private bool RightOfPointIsEmpty(int x, int y)
    {
        if (x == 99)
        {
            return true;
        }
        else
            return points[x + 1, y] == null;
    }

    private bool LeftOfPointIsEmpty(int x, int y)
    {
        if (x == 0)
        {
            return true;
        }
        else
            return points[x - 1, y] == null;
    }

    private bool PointIsEmpty(int x, int y)
    {
        return points[x, y] == null;
    }

    private double PhiFunction(double x)
    {
        //ϕ(x) = (2π)−½e−x2/2

        return ((1 / Math.Sqrt(2 * Math.PI)) * Math.Exp(-(Math.Pow(x, 2)) / 2));
    }

编辑-我最初实现的问题是
我画的是正方形而不是圆盘
我只绘制整数值的点。我应该用十进制值代替。
由于以上两个原因,我需要更改我的距离检查
感谢克里斯·辛克莱和我的Z帮我解决这个问题。最终代码发布在下面。

最佳答案

我要试试这个,不可否认,我没有尝试过这样的测试,所以请原谅我,如果我走远了。不过,一般来说,.netRandom实现是非常好的,而且我从来没有遇到过这样的问题,所以我不会怀疑最初是这样,特别是因为您正确地重用了同一个实例,而不是创建了新的实例。
从parking.pdf和intel文档中可以看到,他们似乎在使用光盘,并计算与中心点的距离。您的实现是使用正方形(点之间的距离为1的数组)从而忽略对角线。
从pdf:
如果使用圆盘,粒子之间的距离r=
p(x(i)-z)2+(y(i)-z)2需要小于或等于1。
使用圆盘还是正方形有关系吗?表明
停车几何图形的重要性可以通过
比较1.0边的正方形和
直径为1.0的圆盘。面积比,圆盘与正方形,是π/4。
因此,预计将在
一个方块比方块在相同的尝试次数。
以及英特尔文档:
测试假设下一个随机点(x,y)成功“停车”,如果
这与之前成功“停车”的每一个点都相距甚远。这个
点(x1,y1)和(x2,y2)之间的足够距离为
最小值(x1-x2,y1-y2)>1。
我猜π/4的盘平方比,以及多少盘可以和正方形匹配的差异,可能是你看到不同数字的原因。(尽管现在我没有看到3523和3070与π/4之间的直接关系。3523*π/4=2767,这很接近,但我相信如果有关系的话,它会比简单的乘法稍微复杂一些。)
不是很好的答案,但我最好的猜测。
编辑:有趣的是,我用一个单位直径的光盘做了一个快速的实现,得到了大约4000个停车场的结果。所以也许这有点超出了我未经训练的自我所能理解的范围(或者也许.net的Random没有通过测试?)无论如何,这是我的光盘实现:

List<Point> parkedCars = new List<Point>();
Random random = new Random();

void Main()
{
    int parked = 0;

    for (int i = 0; i < 12000; i++)
    {
        double x = random.NextDouble() * 100;
        double y = random.NextDouble() * 100;

        Point pointToPark = new Point(x, y);

        if (IsSafeToPark(pointToPark))
        {
            parkedCars.Add(pointToPark);
            parked++;
        }

    }
    Console.WriteLine("Parked: " + parked);
}

private bool IsSafeToPark(Point pointToPark)
{
    //make sure it's "inside" the box
    if (pointToPark.X < 0.5 || pointToPark.X > 99.5
        || pointToPark.Y < 0.5 || pointToPark.Y > 99.5)
        return false;

    if (parkedCars.Any(p => Distance(pointToPark, p) <= 1))
        return false;

    return true;
}

private double Distance(Point p1, Point p2)
{
    return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
}

用我可能太简单的π/4比值计算,得到了3142。再靠近一点,但似乎很不正确。
编辑:正如@mike z所指出的,我的测试使用直接距离是不正确的。根据我忘记的测试参数,只需检查x和y距离是否大于1。将我的检查更改为:
Math.Max(Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y))

在3450附近产生一个更接近的结果,这是相当接近的。如果我去掉我的“//确保它是“在”框内”复选框,平均10次以上得到3531!
所以我最后的“工作”代码是:
public struct Point
{
    public double X,Y;

    public Point(double x, double y)
    {
        this.X = x;
        this.Y = y;
    }
}

List<Point> parkedCars = new List<Point>();
Random random = new Random();

void Main()
{
    int parked = 0;

    for (int i = 0; i < 12000; i++)
    {
        double x = random.NextDouble() * 100;
        double y = random.NextDouble() * 100;

        Point pointToPark = new Point(x, y);

        if (IsSafeToPark(pointToPark))
        {
            parkedCars.Add(pointToPark);
            parked++;
        }

    }

    Console.WriteLine("Parked: " + parked);
}

private bool IsSafeToPark(Point pointToPark)
{
    if (parkedCars.Any(p => Distance(pointToPark, p) <= 1))
        return false;

    return true;
}

private double Distance(Point p1, Point p2)
{
    return Math.Max(Math.Abs(p1.X - p2.X), Math.Abs(p1.Y - p2.Y));
}

编辑:我做了100次测试两次,平均结果分别为3521.29和3526.74。不确定这是否意味着还有更多的东西要做,但也许这只是表示.NET和Fortran之间的舍入或浮点精度差异。

09-12 15:21