1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
/*
Copyright (C) 2020 Fredrik Johansson
This file is part of Calcium.
Calcium is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See <http://www.gnu.org/licenses/>.
*/
#include "utils_flint.h"
static int
within_limits(const fmpz_mpoly_t poly, slong poly_len_limit, slong poly_bits_limit, const fmpz_mpoly_ctx_t ctx)
{
slong bits;
if (fmpz_mpoly_length(poly, ctx) > poly_len_limit)
return 0;
bits = fmpz_mpoly_max_bits(poly);
bits = FLINT_ABS(bits);
if (bits > poly_bits_limit)
return 0;
return 1;
}
static int
fmpz_mpoly_disjoint_lt(const fmpz_mpoly_t f, const fmpz_mpoly_t g, const fmpz_mpoly_ctx_t ctx)
{
int result;
slong i, nvars;
ulong * exp1, * exp2;
nvars = ctx->minfo->nvars;
exp1 = flint_malloc(2 * nvars * sizeof(ulong));
exp2 = exp1 + nvars;
fmpz_mpoly_get_term_exp_ui(exp1, f, 0, ctx);
fmpz_mpoly_get_term_exp_ui(exp2, g, 0, ctx);
result = 1;
for (i = 0; i < nvars && result; i++)
if (exp1[i] && exp2[i])
result = 0;
flint_free(exp1);
return result;
}
int
fmpz_mpoly_buchberger_naive_with_limits(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F,
slong ideal_len_limit, slong poly_len_limit, slong poly_bits_limit, const fmpz_mpoly_ctx_t ctx)
{
pairs_t B;
fmpz_mpoly_t h;
slong i, j, index_h;
pair_t pair;
int success;
fmpz_mpoly_vec_set_primitive_unique(G, F, ctx);
if (G->length <= 1)
return 1;
if (G->length >= ideal_len_limit)
return 0;
for (i = 0; i < G->length; i++)
if (!within_limits(fmpz_mpoly_vec_entry(G, i), poly_len_limit, poly_bits_limit, ctx))
return 0;
pairs_init(B);
fmpz_mpoly_init(h, ctx);
for (i = 0; i < G->length; i++)
for (j = i + 1; j < G->length; j++)
if (!fmpz_mpoly_disjoint_lt(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, j), ctx))
pairs_append(B, i, j);
success = 1;
while (B->length != 0)
{
pair = fmpz_mpoly_select_pop_pair(B, G, ctx);
fmpz_mpoly_spoly(h, fmpz_mpoly_vec_entry(G, pair.a), fmpz_mpoly_vec_entry(G, pair.b), ctx);
fmpz_mpoly_reduction_primitive_part(h, h, G, ctx);
if (!fmpz_mpoly_is_zero(h, ctx))
{
/* printf("h stats %ld, %ld, %ld\n", h->length, h->bits, G->length); */
if (G->length >= ideal_len_limit || !within_limits(h, poly_len_limit, poly_bits_limit, ctx))
{
success = 0;
break;
}
index_h = G->length;
fmpz_mpoly_vec_append(G, h, ctx);
for (i = 0; i < index_h; i++)
if (!fmpz_mpoly_disjoint_lt(fmpz_mpoly_vec_entry(G, i), fmpz_mpoly_vec_entry(G, index_h), ctx))
pairs_append(B, i, index_h);
}
}
fmpz_mpoly_clear(h, ctx);
pairs_clear(B);
return success;
}
void
fmpz_mpoly_buchberger_naive(fmpz_mpoly_vec_t G, const fmpz_mpoly_vec_t F, const fmpz_mpoly_ctx_t ctx)
{
fmpz_mpoly_buchberger_naive_with_limits(G, F, WORD_MAX, WORD_MAX, WORD_MAX, ctx);
}
|