#include "Options.h" #include "Sort.h" int GetParameters(struct opts *pOptions, int argc, char **argv) { /* This function gets the parameters from the command line and enters these into the Options data structure. The command line has the syntax program matrix P eps -option0=value0 -option1=value1 etc. For example: mondriaan pi.mtx 4 0.1 -SplitStrategy=onedimrow It returns TRUE on success and FALSE on failure. This function does NOT initialise the entire pOptions structure, but only changes to parameters specified in the command line options! */ int i; /* Check whether or not the given options are empty. */ if (argc <= 0 || !argv || !pOptions) { fprintf(stderr, "GetParameters(): null arguments!\n"); return FALSE; } /* Print Help if no option is given or a help option */ if (argc == 1 || ! strcmp(argv[1], "-h") || !strcmp(argv[1], "-help") || ! strcmp(argv[1], "--help")) { PrintHelp(argc, argv); return FALSE; } /* Check the number of arguments */ if (argc < 4) { fprintf(stderr, "GetParameters(): invalid number of arguments!\n"); PrintHelp(argc, argv); return FALSE; } /* Read the required arguments */ pOptions->matrix = argv[1]; if (atoi(argv[2]) < 0) fprintf(stderr, "GetParameters(): invalid number of processors!\n"); else pOptions->P = atoi(argv[2]); if (atof(argv[3]) < 0.0) fprintf(stderr, "GetParameters(): imbalance out of range!\n"); else pOptions->eps = atof(argv[3]); /* Read the optional command line arguments, e.g. -SplitStrategy=onedimrow to overrule the corresponding defaults */ i = 3; while (++i < argc) { if (argv[i][0] != '-') { fprintf(stderr, "GetParameters(): warning, invalid argument '%s'!\n", argv[i]); } else { const char *Option = argv[i] + 1, *Value = 0; /* Determine the form of the option: -option=value or -option value. */ if (strchr(Option, '=')) { Value = strchr(Option, '=') + 1; *(strchr(Option, '=')) = 0; } else if (++i < argc) { Value = argv[i]; } else { fprintf(stderr, "GetParameters(): warning, missing value for '%s'!\n", Option); } /* Set the read option. */ SetOption(pOptions, Option, Value); } } return TRUE; } /* end GetParameters */ int SetOptions(struct opts *pOptions, const char *Text) { /* This function sets the options to their default values as specified in a given string which may for example be extracted from a file on the harddisk. Each line of the defaults string contains an option and its desired value. Empty lines and lines starting with a # are ignored. This function returns TRUE on success and FALSE on failure. */ char Option[MAX_WORD_LENGTH], Value[MAX_WORD_LENGTH]; /* First verify that we have valid input. */ if (!pOptions || !Text) { fprintf(stderr, "SetOptions(): null arguments!\n"); return FALSE; } /* Now loop through all the options and set them individually. */ while (*Text) { /* Go to the first non-whitespace character. */ while (*Text && isspace(*Text)) Text++; /* Discard this line if it is a comment, otherwise read it. */ if (*Text && *Text != '#') { if (sscanf(Text, "%s %s", Option, Value) != 2) { fprintf(stderr, "SetOptions(): warning, unable to read the option from this line!\n"); } else { SetOption(pOptions, Option, Value); } } /* Advance to the next line. */ while (*Text && *Text != '\n') Text++; } return TRUE; } char* GetDefaultOptionText() { /* This function sets the default Mondriaan options. */ return "# Mondriaan default settings: \n" "LoadbalanceStrategy constant \n" "LoadbalanceAdjust yes \n" "SplitStrategy mediumgrain \n" "Alternate_FirstDirection ratio \n" "SplitMethod KLFM \n" "Partitioner mondriaan \n" "Metric lambda1 \n" "Discard_Free_Nets yes \n" "SquareMatrix_DistributeVectorsEqual no \n" "SquareMatrix_DistributeVectorsEqual_AddDummies yes \n" "SymmetricMatrix_UseSingleEntry no \n" "SymmetricMatrix_SingleEntryType lower \n" "Coarsening_NrVertices 200 \n" "Coarsening_MaxCoarsenings 128 \n" "Coarsening_NrMatchArbitrary 0 \n" "Coarsening_MaxNrVtxInMatch 2 \n" "Coarsening_StopRatio 0.05 \n" "Coarsening_VtxMaxFractionOfWeight 0.2 \n" "Coarsening_MatchingStrategy ata \n" "Coarsening_MatchingATAMatcher pga \n" "Coarsening_MatchingATAFinder inproduct \n" "Coarsening_InprodMatchingOrder decrwgt \n" "Coarsening_FineSwitchLevel 2 \n" "Coarsening_NetScaling linear \n" "Coarsening_InprodScaling min \n" "Coarsening_MatchIdenticalFirst yes \n" "KLFM_InitPart_NrRestarts 8 \n" "KLFM_InitPart_MaxNrLoops 25 \n" "KLFM_InitPart_MaxNrNoGainMoves 200 \n" "KLFM_Refine_MaxNrLoops 25 \n" "KLFM_Refine_MaxNrNoGainMoves 200 \n" "Iterative_Refinement aftermg \n" "VectorPartition_Step3 random \n" "VectorPartition_MaxNrLoops 10 \n" "VectorPartition_MaxNrGreedyImproves 10 \n" "OutputFormat original \n" "OutputMode original \n" "Seed 99 \n" "Permute none \n" "EnforceSymmetricPermutation no "; } int SetDefaultOptions(struct opts *pOptions) { /* This function sets the default Mondriaan options. */ const char* DefaultText = GetDefaultOptionText(); pOptions->matrix = 0; return SetOptions(pOptions, DefaultText); } int ExportDefaultOptions(FILE *Out) { if (fprintf(Out, "%s", GetDefaultOptionText()) < 0) return FALSE; return TRUE; } /* The following function writes the Mondriaan options to a filestream (i.e. stdout or an opened file on disk). */ int ExportOptions(FILE *Out, const struct opts *Opts) { if (Out == NULL || Opts == NULL) return FALSE; fprintf(Out, "# Mondriaan %s options:\n", MONDRIAANVERSION); fprintf(Out, "LoadbalanceStrategy "); if (Opts->LoadbalanceStrategy == Constant) fprintf(Out, "constant"); else if (Opts->LoadbalanceStrategy == Increase) fprintf(Out, "increase"); else if (Opts->LoadbalanceStrategy == Decrease) fprintf(Out, "decrease"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "LoadbalanceAdjust "); if (Opts->LoadbalanceAdjust == AdjustNo) fprintf(Out, "no"); else if (Opts->LoadbalanceAdjust == AdjustYes) fprintf(Out, "yes"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "SplitStrategy "); if (Opts->SplitStrategy == Alternate) fprintf(Out, "alternate"); else if (Opts->SplitStrategy == LocalBest) fprintf(Out, "localbest"); else if (Opts->SplitStrategy == Hybrid) fprintf(Out, "hybrid"); else if (Opts->SplitStrategy == LocalRatio) fprintf(Out, "localratio"); else if (Opts->SplitStrategy == OneDimRow) fprintf(Out, "onedimrow"); else if (Opts->SplitStrategy == OneDimCol) fprintf(Out, "onedimcol"); else if (Opts->SplitStrategy == FineGrain) fprintf(Out, "finegrain"); else if (Opts->SplitStrategy == SFineGrain) fprintf(Out, "symfinegrain"); else if (Opts->SplitStrategy == MediumGrain) fprintf(Out, "mediumgrain"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Alternate_FirstDirection "); if (Opts->Alternate_FirstDirection == FirstDirRow) fprintf(Out, "row"); else if (Opts->Alternate_FirstDirection == FirstDirCol) fprintf(Out, "col"); else if (Opts->Alternate_FirstDirection == FirstDirRatio) fprintf(Out, "ratio"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "SplitMethod "); if (Opts->SplitMethod == Simple) fprintf(Out, "simple"); else if (Opts->SplitMethod == KLFM) fprintf(Out, "KLFM"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Partitioner "); if (Opts->Partitioner == PartMondriaan) fprintf(Out, "mondriaan"); else if (Opts->Partitioner == PartPaToH) fprintf(Out, "patoh"); else if (Opts->Partitioner == FullPaToH) fprintf(Out, "fullpatoh"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Metric "); if (Opts->Metric == MetricLambda) fprintf(Out, "lambda1"); else if (Opts->Metric == MetricCut) fprintf(Out, "cutnet"); else if (Opts->Metric == MetricLambdaLambdaMinusOne) fprintf(Out, "lambdalambda1"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Discard_Free_Nets "); if (Opts->DiscardFreeNets == FreeNetYes) fprintf(Out, "yes"); else if (Opts->DiscardFreeNets == FreeNetNo) fprintf(Out, "no"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "SquareMatrix_DistributeVectorsEqual "); if (Opts->SquareMatrix_DistributeVectorsEqual == EqVecNo) fprintf(Out, "no"); else if (Opts->SquareMatrix_DistributeVectorsEqual == EqVecYes) fprintf(Out, "yes"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "SquareMatrix_DistributeVectorsEqual_AddDummies "); if (Opts->SquareMatrix_DistributeVectorsEqual_AddDummies == DumNo) fprintf(Out, "no"); else if (Opts->SquareMatrix_DistributeVectorsEqual_AddDummies == DumYes) fprintf(Out, "yes"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "SymmetricMatrix_UseSingleEntry "); if (Opts->SymmetricMatrix_UseSingleEntry == SingleEntNo) fprintf(Out, "no"); else if (Opts->SymmetricMatrix_UseSingleEntry == SingleEntYes) fprintf(Out, "yes"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "SymmetricMatrix_SingleEntryType "); if (Opts->SymmetricMatrix_SingleEntryType == ETypeLower) fprintf(Out, "lower"); else if (Opts->SymmetricMatrix_SingleEntryType == ETypeRandom) fprintf(Out, "random"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Coarsening_NrVertices %ld \n", Opts->Coarsening_NrVertices); fprintf(Out, "Coarsening_MaxCoarsenings %ld \n", Opts->Coarsening_MaxCoarsenings); fprintf(Out, "Coarsening_NrMatchArbitrary %ld \n", Opts->Coarsening_NrMatchArbitrary); fprintf(Out, "Coarsening_MaxNrVtxInMatch %ld \n", Opts->Coarsening_MaxNrVtxInMatch); fprintf(Out, "Coarsening_StopRatio %f \n", Opts->Coarsening_StopRatio); fprintf(Out, "Coarsening_VtxMaxFractionOfWeight %f \n", Opts->Coarsening_VtxMaxFractionOfWeight); fprintf(Out, "Coarsening_MatchingStrategy "); if (Opts->Coarsening_MatchingStrategy == MatchRandom) fprintf(Out, "random"); else if (Opts->Coarsening_MatchingStrategy == MatchInprod) fprintf(Out, "inproduct"); else if (Opts->Coarsening_MatchingStrategy == MatchATA) fprintf(Out, "ata"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Coarsening_MatchingATAMatcher "); if (Opts->Coarsening_MatchingATAMatcher == MatchMatcherGreedy) fprintf(Out, "greedy"); else if (Opts->Coarsening_MatchingATAMatcher == MatchMatcherPGA) fprintf(Out, "pga"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Coarsening_MatchingATAFinder "); if (Opts->Coarsening_MatchingATAFinder == MatchFinderInproduct) fprintf(Out, "inproduct"); else if (Opts->Coarsening_MatchingATAFinder == MatchFinderStairway) fprintf(Out, "stairway"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Coarsening_InprodMatchingOrder "); if (Opts->Coarsening_InprodMatchingOrder == DecreasingWgt) fprintf(Out, "decrwgt"); else if (Opts->Coarsening_InprodMatchingOrder == IncreasingWgt) fprintf(Out, "incrwgt"); else if (Opts->Coarsening_InprodMatchingOrder == DecreasingDegree) fprintf(Out, "decrdegree"); else if (Opts->Coarsening_InprodMatchingOrder == IncreasingDegree) fprintf(Out, "incrdegree"); else if (Opts->Coarsening_InprodMatchingOrder == NaturalOrder) fprintf(Out, "natural"); else if (Opts->Coarsening_InprodMatchingOrder == RandomOrder) fprintf(Out, "random"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Coarsening_FineSwitchLevel %ld \n", Opts->Coarsening_FineSwitchLevel); fprintf(Out, "Coarsening_NetScaling "); if (Opts->Coarsening_NetScaling == NoNetScaling) fprintf(Out, "no"); else if (Opts->Coarsening_NetScaling == NetSclLinear) fprintf(Out, "linear"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Coarsening_InprodScaling "); if (Opts->Coarsening_InprodScaling == NoIpScaling) fprintf(Out, "no"); else if (Opts->Coarsening_InprodScaling == IpSclCos) fprintf(Out, "cos"); else if (Opts->Coarsening_InprodScaling == IpSclMin) fprintf(Out, "min"); else if (Opts->Coarsening_InprodScaling == IpSclMax) fprintf(Out, "max"); else if (Opts->Coarsening_InprodScaling == IpSclJaccard) fprintf(Out, "jaccard"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Coarsening_MatchIdenticalFirst "); if (Opts->Coarsening_MatchIdenticalFirst == MatchIdNo) fprintf(Out, "no"); else if (Opts->Coarsening_MatchIdenticalFirst == MatchIdYes) fprintf(Out, "yes"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "KLFM_InitPart_NrRestarts %ld \n", Opts->KLFM_InitPart_NrRestarts); fprintf(Out, "KLFM_InitPart_MaxNrLoops %ld \n", Opts->KLFM_InitPart_MaxNrLoops); fprintf(Out, "KLFM_InitPart_MaxNrNoGainMoves %ld \n", Opts->KLFM_InitPart_MaxNrNoGainMoves); fprintf(Out, "KLFM_Refine_MaxNrLoops %ld \n", Opts->KLFM_Refine_MaxNrLoops); fprintf(Out, "KLFM_Refine_MaxNrNoGainMoves %ld \n", Opts->KLFM_Refine_MaxNrNoGainMoves); fprintf(Out, "Iterative_Refinement " ); if (Opts->Iterative_Refinement == IR_Never) fprintf(Out, "never" ); else if (Opts->Iterative_Refinement == IR_After_MG) fprintf(Out, "aftermg" ); else if (Opts->Iterative_Refinement == IR_Always) fprintf(Out, "always" ); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "VectorPartition_Step3 "); if (Opts->VectorPartition_Step3 == VecIncrease) fprintf(Out, "increase"); else if (Opts->VectorPartition_Step3 == VecDecrease) fprintf(Out, "decrease"); else if (Opts->VectorPartition_Step3 == VecRandom) fprintf(Out, "random"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "VectorPartition_MaxNrLoops %ld \n", Opts->VectorPartition_MaxNrLoops); fprintf(Out, "VectorPartition_MaxNrGreedyImproves %ld \n", Opts->VectorPartition_MaxNrGreedyImproves); fprintf(Out, "OutputFormat " ); if (Opts->OutputFormat == OutputDMM) fprintf(Out, "original" ); else if (Opts->OutputFormat == OutputEMM) fprintf(Out, "emm" ); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "OutputMode "); if (Opts->OutputMode == OneFile) fprintf(Out, "onefile"); else if (Opts->OutputMode == MultipleFiles) fprintf(Out, "original"); else if (Opts->OutputMode == DIMACS) fprintf(Out, "DIMACS"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "Seed %ld \n", Opts->Seed); fprintf(Out, "Permute "); if (Opts->OrderPermutation == OrderNone) fprintf(Out, "none"); else if (Opts->OrderPermutation == OrderPrefix) fprintf(Out, "reverseBBD"); else if (Opts->OrderPermutation == OrderInfix) fprintf(Out, "SBD"); else if (Opts->OrderPermutation == OrderPostfix) fprintf(Out, "BBD"); else return FALSE; fprintf(Out, "\n"); fprintf(Out, "EnforceSymmetricPermutation "); if (Opts->SymmetricPermute) fprintf(Out, "yes"); else fprintf(Out, "no"); fprintf(Out, "\n"); return TRUE; } int ExportOptionsToLaTeX(FILE *Out, const struct opts *Opts) { /* This function prints all set options to a LaTeX table. */ if (Out == NULL || Opts == NULL) return FALSE; fprintf(Out, "\\begin{tabular}{l|l}\nOption & Value \\\\\n\\hline\n"); fprintf(Out, "P & %d \\\\\n", Opts->P); fprintf(Out, "eps & %e \\\\\n", Opts->eps); fprintf(Out, "LoadbalanceStrategy & "); if (Opts->LoadbalanceStrategy == Constant) fprintf(Out, "constant"); else if (Opts->LoadbalanceStrategy == Increase) fprintf(Out, "increase"); else if (Opts->LoadbalanceStrategy == Decrease) fprintf(Out, "decrease"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "LoadbalanceAdjust & "); if (Opts->LoadbalanceAdjust == AdjustNo) fprintf(Out, "no"); else if (Opts->LoadbalanceAdjust == AdjustYes) fprintf(Out, "yes"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "SplitStrategy & "); if (Opts->SplitStrategy == Alternate) fprintf(Out, "alternate"); else if (Opts->SplitStrategy == LocalBest) fprintf(Out, "localbest"); else if (Opts->SplitStrategy == Hybrid) fprintf(Out, "hybrid"); else if (Opts->SplitStrategy == LocalRatio) fprintf(Out, "localratio"); else if (Opts->SplitStrategy == OneDimRow) fprintf(Out, "onedimrow"); else if (Opts->SplitStrategy == OneDimCol) fprintf(Out, "onedimcol"); else if (Opts->SplitStrategy == FineGrain) fprintf(Out, "finegrain"); else if (Opts->SplitStrategy == SFineGrain) fprintf(Out, "symfinegrain"); else if (Opts->SplitStrategy == MediumGrain) fprintf(Out, "mediumgrain"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Alternate-FirstDirection & "); if (Opts->Alternate_FirstDirection == FirstDirRow) fprintf(Out, "row"); else if (Opts->Alternate_FirstDirection == FirstDirCol) fprintf(Out, "col"); else if (Opts->Alternate_FirstDirection == FirstDirRatio) fprintf(Out, "ratio"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "SplitMethod & "); if (Opts->SplitMethod == Simple) fprintf(Out, "simple"); else if (Opts->SplitMethod == KLFM) fprintf(Out, "KLFM"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Partitioner & "); if (Opts->Partitioner == PartMondriaan) fprintf(Out, "mondriaan"); else if (Opts->Partitioner == PartPaToH) fprintf(Out, "patoh"); else if (Opts->Partitioner == FullPaToH) fprintf(Out, "fullpatoh"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Metric & "); if (Opts->Metric == MetricLambda) fprintf(Out, "lambda1"); else if (Opts->Metric == MetricCut) fprintf(Out, "cutnet"); else if (Opts->Metric == MetricLambdaLambdaMinusOne) fprintf(Out, "lambdalambda1"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Discard-Free-Nets & "); if (Opts->DiscardFreeNets == FreeNetYes) fprintf(Out, "yes"); else if (Opts->DiscardFreeNets == FreeNetNo) fprintf(Out, "no"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "DistributeVectorsEqual & "); if (Opts->SquareMatrix_DistributeVectorsEqual == EqVecNo) fprintf(Out, "no"); else if (Opts->SquareMatrix_DistributeVectorsEqual == EqVecYes) fprintf(Out, "yes"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "DistributeVectorsEqual-AddDummies & "); if (Opts->SquareMatrix_DistributeVectorsEqual_AddDummies == DumNo) fprintf(Out, "no"); else if (Opts->SquareMatrix_DistributeVectorsEqual_AddDummies == DumYes) fprintf(Out, "yes"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "SymmetricMatrix-UseSingleEntry & "); if (Opts->SymmetricMatrix_UseSingleEntry == SingleEntNo) fprintf(Out, "no"); else if (Opts->SymmetricMatrix_UseSingleEntry == SingleEntYes) fprintf(Out, "yes"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "SymmetricMatrix-SingleEntryType & "); if (Opts->SymmetricMatrix_SingleEntryType == ETypeLower) fprintf(Out, "lower"); else if (Opts->SymmetricMatrix_SingleEntryType == ETypeRandom) fprintf(Out, "random"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Coarsening-NrVertices & %ld \\\\\n", Opts->Coarsening_NrVertices); fprintf(Out, "Coarsening-MaxCoarsenings & %ld \\\\\n", Opts->Coarsening_MaxCoarsenings); fprintf(Out, "Coarsening-MaxNrMatchArbitrary & %ld \\\\\n", Opts->Coarsening_NrMatchArbitrary); fprintf(Out, "Coarsening-MaxNrVtxInMatch & %ld \\\\\n", Opts->Coarsening_MaxNrVtxInMatch); fprintf(Out, "Coarsening-StopRatio & %f \\\\\n", Opts->Coarsening_StopRatio); fprintf(Out, "Coarsening-VtxMaxFractionOfWeight & %f \\\\\n", Opts->Coarsening_VtxMaxFractionOfWeight); fprintf(Out, "Coarsening-MatchingStrategy & "); if (Opts->Coarsening_MatchingStrategy == MatchRandom) fprintf(Out, "random"); else if (Opts->Coarsening_MatchingStrategy == MatchInprod) fprintf(Out, "inproduct"); else if (Opts->Coarsening_MatchingStrategy == MatchATA) fprintf(Out, "ata"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Coarsening-MatchingATAMatcher & "); if (Opts->Coarsening_MatchingATAMatcher == MatchMatcherGreedy) fprintf(Out, "greedy"); else if (Opts->Coarsening_MatchingATAMatcher == MatchMatcherPGA) fprintf(Out, "pga"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Coarsening-MatchingATAFinder & "); if (Opts->Coarsening_MatchingATAFinder == MatchFinderInproduct) fprintf(Out, "inproduct"); else if (Opts->Coarsening_MatchingATAFinder == MatchFinderStairway) fprintf(Out, "stairway"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Coarsening-InprodMatchingOrder & "); if (Opts->Coarsening_InprodMatchingOrder == DecreasingWgt) fprintf(Out, "decrwgt"); else if (Opts->Coarsening_InprodMatchingOrder == IncreasingWgt) fprintf(Out, "incrwgt"); else if (Opts->Coarsening_InprodMatchingOrder == DecreasingDegree) fprintf(Out, "decrdegree"); else if (Opts->Coarsening_InprodMatchingOrder == IncreasingDegree) fprintf(Out, "incrdegree"); else if (Opts->Coarsening_InprodMatchingOrder == NaturalOrder) fprintf(Out, "natural"); else if (Opts->Coarsening_InprodMatchingOrder == RandomOrder) fprintf(Out, "random"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Coarsening-FineSwitchLevel & %ld \\\\\n", Opts->Coarsening_FineSwitchLevel); fprintf(Out, "Coarsening-NetScaling & "); if (Opts->Coarsening_NetScaling == NoNetScaling) fprintf(Out, "no"); else if (Opts->Coarsening_NetScaling == NetSclLinear) fprintf(Out, "linear"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Coarsening-InprodScaling & "); if (Opts->Coarsening_InprodScaling == NoIpScaling) fprintf(Out, "no"); else if (Opts->Coarsening_InprodScaling == IpSclCos) fprintf(Out, "cos"); else if (Opts->Coarsening_InprodScaling == IpSclMin) fprintf(Out, "min"); else if (Opts->Coarsening_InprodScaling == IpSclMax) fprintf(Out, "max"); else if (Opts->Coarsening_InprodScaling == IpSclJaccard) fprintf(Out, "jaccard"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "Coarsening-MatchIdenticalFirst & "); if (Opts->Coarsening_MatchIdenticalFirst == MatchIdNo) fprintf(Out, "no"); else if (Opts->Coarsening_MatchIdenticalFirst == MatchIdYes) fprintf(Out, "yes"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "KLFM-InitPart-NrRestarts & %ld \\\\\n", Opts->KLFM_InitPart_NrRestarts); fprintf(Out, "KLFM-InitPart-MaxNrLoops & %ld \\\\\n", Opts->KLFM_InitPart_MaxNrLoops); fprintf(Out, "KLFM-InitPart-MaxNrNoGainMoves & %ld \\\\\n", Opts->KLFM_InitPart_MaxNrNoGainMoves); fprintf(Out, "KLFM-Refine-MaxNrLoops & %ld \\\\\n", Opts->KLFM_Refine_MaxNrLoops); fprintf(Out, "KLFM-Refine-MaxNrNoGainMoves & %ld \\\\\n", Opts->KLFM_Refine_MaxNrNoGainMoves); fprintf(Out, "VectorPartition-Step3 & "); if (Opts->VectorPartition_Step3 == VecIncrease) fprintf(Out, "increase"); else if (Opts->VectorPartition_Step3 == VecDecrease) fprintf(Out, "decrease"); else if (Opts->VectorPartition_Step3 == VecRandom) fprintf(Out, "random"); else fprintf(Out, "?"); fprintf(Out, " \\\\\n"); fprintf(Out, "VectorPartition-MaxNrLoops & %ld \\\\\n", Opts->VectorPartition_MaxNrLoops); fprintf(Out, "VectorPartition-MaxNrGreedyImproves & %ld \\\\\n", Opts->VectorPartition_MaxNrGreedyImproves); fprintf(Out, "Seed & %ld \\\\\n", Opts->Seed); fprintf(Out, "Permute & "); if (Opts->OrderPermutation == OrderNone) fprintf(Out, "none"); else if (Opts->OrderPermutation == OrderPrefix) fprintf(Out, "reverseBBD"); else if (Opts->OrderPermutation == OrderInfix) fprintf(Out, "SBD"); else if (Opts->OrderPermutation == OrderPostfix) fprintf(Out, "BBD"); else fprintf(Out, "?"); fprintf(Out, "\\\\\n"); fprintf(Out, "EnforceSymmetricPermutation & "); if (Opts->SymmetricPermute) fprintf(Out, "yes"); else fprintf(Out, "no"); fprintf(Out, "\n\\\\\\hline\n"); fprintf(Out, "\\end{tabular}\n"); return TRUE; } /* The following function reads an options file from disk to memory and passes it to SetOptions(). The function returns TRUE on success and FALSE on failure.*/ int SetOptionsFromFile(struct opts *pOptions, const char *File) { FILE *pFile; char *Text; size_t Size; int Failure = FALSE; if (!pOptions || !File) { fprintf(stderr, "SetOptionsFromFile(): null arguments!\n"); return FALSE; } if ((pFile = fopen(File, "rb"))) { fseek(pFile, 0, SEEK_END); Size = ftell(pFile); fseek(pFile, 0, SEEK_SET); if ((Text = (char *)malloc(Size + 1))) { if (fread(Text, Size, 1, pFile) == 1) { Text[Size] = 0; SetOptions(pOptions, Text); } else { fprintf(stderr, "SetOptionsFromFile(): could not read data from options file!\n"); Failure = TRUE; } free(Text); } else { fprintf(stderr, "SetOptionsFromFile(): could not allocate text buffer for options file!\n"); Failure = TRUE; } fclose(pFile); } else { fprintf(stderr, "SetOptionsFromFile(): could not open options file '%s'!\n", File); Failure = TRUE; } return (!Failure); } int ApplyOptions(const struct opts *pOptions) { /* This function checks the option values in the given options structure and sets the random seed. Returns TRUE on success and FALSE on failure. */ if (!pOptions) { fprintf(stderr, "ApplyOptions(): null arguments!\n"); return FALSE; } /* Check whether the numerical option values are within the proper range */ if (pOptions->Coarsening_NrVertices < 1) { fprintf(stderr, "ApplyOptions(): Coarsening_NrVertices out of range!\n"); return FALSE; } if (pOptions->Coarsening_MaxCoarsenings < 1) { fprintf(stderr, "ApplyOptions(): Coarsening_MaxCoarsenings out of range!\n"); return FALSE; } if (pOptions->Coarsening_MaxNrVtxInMatch < 2) { fprintf(stderr, "ApplyOptions(): Coarsening_MaxNrVtxInMatch out of range!\n"); return FALSE; } if (pOptions->Coarsening_StopRatio < 0 || pOptions->Coarsening_StopRatio > 1) { fprintf(stderr, "ApplyOptions(): Coarsening_StopRatio out of range!\n"); return FALSE; } if (pOptions->Coarsening_VtxMaxFractionOfWeight <= 0 || pOptions->Coarsening_VtxMaxFractionOfWeight > 1) { fprintf(stderr, "ApplyOptions(): Coarsening_VtxMaxFractionOfWeight out of range!\n"); return FALSE; } if (pOptions->KLFM_InitPart_NrRestarts < 1) { fprintf(stderr, "ApplyOptions(): KLFM_InitPart_NrRestarts out of range!\n"); return FALSE; } if (pOptions->KLFM_InitPart_MaxNrLoops < 1) { fprintf(stderr, "ApplyOptions(): KLFM_InitPart_MaxNrLoops out of range!\n"); return FALSE; } if (pOptions->KLFM_InitPart_MaxNrNoGainMoves < 0) { fprintf(stderr, "ApplyOptions(): KLFM_InitPart_MaxNrNoGainMoves out of range!\n"); return FALSE; } if (pOptions->KLFM_Refine_MaxNrLoops < 1) { fprintf(stderr, "ApplyOptions(): KLFM_Refine_MaxNrLoops out of range!\n"); return FALSE; } if (pOptions->KLFM_Refine_MaxNrNoGainMoves < 0) { fprintf(stderr, "ApplyOptions(): KLFM_Refine_MaxNrNoGainMoves out of range!\n"); return FALSE; } if (pOptions->VectorPartition_MaxNrGreedyImproves < 0) { fprintf(stderr, "ApplyOptions(): VectorPartition_MaxNrGreedyImproves out of range!\n"); return FALSE; } if (pOptions->VectorPartition_MaxNrLoops < 1) { fprintf(stderr, "ApplyOptions(): VectorPartition_MaxNrLoops out of range!\n"); return FALSE; } /* Set the random number seed */ if (pOptions->Seed < -1) { fprintf(stderr, "ApplyOptions(): Random number seed out of range!\n"); return FALSE; } SetRandomSeed(pOptions->Seed); if (pOptions->Metric == MetricCut && pOptions->DiscardFreeNets == FreeNetNo) { fprintf(stderr, "ApplyOptions(): For the cut-net metric it is mandatory that free nets are discarded!\n"); return FALSE; } if (pOptions->Metric == MetricLambdaLambdaMinusOne && pOptions->Partitioner != PartPaToH) { fprintf(stderr, "ApplyOptions(): PaToH is required for the use of the lambda*(lambda - 1) metric!\n"); return FALSE; } if (pOptions->Coarsening_MatchingStrategy == MatchATA && pOptions->Coarsening_MaxNrVtxInMatch != 2) { fprintf(stderr, "ApplyOptions(): Hybrid matching is only supported for matching groups of two vertices!\n"); return FALSE; } #ifndef USE_PATOH if (pOptions->Partitioner == PartPaToH || pOptions->Partitioner == FullPaToH) { fprintf(stderr, "ApplyOptions(): The use of PaToH is requested, but this version of Mondriaan is compiled without PaToH support!\n"); return FALSE; } #endif return TRUE; } int SetOption(struct opts *pOptions, const char *option, const char *value) { /* This function sets the given option to its desired value in the Options data structure. The function does this by checking all the possible options to see whether the given option matches, and then checking all the possible values. It returns TRUE when the given option has succesfully been set to the desired value and FALSE otherwise.*/ if (!pOptions || !option || !value) return FALSE; if (!strcmp(option, "")) return FALSE; if (!strcmp(option, "LoadbalanceStrategy")) { if (!strcmp(value, "constant")) pOptions->LoadbalanceStrategy = Constant; else if (!strcmp(value, "increase")) pOptions->LoadbalanceStrategy = Increase; else if (!strcmp(value, "decrease")) pOptions->LoadbalanceStrategy = Decrease; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "LoadbalanceAdjust")) { if (!strcmp(value, "no") || !strcmp(value, "0")) pOptions->LoadbalanceAdjust = AdjustNo; else if (!strcmp(value, "yes") || !strcmp(value, "1")) pOptions->LoadbalanceAdjust = AdjustYes; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "SplitStrategy")) { if (!strcmp(value, "alternate")) pOptions->SplitStrategy = Alternate; else if (!strcmp(value, "localbest")) pOptions->SplitStrategy = LocalBest; else if (!strcmp(value, "hybrid")) pOptions->SplitStrategy = Hybrid; else if (!strcmp(value, "localratio")) pOptions->SplitStrategy = LocalRatio; else if (!strcmp(value, "onedimrow")) pOptions->SplitStrategy = OneDimRow; else if (!strcmp(value, "onedimcol")) pOptions->SplitStrategy = OneDimCol; else if (!strcmp(value, "finegrain")) pOptions->SplitStrategy = FineGrain; else if (!strcmp(value, "symfinegrain")) pOptions->SplitStrategy = SFineGrain; else if (!strcmp(value, "mediumgrain")) pOptions->SplitStrategy = MediumGrain; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Alternate_FirstDirection")) { if (!strcmp(value, "row")) pOptions->Alternate_FirstDirection = FirstDirRow; else if (!strcmp(value, "col")) pOptions->Alternate_FirstDirection = FirstDirCol; else if (!strcmp(value, "ratio")) pOptions->Alternate_FirstDirection = FirstDirRatio; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "SplitMethod")) { if (!strcmp(value, "simple")) pOptions->SplitMethod = Simple; else if (!strcmp(value, "KLFM") || !strcmp(value, "klfm")) pOptions->SplitMethod = KLFM; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Partitioner")) { if (!strcmp(value, "mondriaan")) pOptions->Partitioner = PartMondriaan; else if (!strcmp(value, "patoh")) pOptions->Partitioner = PartPaToH; else if (!strcmp(value, "fullpatoh")) pOptions->Partitioner = FullPaToH; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Metric")) { if (!strcmp(value, "lambda1")) pOptions->Metric = MetricLambda; else if (!strcmp(value, "cutnet")) pOptions->Metric = MetricCut; else if (!strcmp(value, "lambdalambda1")) pOptions->Metric = MetricLambdaLambdaMinusOne; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Discard_Free_Nets")) { if (!strcmp(value, "yes")) { pOptions->DiscardFreeNets = FreeNetYes; } else if (!strcmp(value, "no")) { pOptions->DiscardFreeNets = FreeNetNo; } else { fprintf(stderr, "SetOptions(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "SquareMatrix_DistributeVectorsEqual")) { if (!strcmp(value, "no") || !strcmp(value, "0")) pOptions->SquareMatrix_DistributeVectorsEqual = EqVecNo; else if (!strcmp(value, "yes") || ! strcmp(value, "1")) pOptions->SquareMatrix_DistributeVectorsEqual = EqVecYes; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "SquareMatrix_DistributeVectorsEqual_AddDummies")) { if (!strcmp(value, "no") || !strcmp(value, "0")) pOptions->SquareMatrix_DistributeVectorsEqual_AddDummies = DumNo; else if (!strcmp(value, "yes") || !strcmp(value, "1")) pOptions->SquareMatrix_DistributeVectorsEqual_AddDummies = DumYes; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "SymmetricMatrix_UseSingleEntry")) { if (!strcmp(value, "no") || ! strcmp(value, "0")) pOptions->SymmetricMatrix_UseSingleEntry = SingleEntNo; else if (!strcmp(value, "yes") || ! strcmp(value, "1")) pOptions->SymmetricMatrix_UseSingleEntry = SingleEntYes; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "SymmetricMatrix_SingleEntryType")) { if (!strcmp(value, "lower")) pOptions->SymmetricMatrix_SingleEntryType = ETypeLower; else if (!strcmp(value, "random")) pOptions->SymmetricMatrix_SingleEntryType = ETypeRandom; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Coarsening_NrVertices")) { pOptions->Coarsening_NrVertices = atol(value); } else if (!strcmp(option, "Coarsening_MaxCoarsenings")) { pOptions->Coarsening_MaxCoarsenings = atol(value); } else if (!strcmp(option, "Coarsening_NrMatchArbitrary")) { pOptions->Coarsening_NrMatchArbitrary = atol(value); } else if (!strcmp(option, "Coarsening_MaxNrVtxInMatch")) { pOptions->Coarsening_MaxNrVtxInMatch = atol(value); } else if (!strcmp(option, "Coarsening_StopRatio")) { pOptions->Coarsening_StopRatio = atof(value); } else if (!strcmp(option, "Coarsening_VtxMaxFractionOfWeight")) { pOptions->Coarsening_VtxMaxFractionOfWeight = atof(value); } else if (!strcmp(option, "Coarsening_MatchingStrategy")) { if (!strcmp(value, "random")) pOptions->Coarsening_MatchingStrategy = MatchRandom; else if (!strcmp(value, "inproduct")) pOptions->Coarsening_MatchingStrategy = MatchInprod; else if (!strcmp(value, "ata")) pOptions->Coarsening_MatchingStrategy = MatchATA; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Coarsening_MatchingATAMatcher")) { if (!strcmp(value, "greedy")) pOptions->Coarsening_MatchingATAMatcher = MatchMatcherGreedy; else if (!strcmp(value, "pga")) pOptions->Coarsening_MatchingATAMatcher = MatchMatcherPGA; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Coarsening_MatchingATAFinder")) { if (!strcmp(value, "inproduct")) pOptions->Coarsening_MatchingATAFinder = MatchFinderInproduct; else if (!strcmp(value, "stairway")) pOptions->Coarsening_MatchingATAFinder = MatchFinderStairway; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Coarsening_FineSwitchLevel")) { pOptions->Coarsening_FineSwitchLevel = atol(value); } else if (!strcmp(option, "Coarsening_InprodMatchingOrder")) { if (!strcmp(value, "decrwgt")) pOptions->Coarsening_InprodMatchingOrder = DecreasingWgt; else if (!strcmp(value, "incrwgt")) pOptions->Coarsening_InprodMatchingOrder = IncreasingWgt; else if (!strcmp(value, "decrdeg")) pOptions->Coarsening_InprodMatchingOrder = DecreasingDegree; else if (!strcmp(value, "incrdeg")) pOptions->Coarsening_InprodMatchingOrder = IncreasingDegree; else if (!strcmp(value, "natural")) pOptions->Coarsening_InprodMatchingOrder = NaturalOrder; else if (!strcmp(value, "random")) pOptions->Coarsening_InprodMatchingOrder = RandomOrder; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Coarsening_NetScaling")) { if (!strcmp(value, "nonetscaling") || ! strcmp(value, "no")) pOptions->Coarsening_NetScaling = NoNetScaling; else if (!strcmp(value, "linear")) pOptions->Coarsening_NetScaling = NetSclLinear; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Coarsening_InprodScaling")) { if (!strcmp(value, "noipscaling") || ! strcmp(value, "no")) pOptions->Coarsening_InprodScaling = NoIpScaling; else if (!strcmp(value, "cos")) pOptions->Coarsening_InprodScaling = IpSclCos; else if (!strcmp(value, "min")) pOptions->Coarsening_InprodScaling = IpSclMin; else if (!strcmp(value, "max")) pOptions->Coarsening_InprodScaling = IpSclMax; else if (!strcmp(value, "jaccard")) pOptions->Coarsening_InprodScaling = IpSclJaccard; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Coarsening_MatchIdenticalFirst")) { if (!strcmp(value, "no") || ! strcmp(value, "0")) pOptions->Coarsening_MatchIdenticalFirst = MatchIdNo; else if (!strcmp(value, "yes") || ! strcmp(value, "1")) pOptions->Coarsening_MatchIdenticalFirst = MatchIdYes; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "KLFM_InitPart_NrRestarts")) { pOptions->KLFM_InitPart_NrRestarts = atol(value); } else if (!strcmp(option, "KLFM_InitPart_MaxNrLoops")) { pOptions->KLFM_InitPart_MaxNrLoops = atol(value); } else if (!strcmp(option, "KLFM_InitPart_MaxNrNoGainMoves")) { pOptions->KLFM_InitPart_MaxNrNoGainMoves = atol(value); } else if (!strcmp(option, "KLFM_Refine_MaxNrLoops")) { pOptions->KLFM_Refine_MaxNrLoops = atol(value); } else if (!strcmp(option, "KLFM_Refine_MaxNrNoGainMoves")) { pOptions->KLFM_Refine_MaxNrNoGainMoves = atol(value); } else if (!strcmp(option, "VectorPartition_Step3")) { if (!strcmp(value, "increase")) pOptions->VectorPartition_Step3 = VecIncrease; else if (!strcmp(value, "decrease")) pOptions->VectorPartition_Step3 = VecDecrease; else if (!strcmp(value, "random")) pOptions->VectorPartition_Step3 = VecRandom; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "VectorPartition_MaxNrLoops")) { pOptions->VectorPartition_MaxNrLoops = atol(value); } else if (!strcmp(option, "VectorPartition_MaxNrGreedyImproves")) { pOptions->VectorPartition_MaxNrGreedyImproves = atol(value); } else if (!strcmp(option, "OutputFormat")) { if (!strcmp(value, "original")) pOptions->OutputFormat = OutputDMM; else if(!strcmp(value, "EMM") || !strcmp(value, "emm") ) pOptions->OutputFormat = OutputEMM; else { fprintf(stderr, "SetOption(): unkown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Iterative_Refinement")) { if (!strcmp(value, "never")) pOptions->Iterative_Refinement = IR_Never; else if(!strcmp(value, "aftermg")) pOptions->Iterative_Refinement = IR_After_MG; else if(!strcmp(value, "always")) pOptions->Iterative_Refinement = IR_Always; else { fprintf(stderr, "SetOption(): unkown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "OutputMode")) { if (!strcmp(value, "onefile")) pOptions->OutputMode = OneFile; else if(!strcmp(value, "original")) pOptions->OutputMode = MultipleFiles; else if(!strcmp(value, "DIMACS")) pOptions->OutputMode = DIMACS; else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "Seed")) { if (!strcmp(value, "random") || atol(value) < 0) pOptions->Seed = -1; else pOptions->Seed = labs(atol(value)); } else if (!strcmp(option, "Permute")) { if (!strcmp(value, "none")) { pOptions->OrderPermutation = OrderNone; } else if (!strcmp(value, "reverseBBD") || !strcmp(value, "prefix")) { pOptions->OrderPermutation = OrderPrefix; } else if (!strcmp(value, "SBD") || !strcmp(value, "infix")) { pOptions->OrderPermutation = OrderInfix; } else if (!strcmp(value, "BBD") || !strcmp(value, "postfix")) { pOptions->OrderPermutation = OrderPostfix; } else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else if (!strcmp(option, "EnforceSymmetricPermutation")) { if (!strcmp(value, "yes")) { pOptions->SymmetricPermute = TRUE; } else if (!strcmp(value, "no")) { pOptions->SymmetricPermute = FALSE; } else { fprintf(stderr, "SetOption(): unknown %s '%s'!\n", option, value); return FALSE; } } else { fprintf(stderr, "SetOption(): unknown option '%s'!\n", option); return FALSE; } return TRUE; } /* end SetOption */ void PrintHelp(int argc, char **argv) { /* This function prints a help message on how to use Mondriaan from the command line. This function can for instance be called in case there are too few arguments. */ printf("\nMondriaan version %s.\n", MONDRIAANVERSION); if (argv && argv[0]) printf("Usage: %s [matrix] [P] [eps] <options>\n\n", argv[0]); else printf("Usage: ./Mondriaan [matrix] [P] [eps] <options>\n\n"); printf(" [matrix] - the matrix to partition\n"); printf(" [P] - the number of processors\n"); printf(" [eps] - the maximum allowed load imbalance\n\n"); printf(" <options>:"); printf(" for details, see the User's Guide at\n"); printf(" http://www.math.uu.nl/people/bisseling"); printf("/Mondriaan/users_guide.html\n"); printf("\n"); fflush(stdout); } /* end PrintHelp */