예제 #1
0
int main(int argc, char *argv[])
{
	// put command line args into variables
	const char *inputFile = argv[1];
	const char *outputFile = argv[2];

	cout << endl << "input file: " << inputFile << endl;
	cout << "output file: " << outputFile << endl;

	// use Image struct
	Image newImage;
	Image * im;
	im = &newImage;


	DisjointSets * setPointer = NULL;
	setPointer = new DisjointSets(1);

	// read image, get # of columns and rows
	readImage(im, inputFile);
	numCols = getNCols(im);
	numRows = getNRows(im);

	scanImage(im, setPointer);
	resolveEquivalences(im, setPointer);
	setColors(im, setPointer->NumSets());
	writeImage(im, outputFile);

	return 0;
}
예제 #2
0
    // Add the fact that v1 and v2 are equivalent
    // return true if v1 was not already equivalent to v2
    // and false if v1 was already equivalent to v2
    bool SetEquivalent(int v1, int v2)
    {
      bool const already_equiv = false;
      if (v1 == v2) 
	return already_equiv;
      ensureElementExists(v1);
      ensureElementExists(v2);

      
      const int r1 = disjoint_sets_.find_set(v1);
      const int r2 = disjoint_sets_.find_set(v2);
      if (r1 == r2) 
	return already_equiv;
      root_set_map_t::const_iterator it1 = rootSetMap_.find(r1);
      assert(it1 != rootSetMap_.end());
      std::list<int> s1 = it1->second;

      root_set_map_t::const_iterator  it2 = rootSetMap_.find(r2);
      assert(it2 != rootSetMap_.end());
      std::list<int> s2 = it2->second;

      s1.splice(s1.begin(), s2); // union the related sets

      disjoint_sets_.link(r1, r2); // union the disjoint sets

      // associate the combined related set with the new root
      int const new_root = disjoint_sets_.find_set(v1);
      if (new_root != r1) {
	rootSetMap_.erase(it1);
      } else {
	rootSetMap_.erase(it2);
      }
      rootSetMap_[new_root] = s1;
      return !already_equiv;
    }
예제 #3
0
static list<int> listSets(const DisjointSets &ds)
{
    list<int> sets;
    for (int i = 0; i < ds.NumElements(); ++i)
    {
        if (ds.FindSet(i) == i)
            sets.push_front(i);
    }
    return sets;
}
예제 #4
0
static list<int> listElements(const DisjointSets &ds, int set)
{
    list<int> elements;
    for (int i = 0; i < ds.NumElements(); ++i)
    {
        if (ds.FindSet(i) == ds.FindSet(set))
            elements.push_front(i);
    }
    return elements;
}
예제 #5
0
void SquareMaze::bottomRemove(int x, int y, DisjointSets & maze,int & count,int rindex)
{
		if (maze.find(rindex) != maze.find(rindex+maze_width))
		{
			setWall(x, y, 1, false); 
			maze.setunion(rindex, rindex+maze_width);
			count++;
		}

}
예제 #6
0
void SquareMaze::rightRemove(int x, int y, DisjointSets & maze,int & count,int rindex)
{
		if (maze.find(rindex) != (maze.find(rindex+1))) 
		{
			setWall(x, y, 0, false); 
			maze.setunion(rindex, rindex+1); 
			count++;
		}


}
예제 #7
0
    // Return true if v1 and v2 are equivalent
    bool AreEquivalent(int v1, int v2) const
    {
      if (v1 == v2) {
	return true;
      }

      // The element does not exist, so we do not
      // know any equivalence information,
      // hence, v1 and v2 are not equivalent.
      if (!elementExists(v1) || !elementExists(v2)) {
	return false;
      }

      return disjoint_sets_.find_set(v1) == disjoint_sets_.find_set(v2);
    }
예제 #8
0
 void
 dynamic_connected_components(EdgeListGraph& g, DisjointSets& ds)
 {
   typename graph_traits<EdgeListGraph>::edge_iterator e, end;
   for (tie(e,end) = edges(g); e != end; ++e)
     ds.link(source(*e,g),target(*e,g));
 }
예제 #9
0
/*
 * set cannot handle over 255 elements. if this occurs, find elements
 * in current set, copy into a vector. push elements in the vector
 * into a new disjoint set, reassign pointer.
 *
 */
void expandSet(DisjointSets** s)
{
	DisjointSets * newPointer = NULL;
	vector <int> currElements = getLabels(*s);
	cout << "expandSet()" << currElements.size() << endl;
	newPointer = new DisjointSets(1);
	for (vector<int>::iterator it = currElements.begin(); it!=currElements.end(); ++it)
	{
	    cout << distance(currElements.begin(), it) << " "<< *it << endl;
	    newPointer->AddElements(*it);
	}



	s = &newPointer;
}
예제 #10
0
 void
 initialize_dynamic_components(VertexListGraph& G,
                               DisjointSets& ds)
 {
   typename graph_traits<VertexListGraph>
     ::vertex_iterator v, vend;
   for (tie(v, vend) = vertices(G); v != vend; ++v)
     ds.make_set(*v);
 }
예제 #11
0
    // Return the representative for the node v.
    int FindSet(int v) const
    {
      // If element does not exist
      if (!elementExists(v)) {
	// Then it is its own root.
	// This avoids adding singleton sets to the partition.
	return v;
      }

      return disjoint_sets_.find_set(v);
    }
예제 #12
0
/**
 * Finds a minimal spanning tree on a graph.
 * THIS FUNCTION IS GRADED.
 *
 * @param graph - the graph to find the MST of
 *
 * @todo Label the edges of a minimal spanning tree as "MST"
 *  in the graph. They will appear blue when graph.savePNG() is called.
 *
 * @note Use your disjoint sets class from MP 7.1 to help you with
 *  Kruskal's algorithm. Copy the files into the libdsets folder.
 * @note You may call std::sort (http://www.cplusplus.com/reference/algorithm/sort/)
 *  instead of creating a priority queue.
 */
void GraphTools::findMST(Graph & graph)
{
	vector<Edge> eds = graph.getEdges();
	sort(eds.begin(), eds.end(),myfunction);
	DisjointSets vers;
    vector <Vertex> vertex_list = graph.getVertices();
    vers.addelements(vertex_list.size());

    for (int i = 0; i < eds.size(); i++)
    {

        Vertex u = eds[i].source;
        Vertex v = eds[i].dest;

        if (vers.find(u) != vers.find(v))
        {
            vers.setunion(u,v);
            graph.setEdgeLabel(u,v,"MST");
        }
    }
}
예제 #13
0
    // Return a list of elements that are in the same disjoint set
    // as v.
    std::list<int> GetRelatedSet(int v) const
    {
      std::list<int> ret;
      if (!elementExists(v)) {
	ret.push_back(v);
	return ret;
      }
      int root = disjoint_sets_.find_set(v);
      root_set_map_t::const_iterator it = rootSetMap_.find(root);
      assert(it!=rootSetMap_.end());
      return it->second;
    }
예제 #14
0
    // If v does not exist, then add it to the disjoint set.
    void ensureElementExists(int v) const
    {
      elements_t::const_iterator it = elements_.find(v);
      if (it == elements_.end()) {
	disjoint_sets_.make_set(v);
	elements_.insert(v);
	
	std::list<int> li;
	li.push_front(v);
	rootSetMap_[v] = li;
      }
      return;
    }
예제 #15
0
/**
 * Finds a minimal spanning tree on a graph.
 * THIS FUNCTION IS GRADED.
 *
 * @param graph - the graph to find the MST of
 *
 * @todo Label the edges of a minimal spanning tree as "MST"
 *  in the graph. They will appear blue when graph.savePNG() is called.
 *
 * @note Use your disjoint sets class from MP 7.1 to help you with
 *  Kruskal's algorithm. Copy the files into the libdsets folder.
 * @note You may call std::sort (http://www.cplusplus.com/reference/algorithm/sort/)
 *  instead of creating a priority queue.
 */
void GraphTools::findMST(Graph & graph)
{
	vector<Edge> theEdges = graph.getEdges();
    std::sort(theEdges.begin(), theEdges.end());

    DisjointSets theVertexSet;
    vector<Vertex> theVertices = graph.getVertices();
    theVertexSet.addelements(theVertices.size());

    int size = theVertices.size();
    int count = 0;
    vector<Edge>::iterator iter;
    for(iter = theEdges.begin(); iter != theEdges.end(); iter++)
    {
        if(count == size - 1) break;
        if(theVertexSet.find(iter->source) != theVertexSet.find(iter->dest))
        {
            theVertexSet.setunion(iter->source, iter->dest);  
            graph.setEdgeLabel(iter->source, iter->dest, "MST");
            count++;
        }
    }
}
예제 #16
0
	void __output_ancestors(Vertex from, Vertex const u, Vertex const v) {
		sets.make_set(from);
		ancestors[sets.find_set(from)] = from;
		VertexContainer child = children(from);
		for (VertexContainer::iterator ite = child.begin(); ite != child.end(); ++ite) {
			__output_ancestors(*ite, u, v);
			sets.union_set(from, *ite);
			ancestors[sets.find_set(from)] = from;
		}
		colors[from] = black;
		if (u == from && colors[v] == black) {
			printf("The least common ancestor of %d and %d is %d.\n",
				query_dat(u), query_dat(v), query_dat(ancestors[sets.find_set(v)]));
		}
		else if (v == from && colors[u] == black) {
			printf("The least common ancestor of %d and %d is %d.\n",
				query_dat(v), query_dat(u), query_dat(ancestors[sets.find_set(u)]));
		}
	}
예제 #17
0
void SquareMaze::makeMaze(int width, int height)
{

right.clear();
bottom.clear();


maze_width = width;
maze_height = height; 
blocks = maze_width * maze_height; 
right.resize(blocks,true);
bottom.resize(blocks,true); 

DisjointSets maze; 
maze.addelements(blocks); 

srand(time(NULL));

//int x, y; 
bool rightmost=true, bottommost=true; 

int count = 0; 
//int rindex;
	while (count< (blocks - 1)) 
	{
		int rindex = rand() % blocks; 
		int x = rindex%maze_width;
		int y = rindex/maze_width;

		if(x==(maze_width-1))
		rightmost=true;
		else rightmost=false;

		if(y==(maze_height-1))
		bottommost=true;
		else bottommost=false;

		if (( rightmost == true ) && ( bottommost == true ))
		{
			rightmost=rightmost;
		}
		else if (!rightmost  && !bottommost)
		 {
			int action=rand()%3;			
					
			if (action == 0)  
			rightRemove(x,y,  maze,count,rindex);
			
		
			else if (action == 1)
			bottomRemove(x,y,  maze,count,rindex);

			else { 
			if ((maze.find(rindex) != maze.find(rindex+1)) && (maze.find(rindex) != maze.find(rindex+maze_width))&& (maze.find(rindex+1) != maze.find(rindex+1)))
			 { 
				setWall(x, y, 0, false); 
				setWall(x, y, 1, false); 
				maze.setunion(rindex, rindex+1); 
				maze.setunion(rindex, rindex+maze_width);
				count+=2;
			}
		}
		}
		
		
		else if(bottommost)
		{
			int action=rand()%2;			 
			if (action== 1)rightRemove(x,y,  maze,count,rindex);
		}
		
		else
		{
			int action =rand()%2;
			if (action == 1)bottomRemove(x,y,  maze,count,rindex);
		}

	}

}
예제 #18
0
	void reset() {
		ancestors.clear();
		colors.clear();
		sets.clear();
	}
예제 #19
0
void printElementSets(const DisjointSets & s)
{
	for (int i = 0; i < s.NumElements(); ++i)
		cout << s.FindSet(i) << "  ";
	cout << endl;
}
예제 #20
0
void SquareMaze::makeMaze(int width,int height)	
{
	width1=width;
	height1=height;
	int size=width*height;
	right.clear();
	down.clear();//clearing right and down walls just in case
	right=vector<bool>(size, true);//set all walls so they are there we will remove later
	down=vector<bool>(size, true);
	vector<int> blocks(size);//vector for indicies
	
	// map<int, int> maps;
	for(int i=0;i<size; i++)
	{
		blocks.push_back(i);//pushing back the indidces for the maze

		// for(int j=0; j<height1; j++)
		// {
		// 	// maps.insert(make_pair(i,j));
		// }
	}
	DisjointSets set;
	set.addelements(size);//used to stop cycles from being created
	srand(time(0));

	// std::random_shuffle(maps.begin(), maps.end());
	std::random_shuffle(blocks.begin(), blocks.end());//randomly shuffles indicies so it doesnt create the same maze

	// map<int, int>::iterator it;
	vector<int> :: iterator it;

	for(it=blocks.begin(); it!=blocks.end(); it++)
	{
		int x=*it%width;//x and y coords for the index
		int y=*it/width;
		int index=*it; //actual index


		if(x!=width1-1 ) //cant go any farther to the right in this case so dont want to do it
		{
			int index1=index+1;
			if(set.find(index)!=set.find(index1)) //checking if the one to the right of the index is in the same set
			{
				setWall(x,y,0,false);//if they are not in the same set we can remove the wall
				set.setunion(index, index1); //we connect them so they are in the same set
				//works because if we try to remove something in the same set it will create a cycle
			}
		}

		if(y!=height1-1)
		{
			int index2=index+width1;
			if(set.find(index)!= set.find(index2))
			{
				setWall(x,y,1,false); //do the same for if we want to go down
				set.setunion(index, index2);
			}
		}

	}
	




}
예제 #21
0
//compute bag affiliation for all vertices
//store result in m_bagindex
void ClusterAnalysis::computeBags() {
	const Graph &G = m_C->constGraph();

	// Storage structure for results
	m_bagindex.init(G);
	// We use Union-Find for chunks and bags
	DisjointSets<> uf;
	NodeArray<int> setid(G); // Index mapping for union-find
#if 0
	node* nn = new node[G.numberOfNodes()]; // dito
#endif

	// Every cluster gets its index
	ClusterArray<int> cind(*m_C);
	// We store the lists of cluster vertices
	List<node>* clists = new List<node>[m_C->numberOfClusters()];
	int i = 0;

	// Store index and detect the current leaf clusters
	List<cluster> ccleafs;
	ClusterArray<int> unprocessedChildren(*m_C); //processing below: compute bags
	for(cluster c : m_C->clusters)
	{
		cind[c] = i++;
		if (c->cCount() == 0) ccleafs.pushBack(c);
		unprocessedChildren[c] = c->cCount();
	}


	// Now we run through all vertices, storing them in the parent lists,
	// at the same time, we initialize m_bagindex
	for(node v : G.nodes)
	{
		// setid is constant in the following
		setid[v] = uf.makeSet();
		// Each vertex v gets its own ClusterArray that stores v's bag index per cluster.
		// See comment on use of ClusterArrays above
		m_bagindex[v] = new ClusterArray<int>(*m_C,DefaultIndex, m_C->maxClusterIndex()+1);//m_C->numberOfClusters());
		cluster c = m_C->clusterOf(v);
		// Push vertices in parent list
		clists[cind[c]].pushBack(v);
	}

	// Now each clist contains the direct vertex descendants
	// We process the clusters bottom-up, compute the chunks
	// of the leafs first. At each level, for a cluster the
	// vertex lists of all children are concatenated
	// (could improve this by having an array of size(#leafs)
	// and concatenating only at child1), then the bags are
	// updated as follows: chunks may be linked by exactly
	// the edges with lca(c) ie the ones in m_lcaEdges[c],
	// and bags may be built by direct child clusters that join chunks.
	// While concatenating the vertex lists, we can check
	// for the vertices in each child if the uf number is the same
	// as the one of a first initial vertex, otherwise we join.

	// First, lowest level clusters are processed: All chunks are bags


	OGDF_ASSERT(!ccleafs.empty());

	while (!ccleafs.empty()){
		const cluster c = ccleafs.popFrontRet();
		Skiplist<int*> cbags; //Stores bag indexes ocurring in c

		auto storeResult = [&] {
			for (node v : clists[cind[c]]) {
				int theid = uf.find(setid[v]);
				(*m_bagindex[v])[c] = theid;
				if (!cbags.isElement(&theid)) {
					cbags.add(new int(theid));
				}
				// push into list of outer active vertices
				if (m_storeoalists && isOuterActive(v, c)) {
					(*m_oalists)[c].pushBack(v);
				}
			}
			(*m_bags)[c] = cbags.size(); // store number of bags of c
		};

		if (m_storeoalists){
			//no outeractive vertices detected so far
			(*m_oalists)[c].clear();
		}

		//process leafs separately
		if (c->cCount() == 0) {


			//Todo could use lcaEdges list here too, see below
			for (node u : c->nodes)
			{
				for(adjEntry adj : u->adjEntries) {
					node w = adj->twinNode();
					if (m_C->clusterOf(w) == c)
					{
						uf.link(uf.find(setid[u]),uf.find(setid[w]));
					}
				}
			}
			// Now all chunks in the leaf cluster are computed
			// update for parent is done in the else case

			storeResult();
		}
		else {
			// ?We construct the vertex list by concatenating
			// ?the lists of the children to the current list.
			// We need the lists for storing the results efficiently.
			// (Should be slightly faster than to call clusterNodes each time)
			// Bags are either links of chunks by edges with lca==c
			// or links of chunk by child clusters.
			// Edge links
			for(edge e : (*m_lcaEdges)[c]) {
				uf.link(uf.find(setid[e->source()]),uf.find(setid[e->target()]));
			}

			// Cluster links
			for(cluster cc : c->children)
			{
				//Initial id per child cluster cc: Use value of first
				//vertex, each time we encounter a different value in cc,
				//we link the chunks

				//add (*itcc)'s vertices to c's list
				ListConstIterator<node> itvc = clists[cind[cc]].begin();
				int inid;
				if (itvc.valid()) inid = uf.find(setid[*itvc]);
				while (itvc.valid())
				{
					int theid = uf.find(setid[*itvc]);

					if (theid != inid)
						uf.link(inid,theid);
					clists[cind[c]].pushBack(*itvc);
					++itvc;
				}
			}

			storeResult();
		}
		// Now we update the status of the parent cluster and,
		// in case all its children are processed, add it to
		// the process queue.
		if (c != m_C->rootCluster())
		{
			OGDF_ASSERT(unprocessedChildren[c->parent()] > 0);
			unprocessedChildren[c->parent()]--;
			if (unprocessedChildren[c->parent()] == 0) ccleafs.pushBack(c->parent());
		}
	}

	// clean up
	delete[] clists;
}
예제 #22
0
 // Normalize the partition so that the smallest element
 // is the root.
 // TODO this would be easy to maintain incrementally.
 //      But I don't think boost does not.
 void Normalize() const
 {
   disjoint_sets_.normalize_sets(elements_.begin(), elements_.end());
 }
예제 #23
0
    void deleteCell(unsigned row, unsigned column) {
        auto &cell = cells[row][column];
        if (cell.getState() != Cell::State::Unknown) {
            throw MultipleStateChangeException();
        }

        auto rOffs = 0;
        auto cOffs = -1;
        for (auto i = 0; i < 4; i++) {
            const auto r = row + rOffs;
            const auto c = column + cOffs;
            if (r >= 0 && r < size && c >= 0 && c < size && cells[r][c].getState() == Cell::State::Deleted) {
                throw NoSolutionExistsException("deleted neighbor found");
            }

            auto t = rOffs;
            rOffs = -cOffs;
            cOffs = t;
        }

        const auto cellSet = static_cast<int>(row * size + column + 1);
        if (row == 0 || row == size - 1 || column == 0 || column == size - 1) {
            deletedTrees.unionSets(0, cellSet);
        }

        rOffs = -1;
        cOffs = -1;
        for (auto i = 0; i < 4; i++) {
            const auto r = row + rOffs;
            const auto c = column + cOffs;
            const auto diagonalNeighborSet = static_cast<int>(r * size + c + 1);
            if (r >= 0 && r < size && c >= 0 && c < size && cells[r][c].getState() == Cell::State::Deleted) {
                const auto diagonalRoot = deletedTrees.findSet(diagonalNeighborSet);
                const auto cellRoot = deletedTrees.findSet(cellSet);
                if (diagonalRoot != cellRoot) {
                    deletedTrees.linkSets(diagonalRoot, cellRoot);

                } else {
                    throw NoSolutionExistsException("circular neighbors found");
                }
            }

            auto t = rOffs;
            rOffs = -cOffs;
            cOffs = t;
        }

        cell.setState(Cell::State::Deleted);

        const auto value = cell.getValue();
        rowCounts[row][value]--;
        columnCounts[column][value]--;
        unknownCellCount--;

        rOffs = 0;
        cOffs = 1;
        for (auto i = 0; i < 4; i++) {
            const auto r = row + rOffs;
            const auto c = column + cOffs;
            if (r >= 0 && r < size && c >= 0 && c < size && cells[r][c].getState() == Cell::State::Unknown) {
                finalizeCell(r, c);
            }

            auto t = rOffs;
            rOffs = -cOffs;
            cOffs = t;
        }
    }
예제 #24
0
 // Return the number of disjoint sets in the partition.
 std::size_t CountSets() const
 {
   return disjoint_sets_.count_sets(elements_.begin(), elements_.end());
 }