Skip to content

Commit

Permalink
abstract the saturation index
Browse files Browse the repository at this point in the history
  • Loading branch information
sumiya11 committed Oct 28, 2023
1 parent 36feaac commit fbe77de
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 27 deletions.
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
┌ Info:
└ FUNCTION_NAME = "find_identifiable_functions"
┌ Info:
└ PROBLEM_NAME = "cholera"
┌ Info:
└ KWARGS = (with_states = true,)
┌ Info:
└ GLOBAL_ID = :with_states
Internal error: encountered unexpected error in runtime:
ReadOnlyMemoryError()

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: UNKNOWN at 0x7ffedb2acf19 --
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
┌ Info:
└ FUNCTION_NAME = "find_identifiable_functions"
┌ Info:
└ PROBLEM_NAME = "generalizedLoktaVolterra (1o)"
┌ Info:
└ KWARGS = (with_states = true,)
┌ Info:
└ GLOBAL_ID = :with_states
Internal error: encountered unexpected error in runtime:
ReadOnlyMemoryError()

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: UNKNOWN at 0x7ffedb2acf19 --
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
┌ Info:
└ FUNCTION_NAME = "find_identifiable_functions"
┌ Info:
└ PROBLEM_NAME = "generalizedLoktaVolterra (2o)"
┌ Info:
└ KWARGS = (with_states = true,)
┌ Info:
└ GLOBAL_ID = :with_states
Internal error: encountered unexpected error in runtime:
ReadOnlyMemoryError()

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: UNKNOWN at 0x7ffedb2acf19 --
13 changes: 13 additions & 0 deletions benchmarking/IdentifiableFunctions/results/p53/logs_with_states
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
┌ Info:
└ FUNCTION_NAME = "find_identifiable_functions"
┌ Info:
└ PROBLEM_NAME = "p53"
┌ Info:
└ KWARGS = (with_states = true,)
┌ Info:
└ GLOBAL_ID = :with_states
Internal error: encountered unexpected error in runtime:
ReadOnlyMemoryError()

Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: UNKNOWN at 0x7ffedb2acf19 --
49 changes: 34 additions & 15 deletions src/RationalFunctionFields/IdealMQS.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,22 @@ mutable struct IdealMQS{T} <: AbstractBlackboxIdeal
function IdealMQS(
funcs_den_nums::Vector{Vector{PolyQQ}};
sat_varname = "t",
sat_var_position = :first,
ordering = :degrevlex,
) where {PolyQQ}
# We are given polynomials of form
# [[f1, f2, f3, ...], [g1, g2, g3, ...], ...]
# We prepare and store them to construct ideal specializations later
@assert !isempty(funcs_den_nums)
@assert sat_var_position in (:first, :last)
ordering !== :degrevlex && (@warn "Ordering is not degrevlex but $ordering")
ring = parent(first(first(funcs_den_nums)))
@debug "Constructing the MQS ideal in $ring"
K, n = base_ring(ring), nvars(ring)
@debug "Finding pivot polynomials"
# In the component f1,f2,... find the polynomial with the minimal total
# degree. Such element will serve as a normalizing term for the
# component
# degree and length. Such element will serve as a normalizing term for
# the component
funcs_den_nums = map(plist -> filter(!iszero, plist), funcs_den_nums)
# funcs_den_nums = filter(plist -> length(plist) > 1, funcs_den_nums)
@assert !isempty(funcs_den_nums) "All elements of the ideal are zero"
Expand All @@ -90,15 +92,25 @@ mutable struct IdealMQS{T} <: AbstractBlackboxIdeal
existing_varnames = map(String, symbols(ring))
ystrs = ["y$i" for i in 1:length(existing_varnames)]
@assert !(sat_varname in ystrs) "The name of the saturation variable collided with a primary variable"
sat_var_index = 1
varnames = vcat([sat_varname], ystrs)
sat_var_index = if sat_var_position === :first
1
else
@assert sat_var_position === :last

Check warning on line 98 in src/RationalFunctionFields/IdealMQS.jl

View check run for this annotation

Codecov / codecov/patch

src/RationalFunctionFields/IdealMQS.jl#L98

Added line #L98 was not covered by tests
length(ystrs) + 1
end
varnames = append_at_index(ystrs, sat_var_index, sat_varname)
@debug "Saturating variable is $sat_varname, index is $sat_var_index"
flush(stdout)
R_sat, v_sat = Nemo.PolynomialRing(K, varnames, ordering = ordering)
# Saturation
t_sat = v_sat[sat_var_index]
den_lcm_orig = den_lcm
den_lcm = parent_ring_change(den_lcm, R_sat, matching = :byindex, shift = 1)
den_lcm = parent_ring_change(
den_lcm,
R_sat,
matching = :byindex,
shift = Int(sat_var_index == 1),
)
den_lcm_sat = parent_ring_change(den_lcm, R_sat)
sat_qq = den_lcm_sat * t_sat - 1
# We construct the array of numerators nums_qq and the array of
Expand All @@ -113,13 +125,23 @@ mutable struct IdealMQS{T} <: AbstractBlackboxIdeal
for i in 1:length(funcs_den_nums)
plist = funcs_den_nums[i]
den = plist[pivots_indices[i]]
den = parent_ring_change(den, R_sat, matching = :byindex, shift = 1)
den = parent_ring_change(
den,
R_sat,
matching = :byindex,
shift = Int(sat_var_index == 1),
)
push!(dens_qq, den)
push!(dens_indices, (length(nums_qq) + 1, length(nums_qq) + length(plist) - 1))
for j in 1:length(plist)
j == pivots_indices[i] && continue
num = plist[j]
num = parent_ring_change(num, R_sat, matching = :byindex, shift = 1)
num = parent_ring_change(
num,
R_sat,
matching = :byindex,
shift = Int(sat_var_index == 1),
)
push!(nums_qq, num)
end
end
Expand Down Expand Up @@ -169,6 +191,7 @@ end
end

function fractionfree_generators_raw(mqs::IdealMQS)
# TODO: this assumes mqs.sat_var_index is last, and thus is broken
ring_params = ParamPunPam.parent_params(mqs)
K = base_ring(ring_params)
varnames = map(string, Nemo.symbols(ring_params))
Expand Down Expand Up @@ -242,15 +265,13 @@ function ParamPunPam.specialize_mod_p(
@assert length(point) == nvars(ParamPunPam.parent_params(mqs))
# +1 actual variable because of the saturation!
@assert length(point) + 1 == nvars(parent(nums_gf[1]))
# NOTE: Assuming the saturating variable is the first one
@assert mqs.sat_var_index == 1
point_sat = vcat(one(K_1), point)
point_sat = append_at_index(point, mqs.sat_var_index, one(K_1))
nums_gf_spec = map(num -> evaluate(num, point_sat), nums_gf)
dens_gf_spec = map(den -> evaluate(den, point_sat), dens_gf)
polys = Vector{typeof(sat_gf)}(undef, length(nums_gf_spec) + 1)
@inbounds for i in 1:length(dens_gf_spec)
den, den_spec = dens_gf[i], dens_gf_spec[i]
iszero(den_spec) && __throw_unlucky_evaluation("Ideal: $mqs\nPoint: $point")
iszero(den_spec) && __throw_unlucky_evaluation("Point: $point")
span = dens_indices[i]
for j in span[1]:span[2]
num, num_spec = nums_gf[j], nums_gf_spec[j]
Expand All @@ -272,15 +293,13 @@ function specialize(mqs::IdealMQS, point::Vector{Nemo.fmpq}; saturated = true)
@assert length(point) == nvars(ParamPunPam.parent_params(mqs))
# +1 actual variable because of the saturation!
@assert length(point) + 1 == nvars(parent(nums_qq[1]))
# NOTE: Assuming the saturating variable is the first one
@assert mqs.sat_var_index == 1
point_sat = vcat(one(K), point)
point_sat = append_at_index(point, mqs.sat_var_index, one(K))
nums_qq_spec = map(num -> evaluate(num, point_sat), nums_qq)
dens_qq_spec = map(den -> evaluate(den, point_sat), dens_qq)
polys = Vector{typeof(sat_qq)}(undef, length(nums_qq_spec) + 1)
@inbounds for i in 1:length(dens_qq_spec)
den, den_spec = dens_qq[i], dens_qq_spec[i]
iszero(den_spec) && __throw_unlucky_evaluation("Ideal: $mqs\nPoint: $point")
iszero(den_spec) && __throw_unlucky_evaluation("Point: $point")
span = dens_indices[i]
for j in span[1]:span[2]
num, num_spec = nums_qq[j], nums_qq_spec[j]
Expand Down
5 changes: 2 additions & 3 deletions src/RationalFunctionFields/RationalFunctionField.jl
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ function simplified_generating_set(
check_variables = false, # almost always slows down and thus turned off
rational_interpolator = :VanDerHoevenLecerf,
)
@info "Simplifying identifiable functions"
@info "Simplifying generating set"
_runtime_logger[:id_groebner_time] = 0.0
_runtime_logger[:id_calls_to_gb] = 0
_runtime_logger[:id_inclusion_check_mod_p] = 0.0
Expand All @@ -502,8 +502,7 @@ function simplified_generating_set(
_runtime_logger[:id_normalforms_time] = 0.0
_runtime_logger[:id_ranking] = 0

# Checking identifiability of particular variables and adding them to the
# field
# Checking membership of particular variables and adding them to the field
if check_variables
vars = gens(poly_ring(rff))
containment = field_contains(rff, vars, (1.0 + p) / 2)
Expand Down
15 changes: 7 additions & 8 deletions src/RationalFunctionFields/normalforms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,14 @@ function local_normal_forms(
)
@assert !isempty(point)
@assert parent(first(point)) == finite_field
@assert mqs.sat_var_index == 1
point_ff_ext = vcat(one(finite_field), point)
point_ff_ext = append_at_index(point, mqs.sat_var_index, one(finite_field))
gens_ff_spec = specialize_mod_p(mqs, point)
gb_ff_spec = Groebner.groebner(gens_ff_spec)
ring_ff = parent(gb_ff_spec[1])
xs_ff = gens(ring_ff)
normal_forms_ff = Vector{elem_type(ring_ff)}(undef, 0)
monoms_ff = Vector{elem_type(ring_ff)}(undef, 0)
@assert mqs.sat_var_index == 1
xs_ff = xs_ff[2:end]
xs_ff = cut_at_index(xs_ff, mqs.sat_var_index)
pivot_vectors = map(f -> exponent_vector(f, 1), xs_ff)
@debug """
variables in the finite field: $(xs_ff)
Expand Down Expand Up @@ -359,8 +357,7 @@ function linear_relations_between_normal_forms(
n_relations_ff = length(complete_intersection_relations_ff)
# Filter out some relations from the complete intersection
zeroed_relations_inds = Vector{Int}()
@assert mqs.sat_var_index == 1
point_ext = vcat(one(finite_field), point)
point_ext = append_at_index(point, mqs.sat_var_index, one(finite_field))
for i in 1:length(complete_intersection_relations_ff)
relation = complete_intersection_relations_ff[i]
relation_mqs = relation - evaluate(relation, point_ext)
Expand Down Expand Up @@ -411,8 +408,10 @@ function linear_relations_between_normal_forms(
modulo: $finite_field"""
throw(ErrorException("Rational reconstruction failed."))
end
@assert mqs.sat_var_index == 1
relation_qq_param = evaluate(relation_qq, vcat(one(ring_param), xs_param))
relation_qq_param = evaluate(
relation_qq,
append_at_index(xs_param, mqs.sat_var_index, one(ring_param)),
)
relations_qq[i] = relation_qq_param // one(relation_qq_param)
end
relations_qq
Expand Down
23 changes: 22 additions & 1 deletion src/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,27 @@ end

# ------------------------------------------------------------------------------

function append_at_index(vec::Vector{T}, idx::Integer, val::T) where {T}
# NOTE: could also just use insert!
@assert (idx == 1) || (idx == length(vec) + 1)
if idx == 1
vcat(val, vec)
else
vcat(vec, val)

Check warning on line 19 in src/util.jl

View check run for this annotation

Codecov / codecov/patch

src/util.jl#L19

Added line #L19 was not covered by tests
end
end

function cut_at_index(vec::Vector{T}, idx::Integer) where {T}
@assert (idx == 1) || (idx == length(vec))
if idx == 1
vec[2:end]
else
vec[1:(end - 1)]

Check warning on line 28 in src/util.jl

View check run for this annotation

Codecov / codecov/patch

src/util.jl#L28

Added line #L28 was not covered by tests
end
end

# ------------------------------------------------------------------------------

"""
eval_at_dict(f, d)
Expand Down Expand Up @@ -398,7 +419,7 @@ end

function str_to_var(s::String, ring::MPolyRing)
ind = findfirst(v -> (string(v) == s), symbols(ring))
if ind == nothing
if ind === nothing
throw(Base.KeyError("Variable $s is not found in ring $ring"))
end
return gens(ring)[ind]
Expand Down

0 comments on commit fbe77de

Please sign in to comment.