4 #include <unordered_map>
83 template <
typename Weightset>
86 template <
typename Reduc,
typename Vector>
89 unsigned begin,
unsigned* permutation)
91 return that->find_pivot(v, begin, permutation);
94 template <
typename Reduc,
typename Vector>
97 Vector& current,
unsigned b,
unsigned* permutation)
99 that->reduce_vector(vbasis, current, b, permutation);
102 template <
typename Reduc,
typename Vector>
105 unsigned pivot,
unsigned* permutation)
107 that->normalisation_vector(v, pivot, permutation);
110 template <
typename Reduc,
typename Basis>
114 that->bottom_up_reduction(basis, permutation);
117 template <
typename Reduc,
typename Basis,
typename Vector>
120 Vector& current, Vector& new_vector,
121 unsigned* permutation)
123 that->vector_in_new_basis(basis, current, new_vector, permutation);
130 template <
typename Reduc,
typename Vector>
133 unsigned begin,
unsigned* permutation)
135 return that->find_pivot_by_norm(v, begin, permutation);
142 template <
typename Reduc,
typename Vector>
145 unsigned begin,
unsigned* permutation)
147 return that->find_pivot_by_norm(v, begin, permutation);
154 template <
typename Reduc,
typename Vector>
157 unsigned begin,
unsigned* permutation)
159 return that->find_pivot_by_norm(v, begin, permutation);
162 template <
typename Reduc,
typename Vector>
165 Vector& current,
unsigned b,
unsigned* permutation)
167 that->z_reduce_vector(vbasis, current, b, permutation);
170 template <
typename Reduc,
typename Vector>
174 template <
typename Reduc,
typename Basis>
178 template <
typename Reduc,
typename Basis,
typename Vector>
181 Vector& current, Vector& new_vector,
182 unsigned* permutation)
184 that->z_vector_in_new_basis(basis, current, new_vector, permutation);
188 template <Automaton Aut>
192 "reduce: requires free labelset");
203 using matrix_t = std::vector<std::map<std::size_t, weight_t> > ;
215 std::unordered_map<state_t, unsigned> state_to_index;
217 for (
auto s:
input_->states())
218 state_to_index[s] = i++;
229 final[state_to_index[
input_->src_of(t)]] =
input_->weight_of(t);
237 it->second[state_to_index[
input_->src_of(t)]]
238 [state_to_index[
input_->dst_of(t)]] =
input_->weight_of(t);
252 unsigned j = it.first;
253 res[j] =
ws_.add(res[j],
ws_.mul(v[i], it.second));
263 res =
ws_.add(res,
ws_.mul(v[i], w[i]));
290 return fabs(w)+fabs(1/w);
302 unsigned* permutation)
306 for (
unsigned i = begin; i <
dimension; ++i)
307 if (!
ws_.is_zero(v[permutation[i]])
308 && (pivot == dimension
309 ||
ws_.less(
norm(v[permutation[i]]), min)))
312 min =
norm(v[permutation[i]]);
337 res =
gcd(-x, y, a, b);
342 res =
gcd(x, -y, a, b);
346 res =
gcd(y, x, b, a);
350 res =
gcd(y, z, b, a);
354 assert(res == a * x + b * y);
366 unsigned nb,
unsigned* permutation)
368 unsigned pivot = permutation[nb];
369 if (
ws_.is_zero(current[pivot]))
377 for (
unsigned i = nb; i <
dimension; ++i)
379 weight_t tmp = current[permutation[i]];
380 current[permutation[i]] = bp*tmp - cp*vbasis[permutation[i]];
381 vbasis[permutation[i]] = a*vbasis[permutation[i]] + b*tmp;
387 unsigned* permutation)
389 for (
unsigned b = 0;
b < basis.size(); ++
b)
392 unsigned pivot = permutation[
b];
393 new_vector[
b] = current[pivot] / vbasis[pivot];
394 if (!
ws_.is_zero(new_vector[
b]))
396 current[pivot] =
ws_.zero();
397 for (
unsigned i = b+1; i <
dimension; ++i)
398 current[permutation[i]]
399 -= new_vector[b] * vbasis[permutation[i]];
414 unsigned* permutation)
416 for (
unsigned i = begin; i <
dimension; ++i)
417 if (!
ws_.is_zero(v[permutation[i]]))
432 unsigned* permutation)
434 unsigned pivot = permutation[
b];
436 if (
ws_.is_zero(ratio))
439 current[pivot] =
ws_.zero();
440 for (
unsigned i = b+1; i <
dimension; ++i)
441 current[permutation[i]]
442 =
ws_.sub(current[permutation[i]],
443 ws_.mul(ratio, vbasis[permutation[i]]));
449 unsigned* permutation)
454 v[permutation[pivot]] =
ws_.one();
456 v[permutation[
r]] =
ws_.rdivide(v[permutation[
r]], k);
463 unsigned* permutation)
465 for (
unsigned b = basis.size()-1; 0 <
b; --
b)
466 for (
unsigned c = 0; c <
b; ++c)
473 unsigned* permutation)
475 for (
unsigned b = 0;
b < basis.size(); ++
b)
495 std::vector<vector_t> basis;
505 unsigned pivot = type_t::find_pivot(
this,
init, 0, permutation);
506 if (pivot == dimension)
509 permutation[0] = pivot;
510 permutation[pivot] = 0;
514 type_t::normalisation_vector(
this, first, 0, permutation);
515 basis.push_back(first);
520 for (
unsigned nb = 0; nb < basis.size(); ++nb)
527 for (
unsigned b = 0;
b < basis.size(); ++
b)
528 type_t::reduce_vector(
this, basis[
b],
529 current, b, permutation);
532 pivot = type_t::find_pivot(
this, current, basis.size(),
534 if (pivot != dimension)
536 if (pivot != basis.size())
537 std::swap(permutation[pivot], permutation[basis.size()]);
538 type_t::normalisation_vector(
this, current,
539 basis.size(), permutation);
540 basis.push_back(current);
546 type_t::bottom_up_reduction(
this, basis, permutation);
550 std::vector<output_state_t> states(basis.size());
551 for (
unsigned b = 0;
b < basis.size(); ++
b)
552 states[
b] =
res_->new_state();
554 vector_t vect_new_basis(basis.size());
555 type_t::vector_in_new_basis(
this, basis,
init,
556 vect_new_basis, permutation);
557 for (
unsigned b = 0;
b < basis.size(); ++
b)
558 res_->set_initial(states[
b], vect_new_basis[b]);
561 for (
unsigned v = 0;
v < basis.size(); ++
v)
565 res_->set_final(states[v],k);
566 for (
auto mu : letter_matrix_set)
571 type_t::vector_in_new_basis(
this, basis, current,
572 vect_new_basis, permutation);
573 for (
unsigned b = 0; b < basis.size(); ++
b)
574 res_->new_transition(states[v], states[b],
575 mu.first, vect_new_basis[b]);
596 template <Automaton Aut>
599 -> decltype(
copy(input))
606 template <Automaton Aut>
609 -> decltype(
copy(input))
619 template <Automaton Aut>
623 const auto& a = aut->
as<Aut>();
void z_vector_in_new_basis(std::vector< vector_t > &basis, vector_t ¤t, vector_t &new_vector, unsigned *permutation)
auto transitions(const Aut &aut) -> decltype(all_transitions(aut, is_special_t< Aut >
All the transition indexes between visible states.
typename context_t::weightset_t weightset_t
static void vector_in_new_basis(Reduc *that, Basis &basis, Vector ¤t, Vector &new_vector, unsigned *permutation)
static void reduce_vector(Reduc *that, Vector &vbasis, Vector ¤t, unsigned b, unsigned *permutation)
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.
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.
weight_t scalar_product(const vector_t &v, const vector_t &w)
Computes the scalar product of two vectors.
unsigned find_pivot_by_norm(const vector_t &v, unsigned begin, unsigned *permutation)
static weight_t norm(const z_weight_t &w)
Norm for integers.
std::vector< weight_t > vector_t
auto final_transitions(const Aut &aut) -> decltype(aut->all_in(aut->post()))
Indexes of transitions from (visible) final states.
weightset_mixin< detail::r_impl > r
type_t
The possible types of expressions.
Provide a variadic mul on top of a binary mul(), and one().
weightset_mixin< detail::b_impl > b
output_automaton_t operator()()
Core algorithm This algorithm computes a basis of I.mu(w).
typename detail::label_t_of_impl< base_t< ValueSet >>::type label_t_of
typename Aut::element_type::template fresh_automaton_t< Context > fresh_automaton_t_of
Given an automaton type, the type of its copies.
typename detail::labelset_t_of_impl< base_t< ValueSet >>::type labelset_t_of
label_t_of< automaton_t > label_t
auto initial_transitions(const Aut &aut) -> decltype(aut->all_out(aut->pre()))
Indexes of transitions to (visible) initial states.
std::vector< std::map< std::size_t, weight_t > > matrix_t
std::map< label_t, matrix_t > matrix_set_t
left_reductioner(const automaton_t &input)
static void vector_in_new_basis(Reduc *that, Basis &basis, Vector ¤t, Vector &new_vector, unsigned *permutation)
static void normalisation_vector(Reduc *, Vector &, unsigned, unsigned *)
static weight_t norm(const r_weight_t &w)
Norm for real numbers; a "stable" pivot should minimize this norm.
static void reduce_vector(Reduc *that, Vector &vbasis, Vector ¤t, unsigned b, unsigned *permutation)
fresh_automaton_t_of< automaton_t > output_automaton_t
void z_reduce_vector(vector_t &vbasis, vector_t ¤t, unsigned nb, unsigned *permutation)
AutOut make_fresh_automaton(const AutIn &model)
Create an empty, mutable, automaton, based on another one.
typename detail::state_t_of_impl< base_t< ValueSet >>::type state_t_of
vcsn::detail::r_impl::value_t r_weight_t
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.
const weightset_t_of< automaton_t > ws_
static unsigned find_pivot(Reduc *that, const Vector &v, unsigned begin, unsigned *permutation)
static weight_t norm(const q_weight_t &w)
static void normalisation_vector(Reduc *that, Vector &v, unsigned pivot, unsigned *permutation)
auto left_reduce(const Aut &input) -> decltype(copy(input))
vcsn::detail::z_impl::value_t z_weight_t
Specializations for Q and R.
auto reduce(const Aut &input) -> decltype(copy(input))
state_t_of< automaton_t > state_t
void linear_representation()
Create the linear representation of the input.
weight_t reduce_vector(vector_t &vbasis, vector_t ¤t, unsigned b, unsigned *permutation)
Reduce a vector w.r.t.
typename detail::weightset_t_of_impl< base_t< ValueSet >>::type weightset_t_of
state_t_of< output_automaton_t > output_state_t
auto copy(const AutIn &input, KeepState keep_state, KeepTrans keep_trans) -> decltype(keep_state(input->null_state()), keep_trans(input->null_transition()), make_fresh_automaton< AutIn, AutOut >(input))
A copy of input keeping only its states that are accepted by keep_state, and transitions accepted by ...
automaton reduce(const automaton &aut)
Bridge.
void normalisation_vector(vector_t &v, unsigned pivot, unsigned *permutation)
Normalize the basis vector such that its pivot is equal to 1.
auto & as()
Extract wrapped typed automaton.
matrix_set_t letter_matrix_set
typename detail::context_t_of_impl< base_t< ValueSet >>::type context_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)
typename context_t::weight_t weight_t
static z_weight_t gcd(z_weight_t x, z_weight_t y, z_weight_t &a, z_weight_t &b)
context_t_of< automaton_t > context_t
Aut transpose(const transpose_automaton< Aut > &aut)
The transpose of a transpose automaton is the original automaton.
static void bottom_up_reduction(Reduc *, Basis &, unsigned *)
static void bottom_up_reduction(Reduc *that, Basis &basis, unsigned *permutation)
static unsigned find_pivot(Reduc *that, const Vector &v, unsigned begin, unsigned *permutation)
static unsigned find_pivot(Reduc *that, const Vector &v, unsigned begin, unsigned *permutation)