2 4ti2 -- A software package for algebraic, geometric and combinatorial
3 problems on linear spaces.
5 Copyright (C) 2006 4ti2 team.
6 Main author(s): Matthias Walter.
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 #include "libzsolve.h"
47 int readTokenFromFile(FILE *stream
, char *tokenchars
, char **ptoken
, int *pmemory
)
57 *ptoken
= (char *)calloc(8, sizeof(char));
63 while ((c
= fgetc(stream
))!=EOF
)
65 if (strchr(tokenchars
, c
))
67 if (len
+1 >= *pmemory
)
70 *ptoken
= (char *)realloc(*ptoken
, *pmemory
*sizeof(char));
73 (*ptoken
)[len
] = '\0';
82 void backupEvent(ZSolveContext ctx
)
86 strcat(BaseName
, ".backup");
87 stream
= fopen(BaseName
, "w");
88 BaseName
[BaseLength
] = '\0';
90 backupZSolveContext(stream
, ctx
);
97 int main(int argc
, char *argv
[])
103 Matrix matrix
= NULL
;
105 VectorArray Lattice
= NULL
;
106 Vector vector
= NULL
;
108 LinearSystem initialsystem
;
116 puts(FORTY_TWO_BANNER
);
120 // START OF RESUME SECTION - READ FILES AND CREATE CONTEXT
122 strcat(BaseName
, ".backup");
123 stream
= fopen(BaseName
, "r");
124 BaseName
[BaseLength
] = '\0';
128 printf("Unable to open backup file %s.backup\n", BaseName
);
134 if (fscanf(stream
, "%d %d %d", &OVerbose
, &OLogging
, &OBackup
)!=3 || OVerbose
<0 || OVerbose
>3 || OLogging
<0 || OLogging
>3 || OBackup
<0)
137 printf("Backup file %s.backup does not contain valid data.\n", BaseName
);
143 ctx
= createZSolveContextFromBackup(stream
, zsolveLogCallbackDefault
, backupEvent
);
149 strcat(BaseName
, ".log");
150 stream
= fopen(BaseName
, "a");
151 BaseName
[BaseLength
] = '\0';
154 printf("Unable to open log file %s.log\n", BaseName
);
158 ctx
->LogFile
= LogFile
= stream
;
161 // END OF RESUME SECTION
168 strcat(BaseName
, ".log");
169 stream
= fopen(BaseName
, "w");
170 BaseName
[BaseLength
] = '\0';
173 printf("Unable to open log file %s.log\n", BaseName
);
179 // check for existance of solution files
182 strcat(BaseName
, ".zhom");
183 stream
= fopen(BaseName
, "r");
184 BaseName
[BaseLength
] = '\0';
189 printf("%s.hom already exists! Use -f to force calculation.\n", BaseName
);
192 fprintf(LogFile
, "%s.hom already exists! Use -f to force calculation.\n", BaseName
);
198 strcat(BaseName
, ".zinhom");
199 stream
= fopen(BaseName
, "r");
200 BaseName
[BaseLength
] = '\0';
205 printf("%s.inhom already exists! Use -f to force calculation.\n", BaseName
);
208 fprintf(LogFile
, "%s.inhom already exists! Use -f to force calculation.\n", BaseName
);
217 strcat(BaseName
, ".mat");
218 stream
= fopen(BaseName
, "r");
219 BaseName
[BaseLength
] = '\0';
223 stream
= fopen(BaseName
, "r");
226 printf("Matrix file %s.mat not found, falling back to project file %s.\n\n", BaseName
, BaseName
);
229 fprintf(LogFile
, "Matrix file %s.mat not found, falling back to project file %s.\n\n", BaseName
, BaseName
);
237 strcat(BaseName
, ".lat");
238 stream
= fopen(BaseName
, "r");
239 BaseName
[BaseLength
] = '\0';
244 printf("Neither matrix file %s.mat nor lattice file %s.lat exists!\n", BaseName
, BaseName
);
247 fprintf(LogFile
, "Neither matrix file %s.mat nor lattice file %s.lat exists!\n", BaseName
, BaseName
);
255 // START OF LATTICE SECTION - READ FILES AND CREATE CONTEXT
257 Lattice
= readVectorArray(stream
, false);
262 printf("Lattice file %s.lat does not contain valid data.\n", BaseName
);
265 fprintf(LogFile
, "Lattice file %s.lat does not contain valid data.\n", BaseName
);
275 strcat(BaseName
, ".rhs");
276 stream
= fopen(BaseName
, "r");
277 BaseName
[BaseLength
] = '\0';
280 fscanf(stream
, "%d", &i
);
284 printf("Height of RHS must be 1!\n");
287 fprintf(LogFile
, "Height of RHS must be 1!\n");
290 deleteMatrix(matrix
);
294 fscanf(stream
, "%d", &i
);
297 if (fscanf(stream
, "%d", &j
) || j
!=0)
299 printf("When reading from %s.lat, RHS file %s.rhs must contain a zero vector.\n", BaseName
, BaseName
);
302 fprintf(LogFile
, "When reading from %s.lat, RHS file %s.rhs must contain a zero vector.\n", BaseName
, BaseName
);
305 deleteMatrix(matrix
);
313 // variable properties
315 for (i
=0; i
<Lattice
->Variables
; i
++)
317 Lattice
->Properties
[i
].Column
= i
;
318 Lattice
->Properties
[i
].Lower
= OHilbert
? 0 : -MAXINT
;
319 Lattice
->Properties
[i
].Upper
= MAXINT
;
320 Lattice
->Properties
[i
].Free
= (!OGraver
&& !OHilbert
);
324 strcat(BaseName
, ".rel");
325 stream
= fopen(BaseName
, "r");
326 BaseName
[BaseLength
] = '\0';
333 if (fscanf(stream
, "%d %d", &r
, &j
)<2 || r
!= 1)
335 printf("RELATION file %s.rel must start with the dimensions.\n", BaseName
);
341 if (readTokenFromFile(stream
, "0123456789=<>", &token
, &memory
) == 0)
343 printf("RELATION file %s.rel ends unexpectedly.\n", BaseName
);
346 else if (!strcmp(token
, "<") || !strcmp(token
, ">"))
348 printf("When reading from %s.lat, inequalities are not allowed.\n", BaseName
);
351 else if (strcmp(token
, "="))
353 printf("Unknown token '%s' in RELATION file %s.rel.\n", token
, BaseName
);
368 strcat(BaseName
, ".sign");
369 stream
= fopen(BaseName
, "r");
370 BaseName
[BaseLength
] = '\0';
377 if (fscanf(stream
, "%d %d", &r
, &i
)<2 || i
!= Lattice
->Variables
|| r
!= 1)
379 printf("SIGN file %s.sign must start with '1 %d'.\n", BaseName
, Lattice
->Variables
);
383 for (i
=0; i
<Lattice
->Variables
; i
++)
385 if (readTokenFromFile(stream
, "0123456789-abcdefghijklmnopqrstuvwxyz", &token
, &memory
) == 0)
387 printf("SIGN file %s.sign ends unexpectedly.\n", BaseName
);
390 if (!strcmp(token
, "0") || !strcmp(token
, "free") || !strcmp(token
, "f"))
392 Lattice
->Properties
[i
].Upper
= MAXINT
;
393 Lattice
->Properties
[i
].Lower
= -MAXINT
;
394 Lattice
->Properties
[i
].Free
= true;
396 else if (!strcmp(token
, "1") || !strcmp(token
, "hil") || !strcmp(token
, "h"))
398 Lattice
->Properties
[i
].Upper
= MAXINT
;
399 Lattice
->Properties
[i
].Lower
= 0;
400 Lattice
->Properties
[i
].Free
= false;
402 else if (!strcmp(token
, "-1") || !strcmp(token
, "-hil") || !strcmp(token
, "-h"))
404 Lattice
->Properties
[i
].Upper
= 0;
405 Lattice
->Properties
[i
].Lower
= -MAXINT
;
406 Lattice
->Properties
[i
].Free
= false;
408 else if (!strcmp(token
, "2") || !strcmp(token
, "graver") || !strcmp(token
, "g"))
412 printf("Input Error: Graver components for `hilbert' executable.\nInput Error: Use the `graver' executable instead.\n");
417 Lattice
->Properties
[i
].Upper
= MAXINT
;
418 Lattice
->Properties
[i
].Lower
= -MAXINT
;
419 Lattice
->Properties
[i
].Free
= false;
424 printf("Unknown token '%s' in SIGN file %s.sign.\n", token
, BaseName
);
433 deleteVectorArray(Lattice
);
440 strcat(BaseName
, ".ub");
441 stream
= fopen(BaseName
, "r");
442 BaseName
[BaseLength
] = '\0';
449 if (fscanf(stream
, "%d %d", &r
, &i
)<2 || i
!= Lattice
->Variables
|| r
!= 1)
451 printf("UPPER BOUNDS file %s.ub must start with '1 %d'.\n", BaseName
, Lattice
->Variables
);
455 for (i
=0; i
<Lattice
->Variables
; i
++)
457 if (readTokenFromFile(stream
, "0123456789*-", &token
, &memory
) == 0)
459 printf("UPPER BOUNDS file %s.ub ends unexpectedly.\n", BaseName
);
462 if (!strcmp(token
, "*"))
463 Lattice
->Properties
[i
].Upper
= MAXINT
;
464 else if (sscanf(token
, "%d", &j
) == 1)
466 if (Lattice
->Properties
[i
].Free
)
468 printf("Upper bound '%s' cannot be set for free variables.\n", token
);
472 Lattice
->Properties
[i
].Upper
= j
;
475 printf("Negative upper bound '%s' in UPPER BOUNDS file %s.ub.\n", token
, BaseName
);
481 printf("Unknown token '%s' in UPPER BOUNDS file %s.ub.\n", token
, BaseName
);
490 deleteVectorArray(Lattice
);
497 strcat(BaseName
, ".lb");
498 stream
= fopen(BaseName
, "r");
499 BaseName
[BaseLength
] = '\0';
506 if (fscanf(stream
, "%d %d", &r
, &i
)<2 || i
!= Lattice
->Variables
|| r
!= 1)
508 printf("LOWER BOUNDS file %s.lb must start with '1 %d'.\n", BaseName
, Lattice
->Variables
);
512 for (i
=0; i
<Lattice
->Variables
; i
++)
514 if (readTokenFromFile(stream
, "0123456789*-", &token
, &memory
) == 0)
516 printf("LOWER BOUNDS file %s.lb ends unexpectedly.\n", BaseName
);
519 if (!strcmp(token
, "*"))
520 Lattice
->Properties
[i
].Lower
= -MAXINT
;
521 else if (sscanf(token
, "%d", &j
) == 1)
523 if (Lattice
->Properties
[i
].Free
)
525 printf("Lower bound '%s' cannot be set for free variables.\n", token
);
529 Lattice
->Properties
[i
].Lower
= j
;
532 printf("Positive lower bound '%s' in LOWER BOUNDS file %s.lb.\n", token
, BaseName
);
538 printf("Unknown token '%s' in LOWER BOUNDS file %s.lb.\n", token
, BaseName
);
547 deleteVectorArray(Lattice
);
553 ctx
= createZSolveContextFromLattice(Lattice
, LogFile
, OLogging
, OVerbose
, zsolveLogCallbackDefault
, backupEvent
);
556 if (ctx
->Verbosity
>0)
558 printf("\nLattice to use:\n\n");
559 printVectorArray(ctx
->Lattice
, false);
564 fprintf(ctx
->LogFile
, "\nLattice to use:\n\n");
565 fprintVectorArray(ctx
->LogFile
, ctx
->Lattice
, false);
566 fprintf(ctx
->LogFile
, "\n\n");
569 // END OF LATTICE SECTION
574 // START OF SYSTEM SECTION - READ FILES AND CREATE CONTEXT
576 matrix
= readMatrix(stream
);
580 printf("Matrix file %s does not contain valid data.\n", BaseName
);
583 fprintf(LogFile
, "Matrix file %s does not contain valid data.\n", BaseName
);
593 strcat(BaseName
, ".rhs");
594 stream
= fopen(BaseName
, "r");
595 BaseName
[BaseLength
] = '\0';
598 if (OGraver
|| OHilbert
)
601 printf("Input Error: No rhs file is allowed with --graver and --hilbert!\n");
602 printf("Input Error: Please delete %s.rhs and rerun zsolve\n", BaseName
);
605 fprintf(LogFile
, "Input Error: No rhs file is allowed with --graver and --hilbert!\n");
606 fprintf(LogFile
, "Input Error: Please delete %s.rhs and rerun zsolve\n", BaseName
);
609 deleteMatrix(matrix
);
614 fscanf(stream
, "%d", &i
);
618 printf("Height of RHS must be 1!\n");
621 fprintf(LogFile
, "Height of RHS must be 1!\n");
624 deleteMatrix(matrix
);
628 fscanf(stream
, "%d", &i
);
629 if (i
!=matrix
->Height
)
632 printf("Matrix height conflicts with width of rhs!\n");
635 fprintf(LogFile
, "Matrix height conflicts with width of rhs!\n");
638 deleteMatrix(matrix
);
642 rhs
= readVector(stream
, matrix
->Height
);
646 printf("RHS file %s.rhs does not contain valid data.\n", BaseName
);
649 fprintf(LogFile
, "RHS file %s.rhs does not contain valid data.\n", BaseName
);
652 deleteMatrix(matrix
);
662 rhs
= createVector(matrix
->Height
);
663 for (i
=0; i
<matrix
->Height
; i
++)
668 initialsystem
= createLinearSystem();
670 setLinearSystemMatrix(initialsystem
, matrix
);
671 deleteMatrix(matrix
);
673 setLinearSystemRHS(initialsystem
, rhs
);
679 setLinearSystemLimit(initialsystem
, -1, -MAXINT
, MAXINT
, false);
681 setLinearSystemLimit(initialsystem
, -1, 0, MAXINT
, false);
683 setLinearSystemLimit(initialsystem
, -1, -MAXINT
, MAXINT
, true);
685 // default equation type
687 setLinearSystemEquationType(initialsystem
, -1, EQUATION_EQUAL
, 0);
690 strcat(BaseName
, ".rel");
691 stream
= fopen(BaseName
, "r");
692 BaseName
[BaseLength
] = '\0';
699 if (fscanf(stream
, "%d %d", &r
, &i
)<2 || i
!= initialsystem
->Equations
|| r
!= 1)
701 printf("RELATION file %s.rel must start with '1 %d'.\n", BaseName
, initialsystem
->Equations
);
705 for (i
=0; i
<initialsystem
->Equations
; i
++)
707 if (readTokenFromFile(stream
, "0123456789=<>", &token
, &memory
) == 0)
709 printf("RELATION file %s.rel ends unexpectedly.\n", BaseName
);
712 if (!strcmp(token
, "="))
713 setLinearSystemEquationType(initialsystem
, i
, EQUATION_EQUAL
, 0);
714 // BUG: Not a real bug, but maybe misdefinition?? <= is not so hard to type :-)
715 else if (!strcmp(token
, "<"))
716 setLinearSystemEquationType(initialsystem
, i
, EQUATION_LESSEREQUAL
, 0);
717 else if (!strcmp(token
, ">"))
718 setLinearSystemEquationType(initialsystem
, i
, EQUATION_GREATEREQUAL
, 0);
721 printf("Unknown token '%s' in RELATION file %s.rel.\n", token
, BaseName
);
730 deleteLinearSystem(initialsystem
);
737 strcat(BaseName
, ".sign");
738 stream
= fopen(BaseName
, "r");
739 BaseName
[BaseLength
] = '\0';
746 if (fscanf(stream
, "%d %d", &r
, &i
)<2 || i
!= initialsystem
->Variables
|| r
!= 1)
748 printf("SIGN file %s.sign must start with '1 %d'.\n", BaseName
, initialsystem
->Variables
);
752 for (i
=0; i
<initialsystem
->Variables
; i
++)
754 if (readTokenFromFile(stream
, "0123456789-abcdefghijklmnopqrstuvwxyz", &token
, &memory
) == 0)
756 printf("SIGN file %s.sign ends unexpectedly.\n", BaseName
);
759 if (!strcmp(token
, "0") || !strcmp(token
, "free") || !strcmp(token
, "f"))
760 setLinearSystemLimit(initialsystem
, i
, -MAXINT
, MAXINT
, true);
761 else if (!strcmp(token
, "1") || !strcmp(token
, "hil") || !strcmp(token
, "h"))
762 setLinearSystemLimit(initialsystem
, i
, 0, MAXINT
, false);
763 else if (!strcmp(token
, "-1") || !strcmp(token
, "-hil") || !strcmp(token
, "-h"))
764 setLinearSystemLimit(initialsystem
, i
, -MAXINT
, 0, false);
765 else if (!strcmp(token
, "2") || !strcmp(token
, "graver") || !strcmp(token
, "g"))
770 printf("Input Error: Graver components for `hilbert' executable.\nInput Error: Use the `graver' executable instead.\n");
774 setLinearSystemLimit(initialsystem
, i
, -MAXINT
, MAXINT
, false);
778 printf("Unknown token '%s' in SIGN file %s.sign.\n", token
, BaseName
);
787 deleteLinearSystem(initialsystem
);
794 strcat(BaseName
, ".ub");
795 stream
= fopen(BaseName
, "r");
796 BaseName
[BaseLength
] = '\0';
803 if (fscanf(stream
, "%d %d", &r
, &i
)<2 || i
!= initialsystem
->Variables
|| r
!= 1)
805 printf("UPPER BOUNDS file %s.ub must start with '1 %d'.\n", BaseName
, initialsystem
->Variables
);
809 for (i
=0; i
<initialsystem
->Variables
; i
++)
811 if (readTokenFromFile(stream
, "0123456789*-", &token
, &memory
) == 0)
813 printf("UPPER BOUNDS file %s.ub ends unexpectedly.\n", BaseName
);
816 if (!strcmp(token
, "*"))
817 setLinearSystemBound(initialsystem
, i
, 'u', MAXINT
);
818 else if (sscanf(token
, "%d", &j
) == 1)
820 if (initialsystem
->VarProperties
[i
].Free
)
822 printf("Upper bound '%s' cannot be set for free variables.\n", token
);
826 setLinearSystemBound(initialsystem
, i
, 'u', j
);
829 printf("Negative upper bound '%s' in UPPER BOUNDS file %s.ub.\n", token
, BaseName
);
835 printf("Unknown token '%s' in UPPER BOUNDS file %s.ub.\n", token
, BaseName
);
844 deleteLinearSystem(initialsystem
);
851 strcat(BaseName
, ".lb");
852 stream
= fopen(BaseName
, "r");
853 BaseName
[BaseLength
] = '\0';
860 if (fscanf(stream
, "%d %d", &r
, &i
)<2 || i
!= initialsystem
->Variables
|| r
!= 1)
862 printf("LOWER BOUNDS file %s.lb must start with '1 %d'.\n", BaseName
, initialsystem
->Variables
);
866 for (i
=0; i
<initialsystem
->Variables
; i
++)
868 if (readTokenFromFile(stream
, "0123456789*-", &token
, &memory
) == 0)
870 printf("LOWER BOUNDS file %s.lb ends unexpectedly.\n", BaseName
);
873 if (!strcmp(token
, "*"))
874 setLinearSystemBound(initialsystem
, i
, 'l', -MAXINT
);
875 else if (sscanf(token
, "%d", &j
) == 1)
877 if (initialsystem
->VarProperties
[i
].Free
)
879 printf("Lower bound '%s' cannot be set for free variables.\n", token
);
883 setLinearSystemBound(initialsystem
, i
, 'l', j
);
886 printf("Positive lower bound '%s' in LOWER BOUNDS file %s.lb.\n", token
, BaseName
);
892 printf("Unknown token '%s' in LOWER BOUNDS file %s.lb.\n", token
, BaseName
);
901 deleteLinearSystem(initialsystem
);
907 ctx
= createZSolveContextFromSystem(initialsystem
, LogFile
, OLogging
, OVerbose
, zsolveLogCallbackDefault
, backupEvent
);
909 // END OF SYSTEM SECTION
914 // printVectorArray(ctx->Lattice, true);
916 zsolveSystem(ctx
, !OResume
);
920 printf("Writing %d vectors to graver file, with respect to symmetry.\n", ctx
->Graver
->Size
);
922 fprintf(LogFile
, "Writing %d vectors to graver file, with respect to symmetry.\n", ctx
->Graver
->Size
);
924 strcat(BaseName
, ".gra");
925 stream
= fopen(BaseName
, "w");
926 BaseName
[BaseLength
] = '\0';
929 fprintf(stream
, "%d %d\n\n", ctx
->Graver
->Size
, ctx
->Graver
->Variables
);
930 fprintVectorArray(stream
, ctx
->Graver
, false);
936 strcat(BaseName
, ".hil");
937 stream
= fopen(BaseName
, "w");
938 BaseName
[BaseLength
] = '\0';
941 fprintf(stream
, "%d %d\n\n", ctx
->Homs
->Size
+ ctx
->Frees
->Size
, ctx
->Homs
->Variables
);
942 fprintVectorArray(stream
, ctx
->Homs
, false);
943 fprintf(stream
, "\n");
944 fprintVectorArray(stream
, ctx
->Frees
, false);
950 strcat(BaseName
, ".zinhom");
951 stream
= fopen(BaseName
, "w");
952 BaseName
[BaseLength
] = '\0';
955 fprintf(stream
, "%d %d\n\n", ctx
->Inhoms
->Size
, ctx
->Inhoms
->Variables
);
956 fprintVectorArray(stream
, ctx
->Inhoms
, false);
960 strcat(BaseName
, ".zhom");
961 stream
= fopen(BaseName
, "w");
962 BaseName
[BaseLength
] = '\0';
965 fprintf(stream
, "%d %d\n\n", ctx
->Homs
->Size
, ctx
->Homs
->Variables
);
966 fprintVectorArray(stream
, ctx
->Homs
, false);
970 if (ctx
->Frees
->Size
>0)
972 strcat(BaseName
, ".zfree");
973 stream
= fopen(BaseName
, "w");
974 BaseName
[BaseLength
] = '\0';
977 fprintf(stream
, "%d %d\n\n", ctx
->Frees
->Size
, ctx
->Frees
->Variables
);
978 fprintVectorArray(stream
, ctx
->Frees
, false);
985 printf("\n4ti2 Total Time: ");
986 printCPUTime(maxd(getCPUTime() - ctx
->AllTime
, 0.0));
989 fprintf(LogFile
, "\n4ti2 Total Time: ");
990 fprintCPUTime(LogFile
, maxd(getCPUTime() - ctx
->AllTime
, 0.0));
991 fprintf(LogFile
, "\n");
994 deleteZSolveContext(ctx
, true);
1002 return EXIT_SUCCESS
;