/** Merge graph \p ga into graph \p gb. Returns false on failure. */
bool mergeNfaPair(NGHolder &ga, NGHolder &gb, const ReportManager *rm,
                  const CompileContext &cc) {
    assert(ga.kind == gb.kind);
    auto a_state_ids = numberStates(ga);
    auto b_state_ids = numberStates(gb);

    // Vacuous NFAs require special checks on their starts to ensure that tops
    // match, and that reports match for mixed-accept cases.
    if (!mergeableStarts(ga, gb)) {
        DEBUG_PRINTF("starts aren't mergeable\n");
        return false;
    }

    u32 cpl = commonPrefixLength(ga, a_state_ids, gb, b_state_ids);
    if (!shouldMerge(gb, b_state_ids, ga, a_state_ids, cpl, rm, cc)) {
        return false;
    }

    mergeNfaComponent(gb, ga, cpl);
    reduceImplementableGraph(gb, SOM_NONE, rm, cc);
    b_state_ids = numberStates(gb);
    return true;
}
Example #2
0
int* StatMerge::doSegmentation(int* ch1, int* ch2, int* ch3, double p)
{
	// first, build the edge array
	for(int x = 0; x < iWidth - 1; ++x)
	{
		for(int y = 0; y < iHeight - 1; ++y)
		{
			int p1 = (y * iWidth) + x;
			int p2 = p1 + 1;
			int p3 = p1 + iWidth;

			// vertical edge
			edgeArray[p1 * 2].p1 = p1;
			edgeArray[p1 * 2].p2 = p2;
			edgeArray[p1 * 2].val = findVal(ch1,ch2,ch3,p1,p2);

			// horizontal edge
			edgeArray[(p1 * 2)+1].p1 = p1;
			edgeArray[(p1 * 2)+1].p2 = p3;
			edgeArray[(p1 * 2)+1].val = findVal(ch1,ch2,ch3,p1,p3);
		}
	}

	// we have to handle the very bottom and right differently
	int y = iHeight - 1;
	int x = 0;
	for(x = 0; x < iWidth - 1; ++x)
	{
		int p1 = (y * iWidth) + x;
		int p2 = p1 + 1;

		// vertical edge
		edgeArray[p1 * 2].p1 = p1;
		edgeArray[p1 * 2].p2 = p2;
		edgeArray[p1 * 2].val = findVal(ch1,ch2,ch3,p1,p2);
	}

	y = 0;
	x = iWidth - 1;
	for(y = 0; y < iHeight - 1; ++y)
	{
		int p1 = (y * iWidth) + x;
		int p2 = p1 + iWidth;

		// horizontal edge
		edgeArray[(p1 * 2)+1].p1 = p1;
		edgeArray[(p1 * 2)+1].p2 = p2;
		edgeArray[(p1 * 2)+1].val = findVal(ch1,ch2,ch3,p1,p2);
	}

	// now sort the edges (probably the most expensive part of this entire operation).
	std::sort(edgeArray, edgeArray + (iWidth * iHeight * 2));

	// now let us prepare for the merging!
	uf.reset();
	resetStats(ch1,ch2,ch3);

	double Qg = 255.0 * sqrt(0.5 * log(2.0 / p));

	int p1, p2;
	int p1r, p2r;

	// first, note what our old maximum group number was
	int oldCutoff = maxGroup;
	++maxGroup;

	// first merge: merge unchanged pixels
	for(int i = 0; i < (iWidth*iHeight*2); ++i)
	{
		p1 = edgeArray[i].p1;
		p2 = edgeArray[i].p2;

		if(p1 < 0 || p2 < 0)
			continue;

		// don't merge if one of us has changed or if we're in different groups
		if(changeMask[p1] || changeMask[p2] || (retArray[p1] != retArray[p2]))
			continue;

		//std::cout << "I should never be called!\n";

		// otherwise, merge
		p1r = uf.Find(p1);
		p2r = uf.Find(p2);

		uf.UFUnion(p1r, p2r);
		//statsArray[p1r].merge(statsArray[p2r]);

		// cheat a bit to make sure new groups are formed
		statsArray[p1r].merge(statsArray[p2r], -1, maxGroup);
	}

	// second merge: merge everything again according to statistical rules
	//std::cout << "MaxGroup: " << maxGroup << std::endl;

	
	for(int i = 0; i < (iWidth*iHeight*2); ++i)
	{
		p1 = edgeArray[i].p1;
		p2 = edgeArray[i].p2;

		if(p1 < 0 || p2 < 0)
			continue;

		p1r = uf.Find(p1);
		p2r = uf.Find(p2);

		// (curLabels[p1]==curLabels[p2])
		// if we aren't already merged and the stats indicate we should, merge
		if(p1r != p2r && (false || shouldMerge(statsArray[p1r], statsArray[p2r], Qg)))
		{
			uf.UFUnion(p1r, p2r);

			// this merge call makes sure that new groups merge into old ones and that
			// new groups are properly created
			statsArray[p1r].merge(statsArray[p2r], oldCutoff, maxGroup);
		}
	}

	// now to fill in the return array thingy...
	int curR;
	int curSize;
	for(int curP = 0; curP < iWidth * iHeight; ++curP)
	{
		curR = uf.Find(curP);
		//curG = statsArray[curR].G;
		//retArray[curP] = changeMask[curR];
		curSize = statsArray[curR].N;
		sizeArray[curP] = curSize;
		retArray[curP] = curR;
	}

	return retArray;
}