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.
24 #include "vectorarray.h"
25 #include "indexarray.h"
26 #include "valuetrees.h"
34 ValueTree
createValueTree(int level
)
36 ValueTree tree
= (ValueTree
)malloc(sizeof(valuetree_t
));
40 fprintf(stderr
, "Fatal Error: Could not allocate memory for ValueTree!\n");
48 tree
->vectors
= level
<0 ? createIndexArray() : NULL
;
55 void deleteValueTree(ValueTree tree
)
61 while ((node
= tree
->pos
)!=NULL
)
63 tree
->pos
= node
->next
;
64 deleteValueTree(node
->sub
);
67 while ((node
= tree
->neg
)!=NULL
)
69 tree
->neg
= node
->next
;
70 deleteValueTree(node
->sub
);
73 deleteValueTree(tree
->zero
);
74 deleteIndexArray(tree
->vectors
);
81 void splitValueTree(ZSolveContext ctx
, ValueTree tree
, int start
)
85 ValueTreeNode node
, temp
;
87 if (!tree
|| tree
->level
>=0)
90 assert(tree
->pos
==NULL
);
91 assert(tree
->neg
==NULL
);
92 assert(tree
->zero
==NULL
);
93 assert(tree
->vectors
);
96 for (; start
<ctx
->Current
; start
++)
98 compo
= start
<0 ? ctx
->Current
: start
;
102 for (i
=0; i
<tree
->vectors
->Size
; i
++)
104 if (ctx
->Lattice
->Data
[tree
->vectors
->Data
[i
]][compo
]>0)
106 else if (ctx
->Lattice
->Data
[tree
->vectors
->Data
[i
]][compo
]<0)
115 if (start
<ctx
->Current
&& tree
->vectors
->Size
> 1)
117 compo
= start
<0 ? ctx
->Current
: start
;
118 for (i
=0; i
<tree
->vectors
->Size
; i
++)
120 value
= ctx
->Lattice
->Data
[tree
->vectors
->Data
[i
]][compo
];
124 if (node
==NULL
|| value
<node
->value
)
126 tree
->pos
= (ValueTreeNode
)malloc(sizeof(valuetreenode_t
));
127 tree
->pos
->value
= value
;
128 tree
->pos
->next
= node
;
129 tree
->pos
->sub
= createValueTree(-1);
130 appendToIndexArray(tree
->pos
->sub
->vectors
, tree
->vectors
->Data
[i
]);
134 while (node
->next
&& value
>=node
->next
->value
)
136 if (value
!=node
->value
)
138 temp
= (ValueTreeNode
)malloc(sizeof(valuetreenode_t
));
140 temp
->sub
= createValueTree(-1);
141 temp
->next
= node
->next
;
145 appendToIndexArray(node
->sub
->vectors
, tree
->vectors
->Data
[i
]);
151 if (node
==NULL
|| value
>node
->value
)
153 tree
->neg
= (ValueTreeNode
)malloc(sizeof(valuetreenode_t
));
154 tree
->neg
->value
= value
;
155 tree
->neg
->next
= node
;
156 tree
->neg
->sub
= createValueTree(-1);
157 appendToIndexArray(tree
->neg
->sub
->vectors
, tree
->vectors
->Data
[i
]);
161 while (node
->next
&& value
<=node
->next
->value
)
163 if (value
!=node
->value
)
165 temp
= (ValueTreeNode
)malloc(sizeof(valuetreenode_t
));
167 temp
->sub
= createValueTree(-1);
168 temp
->next
= node
->next
;
172 appendToIndexArray(node
->sub
->vectors
, tree
->vectors
->Data
[i
]);
177 if (tree
->zero
==NULL
)
178 tree
->zero
= createValueTree(-1);
179 appendToIndexArray(tree
->zero
->vectors
, tree
->vectors
->Data
[i
]);
183 deleteIndexArray(tree
->vectors
);
184 tree
->vectors
= NULL
;
190 splitValueTree(ctx
, node
->sub
, start
);
196 splitValueTree(ctx
, node
->sub
, start
);
200 splitValueTree(ctx
, tree
->zero
, start
);
207 void createValueTrees(ZSolveContext ctx
)
212 for (i
=0; i
<ctx
->Lattice
->Size
; i
++)
213 ctx
->MaxNorm
= maxi(ctx
->MaxNorm
, normVector(ctx
->Lattice
->Data
[i
], ctx
->Current
));
215 ctx
->Norm
= (void **)calloc(ctx
->MaxNorm
+1, sizeof(ValueTree
));
217 for (i
=0; i
<ctx
->Lattice
->Size
; i
++)
219 j
= normVector(ctx
->Lattice
->Data
[i
], ctx
->Current
);
220 // TODO is it correct, to throw out if all 0 on before and current ?! - it seems incorrect, as bayer-test fails.
221 if (j
==0 && ctx
->Lattice
->Data
[i
][ctx
->Current
] == 0)
223 // put in corresponding norm-tree
224 if (ctx
->Norm
[j
]==NULL
)
225 ctx
->Norm
[j
] = createValueTree(-1);
226 appendToIndexArray( ((ValueTree
*)ctx
->Norm
)[j
]->vectors
, i
);
229 for (i
=0; i
<=ctx
->MaxNorm
; i
++)
230 splitValueTree(ctx
, ctx
->Norm
[i
], -1);
235 void deleteValueTrees(ZSolveContext ctx
)
239 for (i
=0; i
<=ctx
->MaxNorm
; i
++)
240 deleteValueTree(ctx
->Norm
[i
]);
248 bool enumValueReducer(ZSolveContext ctx
, ValueTree tree
)
258 value
= ctx
->Sum
[tree
->level
];
262 while (node
&& node
->value
<=value
)
264 if (enumValueReducer(ctx
, node
->sub
))
272 while (node
&& node
->value
>=value
)
274 if (enumValueReducer(ctx
, node
->sub
))
279 if (enumValueReducer(ctx
, tree
->zero
))
284 for (i
=0; i
<tree
->vectors
->Size
; i
++)
286 Reducer
= ctx
->Lattice
->Data
[tree
->vectors
->Data
[i
]];
287 /* printf("=> Testing reduction of [");
288 printVector(ctx->Sum, ctx->Variables);
290 printVector(Reducer, ctx->Variables);
292 for (j
=0; j
<=ctx
->Current
; j
++)
293 if (Reducer
[j
]*ctx
->Sum
[j
]<0 || abs(ctx
->Sum
[j
])<abs(Reducer
[j
]))
305 void insertVectorToValueTree(ZSolveContext ctx
, ValueTree tree
, int index
)
308 ValueTreeNode node
, temp
;
311 assert(index
>=0 && index
<ctx
->Lattice
->Size
);
315 value
= ctx
->Lattice
->Data
[index
][tree
->level
];
319 if (node
==NULL
|| value
<node
->value
)
321 tree
->pos
= (ValueTreeNode
)malloc(sizeof(valuetreenode_t
));
322 tree
->pos
->value
= value
;
323 tree
->pos
->next
= node
;
324 tree
->pos
->sub
= createValueTree(-1);
325 appendToIndexArray(tree
->pos
->sub
->vectors
, index
);
329 while (node
->next
&& value
>=node
->next
->value
)
331 if (value
==node
->value
)
332 insertVectorToValueTree(ctx
, node
->sub
, index
);
335 temp
= (ValueTreeNode
)malloc(sizeof(valuetreenode_t
));
337 temp
->sub
= createValueTree(-1);
338 appendToIndexArray(temp
->sub
->vectors
, index
);
339 temp
->next
= node
->next
;
347 if (node
==NULL
|| value
>node
->value
)
349 tree
->neg
= (ValueTreeNode
)malloc(sizeof(valuetreenode_t
));
350 tree
->neg
->value
= value
;
351 tree
->neg
->next
= node
;
352 tree
->neg
->sub
= createValueTree(-1);
353 appendToIndexArray(tree
->neg
->sub
->vectors
, index
);
357 while (node
->next
&& value
<=node
->next
->value
)
359 if (value
==node
->value
)
360 insertVectorToValueTree(ctx
, node
->sub
, index
);
363 temp
= (ValueTreeNode
)malloc(sizeof(valuetreenode_t
));
365 temp
->sub
= createValueTree(-1);
366 appendToIndexArray(temp
->sub
->vectors
, index
);
367 temp
->next
= node
->next
;
374 if (tree
->zero
==NULL
)
376 tree
->zero
= createValueTree(-1);
377 appendToIndexArray(tree
->zero
->vectors
, index
);
380 insertVectorToValueTree(ctx
, tree
->zero
, index
);
385 appendToIndexArray(tree
->vectors
, index
);
386 splitValueTree(ctx
, tree
, -1);
392 void insertVectorToValueTrees(ZSolveContext ctx
, Vector vector
, int norm
)
394 if (norm
>ctx
->MaxNorm
)
396 ctx
->Norm
= (void **)realloc(ctx
->Norm
, (norm
+1)*sizeof(ValueTree
));
397 while (norm
>ctx
->MaxNorm
)
398 ctx
->Norm
[++ctx
->MaxNorm
] = NULL
;
401 appendToVectorArray(ctx
->Lattice
, vector
);
402 if (ctx
->Norm
[norm
]==NULL
)
404 ctx
->Norm
[norm
] = createValueTree(-1);
405 appendToIndexArray(((ValueTree
*)ctx
->Norm
)[norm
]->vectors
, ctx
->Lattice
->Size
-1);
408 insertVectorToValueTree(ctx
, ctx
->Norm
[norm
], ctx
->Lattice
->Size
-1);
413 void buildValueSum(ZSolveContext ctx
)
423 if (ctx
->First
==ctx
->Second
)
427 if (ctx
->First
[ctx
->Current
]*ctx
->Second
[ctx
->Current
]>0)
430 for (i
=0; i
<ctx
->Current
; i
++)
431 if (ctx
->First
[i
]*ctx
->Second
[i
]<0)
438 for (i
=0; i
<ctx
->Variables
; i
++)
440 ctx
->Sum
[i
] = ctx
->First
[i
] + ctx
->Second
[i
];
442 norm
+= abs(ctx
->Sum
[i
]);
449 /* printf("build: [");
450 printVector(ctx->Sum, ctx->Variables);
455 for (i
=0; i
<=norm
/2; i
++)
459 if (enumValueReducer(ctx
, ctx
->Norm
[i
]))
467 // printf("(reduced)\n");
472 for (i
=0; i
<ctx
->Current
; i
++)
474 if (ctx
->Lattice
->Properties
[i
].Lower
>ctx
->Sum
[i
]) {
475 // printf("(lower bounds failed)\n");
478 if (ctx
->Lattice
->Properties
[i
].Upper
<ctx
->Sum
[i
]) {
479 // printf("(upper bounds failed)\n");
484 if (norm
<=ctx
->MaxNorm
)
485 if (enumValueReducer(ctx
, ctx
->Norm
[norm
]))
488 insertVectorToValueTrees(ctx
, copyVector(ctx
->Sum
, ctx
->Variables
), norm
);
492 for (i
=0; i
<ctx
->Variables
; i
++)
493 ctx
->Sum
[i
] = -ctx
->Sum
[i
];
494 insertVectorToValueTrees(ctx
, copyVector(ctx
->Sum
, ctx
->Variables
), norm
);
500 void enumValueSecond(ZSolveContext ctx
, ValueTree tree
)
507 if (tree
->level
==ctx
->Current
)
509 if (ctx
->First
[ctx
->Current
]>=0)
514 enumValueSecond(ctx
, node
->sub
);
518 if (ctx
->First
[ctx
->Current
]<=0)
523 enumValueSecond(ctx
, node
->sub
);
528 else if (tree
->level
>=0)
530 if (ctx
->First
[tree
->level
]<=0)
535 enumValueSecond(ctx
, node
->sub
);
539 enumValueSecond(ctx
, tree
->zero
);
540 if (ctx
->First
[tree
->level
]>=0)
545 enumValueSecond(ctx
, node
->sub
);
552 assert(tree
->vectors
);
554 for (i
=0; tree
->vectors
!=NULL
&& i
<tree
->vectors
->Size
; i
++)
556 ctx
->Second
= ctx
->Lattice
->Data
[tree
->vectors
->Data
[i
]];
557 if (ctx
->Second
[ctx
->Current
]!=0)
560 if (tree
->vectors
==NULL
)
561 enumValueSecond(ctx
, tree
);
568 void enumValueFirst(ZSolveContext ctx
, ValueTree tree
, int norm
)
582 enumValueFirst(ctx
, node
->sub
, norm
);
585 enumValueFirst(ctx
, tree
->zero
, norm
);
589 enumValueFirst(ctx
, node
->sub
, norm
);
595 assert(tree
->vectors
);
597 for (i
=0; tree
->vectors
!=NULL
&& i
<tree
->vectors
->Size
; i
++)
599 ctx
->First
= ctx
->Lattice
->Data
[tree
->vectors
->Data
[i
]];
600 if ((!ctx
->Symmetric
&& ctx
->First
[ctx
->Current
]<0) || ctx
->First
[ctx
->Current
]>0)
601 enumValueSecond(ctx
, ctx
->Norm
[norm
]);
604 if (tree
->vectors
==NULL
)
605 enumValueFirst(ctx
, tree
, norm
);
612 void completeValueTrees(ZSolveContext ctx
, int norm1
, int norm2
)
615 assert(!(norm1
>ctx
->MaxNorm
|| norm2
>ctx
->MaxNorm
|| ctx
->Norm
[norm1
]==NULL
|| ctx
->Norm
[norm2
]==NULL
));
617 enumValueFirst(ctx
, ctx
->Norm
[norm1
], norm2
);