1 #ifndef VCSN_ALGOS_REDUCE_HH
2 # define VCSN_ALGOS_REDUCE_HH
5 # include <unordered_map>
84 template<
typename Weightset>
87 template<
typename Reduc,
typename Vector>
90 unsigned begin,
unsigned* permutation)
92 return that->find_pivot(v, begin, permutation);
95 template<
typename Reduc,
typename Vector>
98 Vector& current,
unsigned b,
unsigned* permutation)
100 that->reduce_vector(vbasis, current, b, permutation);
103 template<
typename Reduc,
typename Vector>
106 unsigned pivot,
unsigned* permutation)
108 that->normalisation_vector(v, pivot, permutation);
111 template<
typename Reduc,
typename Basis>
115 that->bottom_up_reduction(basis, permutation);
118 template<
typename Reduc,
typename Basis,
typename Vector>
121 Vector& current, Vector& new_vector,
122 unsigned* permutation)
124 that->vector_in_new_basis(basis, current, new_vector, permutation);
131 template<
typename Reduc,
typename Vector>
134 unsigned begin,
unsigned* permutation)
136 return that->find_pivot_by_norm(v, begin, permutation);
143 template<
typename Reduc,
typename Vector>
146 unsigned begin,
unsigned* permutation)
148 return that->find_pivot_by_norm(v, begin, permutation);
155 template<
typename Reduc,
typename Vector>
158 unsigned begin,
unsigned* permutation)
160 return that->find_pivot_by_norm(v, begin, permutation);
163 template <
typename Reduc,
typename Vector>
166 Vector& current,
unsigned b,
unsigned* permutation)
168 that->z_reduce_vector(vbasis, current, b, permutation);
171 template <
typename Reduc,
typename Vector>
175 template<
typename Reduc,
typename Basis>
179 template<
typename Reduc,
typename Basis,
typename Vector>
182 Vector& current, Vector& new_vector,
183 unsigned* permutation)
185 that->z_vector_in_new_basis(basis, current, new_vector, permutation);
189 template <
typename Aut>
193 "reduce: requires free labelset");
199 =
typename automaton_t::element_type::automaton_nocv_t;
205 using matrix_t = std::vector<std::map<std::size_t, weight_t> > ;
217 std::unordered_map<state_t, unsigned> state_to_index;
219 for (
auto s:
input_->states())
220 state_to_index[s] = i++;
227 for (
auto t :
input_->initial_transitions())
230 for (
auto t :
input_->final_transitions())
231 final[state_to_index[
input_->src_of(t)]] =
input_->weight_of(t);
233 for (
auto t :
input_->transitions())
239 it->second[state_to_index[
input_->src_of(t)]]
240 [state_to_index[
input_->dst_of(t)]] =
input_->weight_of(t);
254 unsigned j = it.first;
255 res[j] =
ws_.add(res[j],
ws_.mul(v[i], it.second));
265 res =
ws_.add(res,
ws_.mul(v[i], w[i]));
292 return fabs(w)+fabs(1/w);
304 unsigned* permutation)
308 for (
unsigned i = begin; i <
dimension; ++i)
309 if (!
ws_.is_zero(v[permutation[i]])
310 && (pivot == dimension
311 ||
ws_.less_than(
norm(v[permutation[i]]), min)))
314 min =
norm(v[permutation[i]]);
339 res =
gcd(-x, y, a, b);
344 res =
gcd(x, -y, a, b);
348 res =
gcd(y, x, b, a);
352 res =
gcd(y, z, b, a);
356 assert(res == a * x + b * y);
368 unsigned nb,
unsigned* permutation)
370 unsigned pivot = permutation[nb];
371 if (
ws_.is_zero(current[pivot]))
379 for (
unsigned i = nb; i <
dimension; ++i)
381 weight_t tmp = current[permutation[i]];
382 current[permutation[i]] = bp*tmp - cp*vbasis[permutation[i]];
383 vbasis[permutation[i]] = a*vbasis[permutation[i]] + b*tmp;
389 unsigned* permutation)
391 for (
unsigned b = 0;
b < basis.size(); ++
b)
394 unsigned pivot = permutation[
b];
395 new_vector[
b] = current[pivot] / vbasis[pivot];
396 if (!
ws_.is_zero(new_vector[
b]))
398 current[pivot] =
ws_.zero();
399 for (
unsigned i = b+1; i <
dimension; ++i)
400 current[permutation[i]]
401 -= new_vector[b] * vbasis[permutation[i]];
416 unsigned* permutation)
418 for (
unsigned i = begin; i <
dimension; ++i)
419 if (!
ws_.is_zero(v[permutation[i]]))
434 unsigned* permutation)
436 unsigned pivot = permutation[
b];
438 if (
ws_.is_zero(ratio))
441 current[pivot] =
ws_.zero();
442 for (
unsigned i = b+1; i <
dimension; ++i)
443 current[permutation[i]]
444 =
ws_.sub(current[permutation[i]],
445 ws_.mul(ratio, vbasis[permutation[i]]));
451 unsigned* permutation)
456 v[permutation[pivot]] =
ws_.one();
458 v[permutation[
r]] =
ws_.rdiv(v[permutation[
r]], k);
465 unsigned* permutation)
467 for (
unsigned b = basis.size()-1; 0 <
b; --
b)
468 for (
unsigned c = 0; c <
b; ++c)
475 unsigned* permutation)
477 for (
unsigned b = 0;
b < basis.size(); ++
b)
497 std::vector<vector_t> basis;
507 unsigned pivot = type_t::find_pivot(
this,
init, 0, permutation);
508 if (pivot == dimension)
511 permutation[0] = pivot;
512 permutation[pivot] = 0;
516 type_t::normalisation_vector(
this, first, 0, permutation);
517 basis.push_back(first);
522 for (
unsigned nb = 0; nb < basis.size(); ++nb)
529 for (
unsigned b = 0;
b < basis.size(); ++
b)
530 type_t::reduce_vector(
this, basis[
b],
531 current, b, permutation);
534 pivot = type_t::find_pivot(
this, current, basis.size(),
536 if (pivot != dimension)
538 if (pivot != basis.size())
539 std::swap(permutation[pivot], permutation[basis.size()]);
540 type_t::normalisation_vector(
this, current,
541 basis.size(), permutation);
542 basis.push_back(current);
548 type_t::bottom_up_reduction(
this, basis, permutation);
552 std::vector<output_state_t> states(basis.size());
553 for (
unsigned b = 0;
b < basis.size(); ++
b)
554 states[
b] =
res_->new_state();
556 vector_t vect_new_basis(basis.size());
557 type_t::vector_in_new_basis(
this, basis,
init,
558 vect_new_basis, permutation);
559 for (
unsigned b = 0;
b < basis.size(); ++
b)
560 res_->set_initial(states[
b], vect_new_basis[b]);
563 for (
unsigned v = 0; v < basis.size(); ++v)
567 res_->set_final(states[v],k);
568 for (
auto mu : letter_matrix_set)
573 type_t::vector_in_new_basis(
this, basis, current,
574 vect_new_basis, permutation);
575 for (
unsigned b = 0; b < basis.size(); ++
b)
576 res_->new_transition(states[v], states[b],
577 mu.first, vect_new_basis[b]);
598 template<
typename Aut>
601 -> decltype(
copy(input))
608 template<
typename Aut>
611 -> decltype(
copy(input))
621 template <
typename Aut>
625 const auto& a = aut->as<Aut>();
matrix_set_t letter_matrix_set
static void bottom_up_reduction(Reduc *, Basis &, unsigned *)
vcsn::detail::r_impl::value_t r_weight_t
static weight_t norm(const r_weight_t &w)
Norm for real numbers; a "stable" pivot should minimize this norm.
REGISTER_DECLARE(accessible,(const automaton &) -> automaton)
std::shared_ptr< detail::automaton_base > automaton
typename context_t::weightset_t weightset_t
static weight_t norm(const q_weight_t &w)
void z_vector_in_new_basis(std::vector< vector_t > &basis, vector_t ¤t, vector_t &new_vector, unsigned *permutation)
context_t_of< automaton_t > context_t
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
const weightset_t_of< automaton_t > ws_
static void normalisation_vector(Reduc *, Vector &, unsigned, unsigned *)
state_t_of< output_automaton_t > output_state_t
typename context_t::weight_t weight_t
auto reduce(const Aut &input) -> decltype(copy(input))
static void vector_in_new_basis(Reduc *that, Basis &basis, Vector ¤t, Vector &new_vector, unsigned *permutation)
automaton make_automaton(const Aut &aut)
Build a dyn::automaton.
variadic_mul_mixin< detail::b_impl > b
void product_vector_matrix(const vector_t &v, const matrix_t &m, vector_t &res)
Computes the product of a row vector with a matrix.
typename automaton_t::element_type::automaton_nocv_t output_automaton_t
static void normalisation_vector(Reduc *that, Vector &v, unsigned pivot, unsigned *permutation)
static void reduce_vector(Reduc *that, Vector &vbasis, Vector ¤t, unsigned b, unsigned *permutation)
weight_t reduce_vector(vector_t &vbasis, vector_t ¤t, unsigned b, unsigned *permutation)
Reduce a vector w.r.t.
left_reductioner(const automaton_t &input)
static unsigned find_pivot(Reduc *that, const Vector &v, unsigned begin, unsigned *permutation)
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_t_of
AutOut copy(const AutIn &input, Pred keep_state)
A copy of input keeping only its states that are accepted by keep_state.
std::map< label_t, matrix_t > matrix_set_t
automaton reduce(const automaton &aut)
Bridge.
static weight_t norm(const z_weight_t &w)
Norm for integers.
type_t
The possible types of ratexps.
unsigned find_pivot_by_norm(const vector_t &v, unsigned begin, unsigned *permutation)
auto left_reduce(const Aut &input) -> decltype(copy(input))
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
void bottom_up_reduction(std::vector< vector_t > &basis, unsigned *permutation)
Apply reduction to vectors of the basis to maximize the number of zeros.
static unsigned find_pivot(Reduc *that, const Vector &v, unsigned begin, unsigned *permutation)
std::vector< weight_t > vector_t
static void vector_in_new_basis(Reduc *that, Basis &basis, Vector ¤t, Vector &new_vector, unsigned *permutation)
state_t_of< automaton_t > state_t
static void reduce_vector(Reduc *that, Vector &vbasis, Vector ¤t, unsigned b, unsigned *permutation)
Provide a variadic mul on top of a binary mul(), and one().
unsigned find_pivot(const vector_t &v, unsigned begin, unsigned *permutation)
Return the first (w.r.t the column permutation) non zero element as pivot.
output_automaton_t operator()()
Core algorithm This algorithm computes a basis of I.mu(w).
static void bottom_up_reduction(Reduc *that, Basis &basis, unsigned *permutation)
std::vector< std::map< std::size_t, weight_t > > matrix_t
Aut transpose(const transpose_automaton< Aut > &aut)
void vector_in_new_basis(std::vector< vector_t > &basis, vector_t ¤t, vector_t &new_vector, unsigned *permutation)
Compute the coordinate of a vector in the new basis.
label_t_of< automaton_t > label_t
static unsigned find_pivot(Reduc *that, const Vector &v, unsigned begin, unsigned *permutation)
void normalisation_vector(vector_t &v, unsigned pivot, unsigned *permutation)
Normalize the basis vector such that its pivot is equal to 1.
static z_weight_t gcd(z_weight_t x, z_weight_t y, z_weight_t &a, z_weight_t &b)
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
SharedPtr make_shared_ptr(Args &&...args)
Same as std::make_shared, but parameterized by the shared_ptr type, not the (pointed to) element_type...
void linear_representation()
Create the linear representation of the input.
void z_reduce_vector(vector_t &vbasis, vector_t ¤t, unsigned nb, unsigned *permutation)
vcsn::detail::z_impl::value_t z_weight_t
Specializations for Q and R.
weight_t scalar_product(const vector_t &v, const vector_t &w)
Computes the scalar product of two vectors.
variadic_mul_mixin< detail::r_impl > r
static unsigned find_pivot(Reduc *that, const Vector &v, unsigned begin, unsigned *permutation)