在加权和未加权的快速联合发现时遇到问题

时间:2015-04-22 03:26:05

标签: java weighted union-find

底部的TLDR

我在学校被分配了一个编程项目来建立一个渗透模型,我遇到了一个让我非常困惑的问题。首先,我们应该构建一个api来运行渗透模拟

public class Percolation{
private int grid[][];
public int size;
QuickFindUF unionFind;
//WeightedQuickUnionUF unionFind;


public Percolation(int n)
{

    if(n<1){
        throw new IllegalArgumentException ("grid must be larger than 0");
    }

    grid=new int[n][n];
    size=n;
    unionFind=new QuickFindUF(size*size);
    //unionFind=new WeightedQuickUnionUF(size*size);
    //initially set all to blocked
    for(int i=0;i<n;i++)
    {
        for(int j=0;j<n;j++)
        {
            grid[i][j]=1;
        }
    }
}

public void open(int x, int y)
{
    grid[x][y]=0;

            //Check below to see if you can
            //if you are not on the bottom row
            if(y>0)
            {
                if(grid[x][y]==0 && grid[x][y-1]==0){unionFind.union(x+y*size,x+(y-1)*size);}
            }
            //check to see to the right (x->)
            if(x<size-1){
                if(grid[x][y]==0 && grid[x+1][y]==0){unionFind.union(x+y*size,x+1+y*size);}
            }
            //check if can union to the left
            if(x>0)
            {
                if(grid[x][y]==0 && grid[x-1][y]==0){unionFind.union(x+y*size,x-1+y*size);}

            }
            //check for above 
            if(y<size-1){
                if(grid[x][y]==0 && grid[x][y+1]==0){unionFind.union(x+y*size,x+(y+1)*size);}
            }

}

public boolean isOpen(int x, int y)
{
    if(x>=size || y>=size){return false;}
    if(grid[x][y]==0){return true;}
    return false;
}

public boolean isFull(int x, int y)
{
    if(x>=size || y>=size){return false;}//if input is out of bounds


    for(int i=0;i<size;i++){
        if(unionFind.connected(x+y*size,i+((size-1)*size)))
            return true;
    }


    return false;
}

public boolean percolates()
{
    for(int i=0;i<size;i++){
        for(int j=0;j<size;j++){
            if(unionFind.connected(i,(size-1)*size+j)){
                //System.out.println(i+" "+((size-1)*size+j));

                return true;
            }
        }
    }
    return false;
}
}

现在,这本书提供了quickfindUFWeightedQuickUnionUF。所有与我交谈过的同学在使用PercolationStats课程计时时都得到了预期的结果,我们已经指示他们这样做,但我的结果非常好。这是班级

class PercolationStats{

private Percolation perc;
private double[] array;
private int expCount;

public PercolationStats(int gridSize, int numOfExperiments){
    if(gridSize <= 0 || numOfExperiments <=0)
        throw new IllegalArgumentException("gridSize and numOfExperiments needs to be more than 0");
    array=new double[numOfExperiments];
    expCount=numOfExperiments;

    for(int i=0;i<numOfExperiments;i++){
        perc=new Percolation(gridSize);
        int count=0;
        while(!perc.percolates()){
            int x=StdRandom.uniform(gridSize),y=StdRandom.uniform(gridSize);
            if(!perc.isOpen(x,y)){
                perc.open(x,y);
                count++;
            }
        }
        array[i]=(double) count/(gridSize*gridSize);
    }

}

public double mean(){
    return StdStats.mean(array);
}

public double stddev(){
    return StdStats.stddev(array);
}

public double confidenceLo(){
    return mean() - ((1.96 * stddev()) / Math.sqrt(expCount));
}

public double confidenceHi(){
    return mean()+((1.96 * stddev()) / Math.sqrt(expCount));
}

public static void main(String[] args){
    Stopwatch timer=new Stopwatch();
    PercolationStats percStats=new PercolationStats(200,100);
    System.out.println("mean: "+ percStats.mean() +"stddev: "+percStats.stddev()+" confidence Lo: "+percStats.confidenceLo()+" confidence hi: "+percStats.confidenceHi());
    System.out.println(timer.elapsedTime());
    percStats=new PercolationStats(200,100);
    System.out.println("mean: "+ percStats.mean() +"stddev: "+percStats.stddev()+" confidence Lo: "+percStats.confidenceLo()+" confidence hi: "+percStats.confidenceHi());
    percStats=new PercolationStats(2,100000);
    System.out.println("mean: "+ percStats.mean() +"stddev: "+percStats.stddev()+" confidence Lo: "+percStats.confidenceLo()+" confidence hi: "+percStats.confidenceHi());
}

}

当我使用QuickFindUF运行它时,在percStats(200,100),它需要大约7秒,如果我使用WeightedQuickUnionUF在相同的200,100运行它,它需要大约50+秒?我非常肯定加权快速联合应该更快,而且不仅仅是因为我的可怕的最坏情况随机数发生器不幸。我运行了很多次,结果仍然大致相同,我一直盯着这段代码很长一段时间,无法弄清楚为什么我的代码错了..

TLDR

结果正确,时机不正确。由于某种原因,较慢的api更快,我无法弄清楚原因。 QuickFindUF比WeightedQuickUnionUF更快。 (大约快7-8倍)。我做错了什么?

1 个答案:

答案 0 :(得分:0)

哈哈,我真傻。我在网上看到其他人正在使用虚拟顶部,所以我添加了一个,现在它工作正常:P