Ejemplo n.º 1
0
inline int PolyModel::simplicalNK(int n, int k) {
  if (n == 0)
    return 1;
  else if (k == 0)
    return 0;
  else
    return nChooseK(n+k-1,k-1);
}
Ejemplo n.º 2
0
/**
 * Initialize all data elements.
 *
 * @param r the saturation parameter.
 * @param n the order of the initial graph.
 */
void SaturationGraph::initData( int r, int N )
{
	this->r = r;
	this->N = N;

	int Nchoose2 = (this->N * (this->N - 1)) / 2;
	this->adjmat = (char*) malloc(Nchoose2);
	this->completemult = (char*) malloc(Nchoose2);
	this->completions = (int**) malloc(Nchoose2 * sizeof(int*));
	this->zeroDegrees = (int*) malloc(this->N * sizeof(int));
	this->oneDegrees = (int*) malloc(this->N * sizeof(int));

	this->openedges = new TreeSet();
	for ( int i = 0; i < Nchoose2; i++ )
	{
		this->openedges->add(i);

		/* 2-edges fill the graph */
		this->adjmat[i] = 2;

		/* multiplicities are zero */
		this->completemult[i] = 0;

		/* completions are null */
		this->completions[i] = 0;
	}

	bzero(this->zeroDegrees, this->N * sizeof(int));
	bzero(this->oneDegrees, this->N * sizeof(int));

	/* Now, we fill in the base graph, a K_r minus an edge, plus an isolated vertex */
	this->n = r + 1;

	this->convertEdge(0, 0);
	this->completions[0] = (int*) malloc((r - 2) * sizeof(int));

	for ( int i = 0; i < r - 2; i++ )
	{
		this->completions[0][i] = i + 2;
	}

	/* fill in rest of K_r with 1-edges */
	for ( int i = 1; i < nChooseK(r, 2); i++ )
	{
		this->convertEdge(i, 1);
	}

	this->g = 0;

	/* this small_g is null until fixed by compactTheGraph() */
	this->small_g = 0;
}
Ejemplo n.º 3
0
/*!
 * Formula for Bernstein polynomials taken from the Sederberg & Parry paper.
 */
double ffdPlanar::bernsteinPoly( int i, int n, double s )
{
    return nChooseK(n, i) * pow(1 - s, (n - i)) * pow(s, i);
}
Ejemplo n.º 4
0
/**
 * augment -- Augment by adding a non-edge with completion.
 *
 * Results in modifying the adjacency matrix and pushes information for this augmentation
 * onto the stack.
 *
 * @param noni One endpoint of the non-edge.
 * @param nonj The other endpoint of the non-edge.
 * @param completion An array of r-2 vertices which form the completion.
 *
 * @return True iff the augmentation succeeds without adding a K_r
 * 	or multiple K_r's when adding some assigned non-edge.
 */
bool SaturationGraph::augment( int noni, int nonj, int* completion )
{
	int oldN = this->n;

	this->regenerateOpenEdges();

	if ( this->augmentations.size() > 0 )
	{
		Augmentation* augment = this->augmentations.top();

		if ( augment->type == FILL )
		{
			this->augmentation_succeeded = false;
			/* FILL is the LAST thing to happen! */
			this->augmentations.push(new Augmentation(NONEDGE, -1, -1, 0, 0, oldN));
			return false;
		}
	}

	/* TODO: implement in this augmentation */
	int ij_index = this->indexOf(noni, nonj);

	if ( this->adjmat[ij_index] != 2 )
	{
		printf("--[augment] edge {%d %d} is not a 2! it's a %d\n", noni, nonj, this->adjmat[ij_index]);

		if ( this->openedges->contains(ij_index) == 1 )
		{
			printf("\t\t--[augment] but the index %d IS in openEdges.\n", ij_index);
		}
		else
		{
			printf("\t\t--[augment] and the index %d IS NOT in openEdges.\n", ij_index);
		}

		printf("\t-- completion is ");
		for ( int k = 0; k < this->r - 2; k++ )
		{
			printf("%d ", completion[k]);
		}
		printf("\n");

		this->augmentations.push(new Augmentation(NONEDGE, -1, -1, 0, 0, oldN));
		char* str = this->getString();
		printf("\t\t\t\t%s", str);
		free(str);
		this->augmentation_succeeded = false;

		return false;
	}

	if ( noni >= this->n || nonj >= this->n )
	{
		printf("--[augment] Trying to add a vertex which is too large: i=%d j=%d n=%d\n", noni, nonj, this->n);
		this->augmentations.push(new Augmentation(NONEDGE, -1, -1, 0, 0, oldN));
		this->augmentation_succeeded = false;
		return false;
	}

	/* STEP 1: Check if the completion requires new vertices. */
	/* 1.a. check that these are within range */
	for ( int k = 0; k < this->r - 2; k++ )
	{
		int vk = completion[k];

		if ( vk >= this->N )
		{
			/* too large! */
			this->augmentation_succeeded = false;
			this->augmentations.push(new Augmentation(NONEDGE, -1, -1, 0, 0, oldN));
			printf("\t\t--[augment] Trying to augment with an endpoint which is too large.\n");
			return false;
		}
	}

	/* 1.b. Add those new vertices */
	for ( int k = 0; k < this->r - 2; k++ )
	{
		int vk = completion[k];

		while ( vk >= this->n && this->n < this->N )
		{
			//			printf("\t--[augment] Adding a new vertex %d.\n", this->n);
			/* fill new edges with 2's */
			for ( int i = 0; i < this->n; i++ )
			{
				int iton = this->indexOf(i, this->n);

				this->adjmat[iton] = 2;
				this->completemult[iton] = 0;
				this->completions[iton] = 0;
				this->openedges->add(iton);
			}

			this->zeroDegrees[this->n] = 0;
			this->oneDegrees[this->n] = 0;

			this->n = this->n + 1;
		}
	}

	/* STEP 2: Add edges between {noni,nonj} and the completion vertices. */

	/* 2.a: Verify that we can do this augmentation */
	bool working = true;
	for ( int k = 0; working && k < this->r - 2; k++ )
	{
		int vk = completion[k];

		int ki_index = this->indexOf(vk, noni);
		int kj_index = this->indexOf(vk, nonj);

		if ( this->adjmat[ki_index] == 0 )
		{
			working = false;
		}
		else if ( this->adjmat[kj_index] == 0 )
		{
			working = false;
		}
		else
		{
			/* other edges in the completion */
			for ( int l = k + 1; working && l < this->r - 2; l++ )
			{
				int vl = completion[l];
				int kl_index = this->indexOf(vk, vl);

				if ( this->adjmat[kl_index] == 0 )
				{
					working = false;
				}
			} /* end for all l */
		}
	}

	if ( !working )
	{
		this->augmentations.push(new Augmentation(NONEDGE, -1, -1, 0, 0, oldN));
		printf("\t\t--[augment] Trying to augment, but there is a 0-edge somewhere!\n");
		this->n = oldN;
		this->augmentation_succeeded = false;
		return false;
	}

	/* from this point on, we may modify the graph */
	/* instead of just returning false, we'll need to  */
	/* fix what we've done */
	for ( int k = 0; k < this->r - 2; k++ )
	{
		int vk = completion[k];

		int ki_index = this->indexOf(vk, noni);
		int kj_index = this->indexOf(vk, nonj);

		this->convertEdge(ki_index, 1);
		this->convertEdge(kj_index, 1);

		for ( int l = k + 1; working && l < this->r - 2; l++ )
		{
			int vl = completion[l];
			int kl_index = this->indexOf(vk, vl);

			this->convertEdge(kl_index, 1);
		} /* end for all l */
	} /* end for all k */

	this->convertEdge(ij_index, 0);
	this->completions[ij_index] = completion;

	Augmentation* augment = new Augmentation(NONEDGE, noni, nonj, completion, this->r, oldN);

	if ( this->do_zero_implications )
	{
		/* what implied zeroes are there? */
		augment->zeroEdges = (int*) malloc(this->n * this->n * sizeof(int));
		bzero(augment->zeroEdges, this->n * this->n * sizeof(int));
		augment->numZeroEdges = 0;

		bool no_doubles = true;

		for ( int index = 0; no_doubles && index < nChooseK(n, 2); index++ )
		{
			if ( index != ij_index && this->adjmat[index] == 2 )
			{
				/* test for implication */
				int i, j;
				indexToPair(index, i, j);

				int ij_completions = 0;

				if ( this->r == 4 )
				{
					for ( int k = 0; no_doubles && k < this->n - 1; k++ )
					{
						if ( k == i || k == j )
						{
							continue;
						}

						int ik_index = this->indexOf(i, k);
						int jk_index = this->indexOf(j, k);

						if ( this->adjmat[ik_index] != 1 || this->adjmat[jk_index] != 1 )
						{
							continue;
						}

						for ( int l = k + 1; no_doubles && l < this->n; l++ )
						{
							if ( l == i || l == j )
							{
								continue;
							}

							int il_index = this->indexOf(i, l);
							int jl_index = this->indexOf(j, l);
							int kl_index = this->indexOf(k, l);

							if ( this->adjmat[il_index] == 1 && this->adjmat[jl_index] == 1 && this->adjmat[kl_index]
							        == 1 )
							{
								ij_completions++;

								if ( ij_completions >= 2 )
								{
									no_doubles = false;
								}
								else
								{
									/* add this edge to the implied set */
									augment->zeroEdges[augment->numZeroEdges] = index;
									(augment->numZeroEdges)++;
									this->completions[index] = (int*) malloc((this->r - 2) * sizeof(int));
									this->completions[index][0] = k;
									this->completions[index][1] = l;
								}
							}
						}
					}
				}
				else
				{
					printf("--[augment] Trying to imply when r = %d.\n", this->r);
				}
			}
		}

		if ( !no_doubles )
		{
			/* we have a problem, let's UNDO what we did! */
			for ( int k = 0; k < this->r - 2; k++ )
			{
				int vk = completion[k];

				int ki_index = this->indexOf(vk, noni);
				int kj_index = this->indexOf(vk, nonj);

				this->convertEdge(ki_index, 2);
				this->convertEdge(kj_index, 2);

				for ( int l = k + 1; working && l < this->r - 2; l++ )
				{
					int vl = completion[l];
					int kl_index = this->indexOf(vk, vl);

					this->convertEdge(kl_index, 2);
				} /* end for all l */
			} /* end for all k */

			for ( int k = 0; k < augment->numZeroEdges; k++ )
			{
				free(this->completions[augment->zeroEdges[k]]);
				this->completions[augment->zeroEdges[k]] = 0;
			}

			this->convertEdge(ij_index, 2);
			this->completions[ij_index] = 0;

			delete augment;
			this->augmentations.push(new Augmentation(NONEDGE, -1, -1, 0, 0, oldN));
			this->n = oldN;
			this->augmentation_succeeded = false;
			return false;
		}
		else
		{
			for ( int k = 0; k < augment->numZeroEdges; k++ )
			{
				int index = augment->zeroEdges[k];
				this->convertEdge(index, 0);

				int ii, jj;
				indexToPair(index, ii, jj);

				for ( int l = 0; l < this->r - 2; l++ )
				{
					int vl = this->completions[index][l];
					this->convertEdge(indexOf(ii, vl), 1);
					this->convertEdge(indexOf(jj, vl), 1);

					for ( int l2 = l + 1; l2 < this->r - 2; l2++ )
					{
						int vl2 = this->completions[index][l2];
						this->convertEdge(indexOf(vl, vl2), 1);
					}
				}
			}
		}
	}

	this->augmentations.push(augment);
	this->augmentation_succeeded = true;
	this->regenerateOpenEdges();

	return true;
}
Ejemplo n.º 5
0
/**
 * convertEdge
 *
 * Take an edge index, and turn it into a new type.
 */
void SaturationGraph::convertEdge( int index, char type )
{
	int i, j;
	this->indexToPair(index, i, j);
	char cur_type = this->adjmat[index];

	if ( index < 0 )
	{
		printf("--[convertEdge] Bad input %d\n", index);
		return;
	}

	if ( index >= nChooseK(this->n, 2) )
	{
		printf("--[convertEdge] Index too large %d\n", index);
		return;
	}

	if ( cur_type == 0 )
	{
		/* can't switch to 1 */
		if ( type == 2 )
		{
			this->adjmat[index] = 2;
			this->openedges->add(index);

			if ( this->completions[index] != 0 )
			{
				/* Free this, now that Augmentation copies completions */
				free(this->completions[index]);
				this->completions[index] = 0;
			}
			else
			{
				printf("--[convertEdge] Trying to delete a completion which is null...(index %d -- %d, %d)\n", index,
				       i, j);
			}

			this->zeroDegrees[i] = this->zeroDegrees[i] - 1;
			this->zeroDegrees[j] = this->zeroDegrees[j] - 1;
		}
		else if ( type == 1 )
		{
			printf("--[convertEdge] trying to convert %d,%d from 0 to 1.\n", i, j);
		}
	}
	else if ( cur_type == 1 )
	{
		/* can't switch to 0 */
		if ( type == 2 )
		{
			int cur_mult = this->completemult[index];

			cur_mult--;
			this->completemult[index] = cur_mult;

			/* only REALLY switch if the count is right */
			if ( cur_mult == 0 )
			{
				this->completemult[index] = 0;
				this->adjmat[index] = 2;
				this->openedges->add(index);
				this->oneDegrees[i] = this->oneDegrees[i] - 1;
				this->oneDegrees[j] = this->oneDegrees[j] - 1;
			}
			else if ( cur_mult < 0 )
			{
				this->completemult[index] = 0;
				this->adjmat[index] = 2;
				this->openedges->add(index);
				printf("--[convertEdge] cur_mult < 0 for index %d (%d, %d)\n", index, i, j);
			}
		}
		else if ( type == 1 )
		{
			/* if ALREADY a 1, just increase multiplicity */
			int cur_mult = this->completemult[index];
			cur_mult++;
			this->completemult[index] = cur_mult;
		}
		else if ( type == 0 )
		{
			printf("--[convertEdge] trying to convert %d,%d from 1 to 0.\n", i, j);
		}
	}
	else if ( cur_type == 2 )
	{
		if ( type != 2 )
		{
			this->openedges->remove(index);
		}

		this->adjmat[index] = type;

		if ( type == 0 )
		{
			this->zeroDegrees[i] = this->zeroDegrees[i] + 1;
			this->zeroDegrees[j] = this->zeroDegrees[j] + 1;
		}
		else if ( type == 1 )
		{
			this->completemult[index] = this->completemult[index] + 1;
			this->oneDegrees[i] = this->oneDegrees[i] + 1;
			this->oneDegrees[j] = this->oneDegrees[j] + 1;
		}
	}
}
Ejemplo n.º 6
0
/**
 * regenerateOpenEdges
 *
 * THIS IS A TEMPORARY METHOD
 */
void SaturationGraph::regenerateOpenEdges()
{
	clock_t start_c = clock();
	//	/* Regenerate the 2-type Edge Set */

	int Nchoose2 = nChooseK(this->n, 2);
	if ( 0 )
	{
		this->openedges->clear();

		for ( int i = 0; i < Nchoose2; i++ )
		{
			if ( this->adjmat[i] == 2 )
			{
				this->openedges->add(i);
			}
		}

		/* Double-Check every 0-type edge */

		for ( int i = 0; i < Nchoose2; i++ )
		{
			if ( this->adjmat[i] == 0 )
			{
				if ( this->completions[i] == 0 )
				{
					printf("--[SaturationGraph] There is a 0-type edge with no completion: %d\n", i);
				}
				else
				{
					/* be sure all completion edges are 1-type */
					int vi, vj;
					this->indexToPair(i, vi, vj);

					for ( int k = 0; k < this->r - 2; k++ )
					{
						int vk = this->completions[i][k];
						int ik_index = this->indexOf(vi, vk);
						int jk_index = this->indexOf(vj, vk);

						if ( this->adjmat[ik_index] != 1 )
						{
							printf(
							       "\t\t\t--[SaturationGraph] What should be a 1-type edge is of %d-type: index %d vi=%d vk=%d\n",
							       this->adjmat[ik_index], ik_index, vi, vk);
						}
						if ( this->adjmat[jk_index] != 1 )
						{
							printf(
							       "\t\t\t--[SaturationGraph] What should be a 1-type edge is of %d-type: index %d vj=%d vk=%d\n",
							       this->adjmat[jk_index], jk_index, vj, vk);
						}

						for ( int l = 0; l < k; l++ )
						{
							int vl = this->completions[i][l];

							int il_index = this->indexOf(vi, vl);
							int jl_index = this->indexOf(vj, vl);
							int kl_index = this->indexOf(vl, vk);

							if ( this->adjmat[il_index] != 1 )
							{
								printf(
								       "\t\t\t--[SaturationGraph] What should be a 1-type edge is of %d-type: index %d vi=%d vl=%d\n",
								       this->adjmat[il_index], il_index, vi, vl);
							}
							if ( this->adjmat[jl_index] != 1 )
							{
								printf(
								       "\t\t\t--[SaturationGraph] What should be a 1-type edge is of %d-type: index %d vj=%d vl=%d\n",
								       this->adjmat[jl_index], jl_index, vj, vl);
							}
							if ( this->adjmat[kl_index] != 1 )
							{
								printf(
								       "\t\t\t--[SaturationGraph] What should be a 1-type edge is of %d-type: index %d vk=%d vl=%d\n",
								       this->adjmat[kl_index], kl_index, vk, vl);
							}
						}
					}
				}
			}
		}
	}

	if ( 0 )
	{
		/* NOW: Check that all 1-edges have completemult > 0 */
		for ( int i = 0; i < Nchoose2; i++ )
		{
			if ( this->adjmat[i] == 1 && this->completemult[i] <= 0 )
			{
				printf("\t\t\t--[SaturtionGraph] There is a 1-type edge NOT in any completion! %d\n", i);
			}

		}
	}

	/* fix degree sequences */
	//	bzero(this->zeroDegrees, this->N * sizeof(int));


	for ( int i = 0; i < this->n; i++ )
	{
		int ionedeg = 0;
		int izerodeg = 0;
		for ( int j = 0; j < this->n; j++ )
		{
			if ( j != i )
			{
				int index = indexOf(i, j);

				if ( this->adjmat[index] == 0 )
				{
					izerodeg++;
				}
				else if ( this->adjmat[index] == 1 )
				{
					ionedeg++;
				}
			}
		}

		if ( izerodeg != this->zeroDegrees[i] )
		{
			this->zeroDegrees[i] = izerodeg;
		}

		if ( ionedeg != this->oneDegrees[i] )
		{
			this->oneDegrees[i] = ionedeg;
		}
	}

	clock_t end_c = clock();
	(this->time_in_regenerate) = this->time_in_regenerate + (double) (end_c - start_c) / (double) CLOCKS_PER_SEC;
}
Ejemplo n.º 7
0
/**
 * isCanonical
 *
 * Check if the most recent assignment of a non-edge is a canonical deletion, corresponding to
 * a canonical augmentation at that index. It selects a canonical deletion and tests if this
 * edge is in the same orbit.
 *
 * The recent assignment is stored in the augmentation stack.
 *
 * Note: the other augmentations are immediately canonical.
 *
 * @return True if the given augmentation is canonical for this graph.
 */
bool SaturationGraph::isCanonical()
{
	/* check if the CURRENT augmentation is canonical */
	Augmentation* augment = this->augmentations.top();

	if ( this->augmentations.size() >= 2 )
	{
		this->augmentations.pop();

		Augmentation* augment2 = this->augmentations.top();
		this->augmentations.push(augment);

		if ( augment2->type == FILL )
		{
			return false;
		}
	}
	/* Use a domain-reduction strategy, so that we can shortcut the calculation
	 * 	if we ever eliminate the given augmentation
	 */
	this->regenerateOpenEdges();

	bool has_zero_degree = false;

	for ( int i = this->n - 1; !has_zero_degree && i >= 0; i-- )
	{
		if ( this->zeroDegrees[i] == 0 && this->oneDegrees[i] == 0 )
		{
			has_zero_degree = true;
		}
	}

	if ( has_zero_degree )
	{
		/* this MUST be an ADDVERTEX type */
		if ( augment->type == ADDVERTEX )
		{
			return true;
		}

		return false;
	}

	if ( this->openedges->size() == 0 )
	{
		/* check for a completemult == 0  */
		bool has_zero_mult = false;
		for ( int i = 0; !has_zero_mult && i < this->n * (this->n - 1) / 2; i++ )
		{
			if ( this->adjmat[i] == 1 && this->completemult[i] == 0 )
			{
				has_zero_mult = true;
			}
		}

		if ( has_zero_mult && augment->type != FILL )
		{
			/* this can ONLY occur when a FILL happens */
			return false;
		}

		return true;
	}

	if ( augment->type != NONEDGE )
	{
		/* If it did not fit the above cases, it should be a NONEDGE augmentation */
		return false;
	}

	int aug_index = indexOf(augment->i, augment->j);

	/* so, we are of nonedge type */
	/* let us reduce the set of things to consider */
	if ( 0 )
	{

		int* aug_degree_tuple = (int*) malloc(4 * sizeof(int));
		aug_degree_tuple[0] = this->zeroDegrees[augment->i];
		aug_degree_tuple[1] = this->oneDegrees[augment->i];
		aug_degree_tuple[2] = this->zeroDegrees[augment->j];
		aug_degree_tuple[3] = this->oneDegrees[augment->j];

		int aug_deg_index = indexOfTuple(this->n, 4, aug_degree_tuple);

		/* try other ORIENTATION of edge */
		aug_degree_tuple[0] = this->zeroDegrees[augment->j];
		aug_degree_tuple[1] = this->oneDegrees[augment->j];
		aug_degree_tuple[2] = this->zeroDegrees[augment->i];
		aug_degree_tuple[3] = this->oneDegrees[augment->i];

		int temp_index = indexOfTuple(this->n, 4, aug_degree_tuple);

		if ( temp_index < aug_deg_index )
		{
			aug_deg_index = temp_index;
		}
		else
		{
			aug_degree_tuple[0] = this->zeroDegrees[augment->i];
			aug_degree_tuple[1] = this->oneDegrees[augment->i];
			aug_degree_tuple[2] = this->zeroDegrees[augment->j];
			aug_degree_tuple[3] = this->oneDegrees[augment->j];
		}

		int* degree_tuple = (int*) malloc(4 * sizeof(int));

		/* compute degrees at each endpoint */
		int npow4 = pow(this->n, 4);
		int* degreeMult = (int*) malloc(npow4 * sizeof(int));
		bzero(degreeMult, npow4 * sizeof(int));

		Set* posIndices = new TreeSet();

		for ( int index = 0; index < nChooseK(this->n, 2); index++ )
		{
			if ( this->adjmat[index] == 0 )
			{
				int ii, ij;
				indexToPair(index, ii, ij);

				degree_tuple[0] = this->zeroDegrees[ii];
				degree_tuple[1] = this->oneDegrees[ii];
				degree_tuple[2] = this->zeroDegrees[ij];
				degree_tuple[3] = this->oneDegrees[ij];

				int degree_index = indexOfTuple(this->n, 4, degree_tuple);

				degree_tuple[0] = this->zeroDegrees[ij];
				degree_tuple[1] = this->oneDegrees[ij];
				degree_tuple[2] = this->zeroDegrees[ii];
				degree_tuple[3] = this->oneDegrees[ii];

				temp_index = indexOfTuple(this->n, 4, degree_tuple);

				if ( temp_index < degree_index )
				{
					degree_index = temp_index;
				}

				posIndices->add(degree_index);

				degreeMult[degree_index] = degreeMult[degree_index] + 1;
			}
		}

		int min_deg_mult = this->n * this->n;
		int min_deg_index = npow4 + 1;
		for ( posIndices->resetIterator(); posIndices->hasNext(); )
		{
			int degree_index = posIndices->next();
			if ( (degreeMult[degree_index] > 0 && degreeMult[degree_index] < min_deg_mult) || (degreeMult[degree_index]
			        == min_deg_mult && degree_index < min_deg_index) )
			{
				min_deg_mult = degreeMult[degree_index];
				min_deg_index = degree_index;
			}
		}
		delete posIndices;

		if ( 0 && min_deg_index != aug_deg_index )
		{
			printf("--NOT CANONICAL since (%d) min_deg_index %d != %d aug_deg_index (%d)\n", min_deg_mult,
			       min_deg_index, aug_deg_index, degreeMult[aug_deg_index]);

			indexToTuple(this->n, 4, min_deg_index, degree_tuple);

			printf("-- aug_degree_tuple %d %d %d %d\n", aug_degree_tuple[0], aug_degree_tuple[1], aug_degree_tuple[2],
			       aug_degree_tuple[3]);
			printf("--     degree_tuple %d %d %d %d\n", degree_tuple[0], degree_tuple[1], degree_tuple[2],
			       degree_tuple[3]);

			free(degreeMult);
			free(degree_tuple);
			free(aug_degree_tuple);
			return false;
		}

		//	if ( 1 )
		//	{
		//		printf("-- IS CANONICAL since (%d) min_deg_index %d == %d aug_deg_index (%d)\n", min_deg_mult, min_deg_index,
		//		       aug_deg_index, degreeMult[aug_deg_index]);
		//
		//		free(degree_tuple);
		//		free(aug_degree_tuple);
		//		return true;
		//	}

		free(degreeMult);
		/* still in the running */

		//	if ( min_deg_mult == 1 )
		//	{
		//		/* decision made AND it's this one! */
		//		//		printf("--IS CANONICAL since min_deg_index %d = %d aug_deg_index AND unique multiplicity!\n", min_deg_index,
		//		//		       aug_deg_index);
		//		free(degree_tuple);
		//		free(aug_degree_tuple);
		//		return true;
		//	}
	}
	else if ( 0 )
	{
		/* compute based on 1-degrees */
		int onedegi = this->oneDegrees[augment->i];
		int onedegj = this->oneDegrees[augment->j];
		int aug_deg_index = 0;
		if ( onedegi < onedegj )
		{
			aug_deg_index = this->n * onedegi + onedegj;
		}
		else
		{
			aug_deg_index = this->n * onedegj + onedegi;
		}

		int* degreeMult = (int*) malloc(this->n * this->n * sizeof(int));
		bzero(degreeMult, this->n * this->n * sizeof(int));

		Set* posIndices = new TreeSet();

		for ( int index = 0; index < nChooseK(this->n, 2); index++ )
		{
			if ( this->adjmat[index] == 0 )
			{
				int ii, jj;
				indexToPair(index, ii, jj);

				int onedegii = this->oneDegrees[ii];
				int onedegjj = this->oneDegrees[jj];
				int deg_index = 0;
				if ( onedegii < onedegjj )
				{
					aug_deg_index = this->n * onedegii + onedegjj;
				}
				else
				{
					aug_deg_index = this->n * onedegjj + onedegii;
				}

				posIndices->add(deg_index);

				degreeMult[deg_index] = degreeMult[deg_index] + 1;
			}
		}

		int min_deg_mult = this->n * this->n;
		int min_deg_index = this->n * this->n + 1;

		for ( posIndices->resetIterator(); posIndices->hasNext(); )
		{
			int deg_index = posIndices->next();

			if ( degreeMult[deg_index] > 0 && degreeMult[deg_index] < min_deg_mult )
			{
				min_deg_index = deg_index;
				min_deg_mult = degreeMult[deg_index];
			}
			else if ( degreeMult[deg_index] == min_deg_mult && deg_index > min_deg_index )
			{
				min_deg_index = deg_index;
			}
		}

		delete posIndices;
		free(degreeMult);

		if ( min_deg_index != aug_deg_index )
		{
			return false;
		}
		else if ( min_deg_mult == 1 )
		{
			return true;
		}
	}

	/* compute canonical labels now */
	this->computeOrbits();

	/* within this set, find a canonical label */
	/* if this label is ever beaten, then not canonical! */
	int aug_orbit = augment->zeroOrbitLabels[aug_index];
	int aug_label = indexOf(augment->canonicalLabels[augment->i], augment->canonicalLabels[augment->j]);
	int min_label = aug_label;
	int min_index = aug_index;

	for ( int index = 0; index < nChooseK(this->n, 2); index++ )
	{
		if ( this->adjmat[index] == 0 )
		{
			int ii, ij;
			indexToPair(index, ii, ij);

			/* try min canon label */
			int canon_index = indexOf(augment->canonicalLabels[ii], augment->canonicalLabels[ij]);

			if ( canon_index < min_label )
			{
				min_label = canon_index;
				min_index = index;
			}
			//			}
		}
	}

	//	free(degree_tuple);
	//	free(aug_degree_tuple);

	if ( augment->zeroOrbitLabels[min_index] != aug_orbit )
	{
		return false;
	}

	return true;
}
Ejemplo n.º 8
0
/**
 * computeStabilizer
 *
 * Compute and store the automorphism group when a single pair is stabilized.
 *
 * @param i one endpoint
 * @param j another endpoint
 */
void SaturationGraph::computeStabilizer( int i, int j )
{
	/* First: check if the current augmentation HAS stabilizer data */
	Augmentation* augment = this->augmentations.top();

	this->computeOrbits();

	int index = this->indexOf(i, j);

	if ( augment->stabilizer == index )
	{
		return;
	}
	else
	{
		if ( 1 )
		{
			clock_t start_c = clock();
			/* we WANT this to be the right way */
			this->compactTheGraph();
			computeStabilizedOrbits(this->r, this, index, augment);

			clock_t end_c = clock();
			(this->time_in_stabilized) = (this->time_in_stabilized) + (double) (end_c - start_c)
			        / (double) CLOCKS_PER_SEC;
		}
		else
		{
			int nChooseSum = 1;
			for ( int s = 1; s <= r - 2; s++ )
			{
				nChooseSum += nChooseK(n, s);
			}

			augment->completionOrbitReps = (int**) malloc(nChooseSum * sizeof(int*));
			bzero(augment->completionOrbitReps, nChooseSum * sizeof(int*));

			int orb = 0;
			int* temp_set = (int*) malloc((r - 2) * sizeof(int));

			int pairi = i;
			int pairj = j;

			for ( int s = 1; s <= r - 2; s++ )
			{
				if ( n + (r - 2 - s) > this->getMaxN() )
				{
					/* there are too many vertices! */
					continue;
				}

				int nChooseS = nChooseK(this->n, s);

				for ( int set_index = 0; set_index < nChooseS; set_index++ )
				{
					/* add the orbit iff it can be a completion for the pair */

					bool can_complete = true;
					indexToSet(s, set_index, temp_set);

					for ( int k = 0; can_complete && k < s; k++ )
					{
						int ki_index = indexOf(pairi, temp_set[k]);
						int kj_index = indexOf(pairj, temp_set[k]);

						if ( this->getAdjacency(ki_index) == 0 || this->getAdjacency(kj_index) == 0 )
						{
							can_complete = false;
						}

						for ( int l = k + 1; can_complete && l < s; l++ )
						{
							int kl_index = indexOf(temp_set[k], temp_set[l]);
							if ( this->getAdjacency(kl_index) == 0 )
							{
								can_complete = false;
							}
						}
					}

					if ( can_complete )
					{
						/* this is a good completion */
						augment->completionOrbitReps[orb] = (int*) malloc((r - 2) * sizeof(int));
						indexToSet(s, set_index, augment->completionOrbitReps[orb]);

						/* fill in the rest */
						for ( int t = s; t < r - 2; t++ )
						{
							augment->completionOrbitReps[orb][t] = n + (t - s);
						}

						/* increase the set orbit */
						orb++;
					}
				}
			}

			free(temp_set);

			/* set numOrbits */
			augment->numStabilizedOrbits = orb;
		}

		augment->stabilizer = index;
	}
}
Ejemplo n.º 9
0
/**
 * computeOrbits
 *
 * Use the current assignment of edges to generate a
 * list of pair orbits.
 */
void SaturationGraph::computeOrbits()
{
	/* get the top augmentation */
	Augmentation* augment = this->augmentations.top();

	if ( augment->numOrbits >= 0 )
	{
		/* orbits are calculated */
		return;
	}

	/* First, build the 2-layer graph small_g */
	this->compactTheGraph();

	if ( 1 )
	{
		/* Now, feed it into the symmetry method */
		clock_t start_c = clock();
		computeUnassignedOrbits(this, augment);

		clock_t end_c = clock();
		(this->time_in_orbits) = (this->time_in_orbits) + (double) (end_c - start_c) / (double) CLOCKS_PER_SEC;
	}
	else
	{
		/* fill in the orbitLabels */
		augment->orbitLabels = (int*) malloc(n * n * sizeof(int));
		for ( int i = 0; i < n * n; i++ )
		{
			augment->orbitLabels[i] = -1;
		}

		augment->orbits = (int**) malloc(n * n * sizeof(int*));
		bzero(augment->orbits, n * n * sizeof(int*));

		augment->zeroOrbitLabels = (int*) malloc(n * n * sizeof(int));
		for ( int i = 0; i < n * n; i++ )
		{
			augment->zeroOrbitLabels[i] = -1;
		}

		int orb = 0;
		int zeroindex = 0;

		for ( int pair_ij = 0; pair_ij < nChooseK(n, 2); pair_ij++ )
		{
			/* Is it a representative? */
			/* we MOSTLY care about 2-orbits */
			if ( this->getAdjacency(pair_ij) == 2 )
			{
				/* this is the orbit representative */
				augment->orbitLabels[pair_ij] = orb;
				augment->orbits[orb] = (int*) malloc(n * n * sizeof(int));

				/* pre-fill with terminating -1's */
				for ( int k = 0; k < n * n; k++ )
				{
					augment->orbits[orb][k] = -1;
				}

				/* fill orbits with pair from g */
				augment->orbits[orb][0] = pair_ij;

				int k = 1;

				augment->orbits[orb][k] = -1;
				augment->orbits[orb][k + 1] = -1;

				/* increase the pair orbit */
				orb++;
			}
			else if ( this->getAdjacency(pair_ij) == 0 )
			{
				/* but also care about 1-orbits */
				/* a 1-type orbit rep! */
				/* this is the orbit representative */
				augment->zeroOrbitLabels[pair_ij] = zeroindex;

				/* increase the pair orbit */
				zeroindex++;
			}
		}

		/* set numOrbits */
		augment->numOrbits = orb;

		/* compute canonical labels */
		augment->canonicalLabels = (int*) malloc(n * sizeof(int));

		for ( int i = 0; i < n; i++ )
		{
			augment->canonicalLabels[i] = i;
		}
	}
}