Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented partial tree completion. #79

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion include/cmr/regular.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,29 @@ typedef enum
CMR_DEC_CONSTRUCT_ALL = 2,
} CMR_DEC_CONSTRUCT;

/**
* \brief Flags that control termination of the regular matroid decomposition algorithm.
*
* \see The desired types can be set by modifying \ref CMR_REGULAR_PARAMS.treeFlags.
*/

typedef enum
{
CMR_REGULAR_TREE_FLAGS_RECURSE = 1,
/**< Do not process child nodes. */
CMR_REGULAR_TREE_FLAGS_STOP_IRREGULAR = 2,
/**< Stop if a (grand-)child is irregular. */
CMR_REGULAR_TREE_FLAGS_STOP_NONGRAPHIC = 4,
/**< Stop if a (grand-)child is non-graphic. */
CMR_REGULAR_TREE_FLAGS_STOP_NONCOGRAPHIC = 8,
/**< Stop if a (grand-)child is non-cographic. */
CMR_REGULAR_TREE_FLAGS_STOP_NONGRAPHIC_NONCOGRAPHIC = 16,
/**< Stop if a (grand-)child is non-graphic **and** non-cographic. */

CMR_REGULAR_TREE_FLAGS_DEFAULT = CMR_REGULAR_TREE_FLAGS_RECURSE | CMR_REGULAR_TREE_FLAGS_STOP_IRREGULAR

} CMR_REGULAR_TREE_FLAGS;

typedef struct
{
bool directGraphicness;
Expand All @@ -36,7 +59,10 @@ typedef struct
/**< \brief Whether to allow series-parallel operations in the decomposition tree; default: \c true */
bool planarityCheck;
/**< \brief Whether minors identified as graphic should still be checked for cographicness; default: \c false. */
bool completeTree;

int treeFlags;
/**< \brief Flags controlling the decomposition algorithm. See \ref */

/**< \brief Whether to compute a complete decomposition tree (even if already non-regular; default: \c false. */
bool threeSumPivotChildren;
/**< \brief Whether pivots for 3-sums shall be applied such that the matrix contains both child matrices as
Expand Down
3 changes: 1 addition & 2 deletions src/cmr/matroid.c
Original file line number Diff line number Diff line change
Expand Up @@ -2023,8 +2023,7 @@ CMR_ERROR CMRmatroiddecSetAttributes(CMR_MATROID_DEC* dec)
{
case CMR_MATROID_DEC_TYPE_UNKNOWN:
dec->regularity = 0;
dec->graphicness = 0;
dec->cographicness = 0;
/* We do not set (co)graphicness because its absense may have been determined without setting the type. */
break;
case CMR_MATROID_DEC_TYPE_PLANAR:
dec->regularity = 1;
Expand Down
6 changes: 3 additions & 3 deletions src/cmr/regular.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ CMR_ERROR CMRregularParamsInit(CMR_REGULAR_PARAMS* params)
params->directGraphicness = true;
params->seriesParallel = true;
params->planarityCheck = false;
params->completeTree = false;
params->treeFlags = CMR_REGULAR_TREE_FLAGS_DEFAULT;
params->threeSumPivotChildren = false;
params->threeSumStrategy = CMR_MATROID_DEC_THREESUM_FLAG_DISTRIBUTED_RANKS /* TODO: Later no pivots. */
| CMR_MATROID_DEC_THREESUM_FLAG_FIRST_WIDE | CMR_MATROID_DEC_THREESUM_FLAG_FIRST_MIXED
Expand Down Expand Up @@ -88,7 +88,6 @@ CMR_ERROR CMRregularTest(CMR* cmr, CMR_CHRMAT* matrix, bool *pisRegular, CMR_MAT
{
assert(cmr);
assert(matrix);
assert(pisRegular);

CMR_REGULAR_PARAMS defaultParams;
if (!params)
Expand All @@ -100,7 +99,8 @@ CMR_ERROR CMRregularTest(CMR* cmr, CMR_CHRMAT* matrix, bool *pisRegular, CMR_MAT
CMR_SUBMAT* submatrix = NULL;
if (!CMRchrmatIsBinary(cmr, matrix, pminor ? &submatrix : NULL))
{
*pisRegular = false;
if (pisRegular)
*pisRegular = false;
if (pminor)
CMR_CALL( CMRminorCreate(cmr, pminor, 0, submatrix) );
return CMR_OKAY;
Expand Down
81 changes: 49 additions & 32 deletions src/cmr/regularity.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ CMR_ERROR CMRregularityQueueCreate(CMR* cmr, DecompositionQueue** pqueue)
DecompositionQueue* queue = *pqueue;
queue->head = NULL;
queue->foundIrregularity = false;
queue->foundNongraphicness = false;
queue->foundNoncographicness = false;

return CMR_OKAY;
}
Expand Down Expand Up @@ -180,41 +182,16 @@ CMR_ERROR CMRregularityTest(CMR* cmr, CMR_CHRMAT* matrix, bool ternary, bool *pi
CMR_CALL( CMRchrmatPrintDense(cmr, matrix, stdout, '0', false) );
#endif /* CMR_DEBUG */

clock_t time = clock();
if (stats)
stats->totalCount++;

CMR_MATROID_DEC* root = NULL;
CMR_CALL( CMRmatroiddecCreateMatrixRoot(cmr, &root, ternary, matrix) );
assert(root);

DecompositionQueue* queue = NULL;
CMR_CALL( CMRregularityQueueCreate(cmr, &queue) );
DecompositionTask* rootTask = NULL;
CMR_CALL( CMRregularityTaskCreateRoot(cmr, root, &rootTask, params, stats, time, timeLimit) );
CMRregularityQueueAdd(queue, rootTask);

while (!CMRregularityQueueEmpty(queue) && (params->completeTree || !queue->foundIrregularity))
{
DecompositionTask* task = CMRregularityQueueRemove(queue);
CMR_CALL( CMRregularityTaskRun(cmr, task, queue) );
}

CMR_CALL( CMRregularityQueueFree(cmr, &queue) );
CMR_CALL( CMRregularityCompleteDecomposition(cmr, root, params, stats, timeLimit) );

CMR_CALL( CMRmatroiddecSetAttributes(root) );
assert(root->regularity != 0);
if (pisRegular)
if (root->regularity && pisRegular)
*pisRegular = root->regularity > 0;

/* Either store or free the decomposition. */
if (pdec)
*pdec = root;
else
CMR_CALL( CMRmatroiddecRelease(cmr, &root) );

if (stats)
stats->totalTime += (clock() - time) * 1.0 / CLOCKS_PER_SEC;

return CMR_OKAY;
}
Expand All @@ -228,10 +205,10 @@ CMR_ERROR CMRregularityCompleteDecomposition(CMR* cmr, CMR_MATROID_DEC* subtree,

#if defined(CMR_DEBUG)
CMRdbgMsg(0, "Completing decomposition tree for a %s %zux%zu matrix.\n",
dec->isTernary ? "ternary" : "binary", root->matrix->numRows, root->matrix->numColumns);
subtree->isTernary ? "ternary" : "binary", subtree->matrix->numRows, subtree->matrix->numColumns);
CMRdbgMsg(0, "Considered subtree belongs to the %zux%zu matrix.\n",
dec->matrix->numRows, dec->matrix->numColumns);
CMR_CALL( CMRchrmatPrintDense(cmr, dec->matrix, stdout, '0', false) );
subtree->matrix->numRows, subtree->matrix->numColumns);
CMR_CALL( CMRchrmatPrintDense(cmr, subtree->matrix, stdout, '0', false) );
#endif /* CMR_DEBUG */

clock_t time = clock();
Expand All @@ -253,16 +230,56 @@ CMR_ERROR CMRregularityCompleteDecomposition(CMR* cmr, CMR_MATROID_DEC* subtree,
CMR_CALL( CMRregularityTaskCreateRoot(cmr, subtree, &decTask, params, stats, time, timeLimit) );
CMRregularityQueueAdd(queue, decTask);

while (!CMRregularityQueueEmpty(queue) && (params->completeTree || !queue->foundIrregularity))
while (!CMRregularityQueueEmpty(queue))
{
DecompositionTask* task = CMRregularityQueueRemove(queue);

if (!(params->treeFlags & CMR_REGULAR_TREE_FLAGS_RECURSE) && (task->dec != subtree))
{
CMRdbgMsg(2, "Skipping task for decomposition node %p of size %zux%zu.\n", task->dec, task->dec->numRows,
task->dec->numColumns);
CMR_CALL( CMRregularityTaskFree(cmr, &task) );
continue;
}

if ((params->treeFlags & CMR_REGULAR_TREE_FLAGS_STOP_IRREGULAR) && queue->foundIrregularity)
{
CMRdbgMsg(2, "Clearing task queue due to an irregular node.\n");
CMR_CALL( CMRregularityTaskFree(cmr, &task) );
continue;
}
else if ((params->treeFlags & CMR_REGULAR_TREE_FLAGS_STOP_IRREGULAR) && queue->foundIrregularity)
{
CMRdbgMsg(2, "Clearing task queue due to an irregular node.\n");
CMR_CALL( CMRregularityTaskFree(cmr, &task) );
continue;
}
else if ((params->treeFlags & CMR_REGULAR_TREE_FLAGS_STOP_NONGRAPHIC) && queue->foundNongraphicness)
{
CMRdbgMsg(2, "Clearing task queue due to a nongraphic node.\n");
CMR_CALL( CMRregularityTaskFree(cmr, &task) );
continue;
}
else if ((params->treeFlags & CMR_REGULAR_TREE_FLAGS_STOP_NONCOGRAPHIC) && queue->foundNoncographicness)
{
CMRdbgMsg(2, "Clearing task queue due to a noncographic node.\n");
CMR_CALL( CMRregularityTaskFree(cmr, &task) );
continue;
}
else if ((params->treeFlags & CMR_REGULAR_TREE_FLAGS_STOP_NONGRAPHIC_NONCOGRAPHIC) && queue->foundNongraphicness
&& queue->foundNoncographicness)
{
CMRdbgMsg(2, "Clearing task queue due to a nongraphic node and a noncographic node.\n");
CMR_CALL( CMRregularityTaskFree(cmr, &task) );
continue;
}

CMR_CALL( CMRregularityTaskRun(cmr, task, queue) );
}

CMR_CALL( CMRregularityQueueFree(cmr, &queue) );

CMR_CALL( CMRmatroiddecSetAttributes(subtree) );
assert(subtree->regularity != 0);

if (stats)
stats->totalTime += (clock() - time) * 1.0 / CLOCKS_PER_SEC;
Expand Down
6 changes: 6 additions & 0 deletions src/cmr/regularity_graphic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1705,6 +1705,7 @@ CMR_ERROR CMRregularityNestedMinorSequenceGraphicness(CMR* cmr, DecompositionTas
else
{
dec->graphicness = -1;
queue->foundNongraphicness = true;

/* Add task back to list of unprocessed tasks to test cographicness. */
CMRregularityQueueAdd(queue, task);
Expand Down Expand Up @@ -1788,6 +1789,7 @@ CMR_ERROR CMRregularityNestedMinorSequenceCographicness(CMR* cmr, DecompositionT
else
{
dec->cographicness = -1;
queue->foundNoncographicness = true;

/* Add task back to list of unprocessed tasks to search for 3-separations. */
CMRregularityQueueAdd(queue, task);
Expand Down Expand Up @@ -1860,6 +1862,8 @@ CMR_ERROR CMRregularityTestGraphicness(CMR* cmr, DecompositionTask* task, Decomp
dec->graphicness = isGraphic ? 1 : -1;
if (isGraphic)
dec->type = (dec->type == CMR_MATROID_DEC_TYPE_COGRAPH) ? CMR_MATROID_DEC_TYPE_PLANAR : CMR_MATROID_DEC_TYPE_GRAPH;
else
queue->foundNongraphicness = true;

if ((isGraphic && (!task->params->planarityCheck || dec->cographicness)) || dec->cographicness > 0)
{
Expand Down Expand Up @@ -1937,6 +1941,8 @@ CMR_ERROR CMRregularityTestCographicness(CMR* cmr, DecompositionTask* task, Deco
dec->cographicness = isCographic ? 1 : -1;
if (isCographic)
dec->type = (dec->type == CMR_MATROID_DEC_TYPE_GRAPH) ? CMR_MATROID_DEC_TYPE_PLANAR : CMR_MATROID_DEC_TYPE_COGRAPH;
else
queue->foundNoncographicness = true;

if ((isCographic && (!task->params->planarityCheck || dec->graphicness)) || dec->graphicness > 0)
{
Expand Down
6 changes: 4 additions & 2 deletions src/cmr/regularity_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ CMR_ERROR CMRregularityTaskFree(

typedef struct DecompositionQueue
{
DecompositionTask* head; /**< \brief Next task to be processed. */
bool foundIrregularity; /**< \brief Whether irregularity was detected for some node. */
DecompositionTask* head; /**< \brief Next task to be processed. */
bool foundIrregularity; /**< \brief Whether irregularity was detected for some node. */
bool foundNongraphicness; /**< \brief Whether non-graphiness was detected for some node. */
bool foundNoncographicness; /**< \brief Whether non-cographiness was detected for some node. */
} DecompositionQueue;

/**
Expand Down
2 changes: 2 additions & 0 deletions src/cmr/regularity_r10.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ CMR_ERROR CMRregularityTestR10(CMR* cmr, DecompositionTask* task, DecompositionQ
}

dec->type = CMR_MATROID_DEC_TYPE_R10;
queue->foundNongraphicness = true;
queue->foundNoncographicness = true;

cleanup:

Expand Down
3 changes: 2 additions & 1 deletion src/main/regular_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ CMR_ERROR testRegularity(
CMR_MINOR* minor = NULL;
CMR_REGULAR_PARAMS params;
CMR_CALL( CMRregularParamsInit(&params) );
params.completeTree = outputTreeFileName;
params.treeFlags = outputTreeFileName ? (CMR_REGULAR_TREE_FLAGS_RECURSE)
: (CMR_REGULAR_TREE_FLAGS_RECURSE | CMR_REGULAR_TREE_FLAGS_STOP_IRREGULAR);
params.directGraphicness = directGraphicness;
params.seriesParallel = seriesParallel;
CMR_REGULAR_STATS stats;
Expand Down
3 changes: 2 additions & 1 deletion src/main/tu_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ CMR_ERROR testTotalUnimodularity(
CMR_TU_PARAMS params;
CMR_CALL( CMRtuParamsInit(&params) );
params.algorithm = algorithm;
params.regular.completeTree = outputTreeFileName;
params.regular.treeFlags = outputTreeFileName ? (CMR_REGULAR_TREE_FLAGS_RECURSE)
: (CMR_REGULAR_TREE_FLAGS_RECURSE | CMR_REGULAR_TREE_FLAGS_STOP_IRREGULAR);
params.regular.directGraphicness = directGraphicness;
params.regular.seriesParallel = seriesParallel;
CMR_TU_STATS stats;
Expand Down
Loading
Loading