ʻOhana
Population structure, admixture history, and selection using learning methods.
qpas/jade.improver.hpp
1 /* -------------------------------------------------------------------------
2  Ohana
3  Copyright (c) 2015-2020 Jade Cheng (\___/)
4  Jade Cheng <info@jade-cheng.com> (='.'=)
5  ------------------------------------------------------------------------- */
6 
7 #ifndef JADE_IMPROVER_HPP__
8 #define JADE_IMPROVER_HPP__
9 
10 #include "jade.forced_grouping.hpp"
11 #include "jade.qpas.hpp"
12 #include "jade.verification.hpp"
13 
14 namespace jade
15 {
16  ///
17  /// A template for a class that improves the Q and F matrices.
18  ///
19  template <typename TValue>
20  class basic_improver
21  {
22  public:
23  /// The value type.
24  typedef TValue value_type;
25 
26  /// The matrix type.
28 
29  /// The genotype matrix type.
31 
32  /// The forced grouping type.
34 
35  /// The verification type.
37 
38  /// The QPAS type.
40 
41  ///
42  /// \return A new-and-improved F matrix.
43  ///
45  const genotype_matrix_type & g, ///< The G matrix.
46  const matrix_type & q, ///< The Q matrix.
47  const matrix_type & fa, ///< The F matrix.
48  const matrix_type & fb, ///< The 1-F matrix.
49  const matrix_type & qfa, ///< The Q*F matrix.
50  const matrix_type & qfb, ///< The Q*(1-F) matrix.
51  const matrix_type * fif, ///< The Fin-force matrix.
52  const bool frb) ///< Using frequency-bounds.
53  {
54  assert(verification_type::validate_gqf_sizes(g, q, fa));
55  assert(verification_type::validate_gqf_sizes(g, q, fb));
58  assert(nullptr == fif || !frb);
59 
60  const auto I = g.get_height();
61  const auto K = fa.get_height();
62  const auto J = fa.get_width();
63  assert(nullptr == fif || verification_type::
64  validate_fif_size(*fif, K, J));
65 
66  matrix_type f_dst (K, J);
67 
68  static const std::vector<size_t> fixed_active_set;
69 
70  matrix_type derivative_vec (K, 1);
71  matrix_type hessian_mat (K, K);
72 
73  const auto frb_delta = value_type(1.0) /
74  (value_type(2 * I) + value_type(1.0));
75 
76  for (size_t j = 0; j < J; j++)
77  {
78  const auto f_column = fa.copy_column(j);
79 
81  q,
82  fa,
83  fb,
84  qfa,
85  qfb,
86  j,
87  derivative_vec,
88  hessian_mat);
89 
90  const auto coefficients_mat = _create_coefficients_mat(K, 0);
91 
92  auto b_vec = _create_b_vec(f_column, 0);
93  if (nullptr != fif)
94  {
95  for (size_t k = 0; k < fif->get_height(); k++)
96  {
97  b_vec[k + 0] = value_type(0);
98  b_vec[k + K] = value_type(0);
99  }
100  }
101  else if (frb)
102  {
103  for (size_t k = 0; k < K; k++)
104  {
105  b_vec[k + 0] -= frb_delta;
106  b_vec[k + K] -= frb_delta;
107  }
108  }
109 
110  std::vector<size_t> active_set { 0 };
111  matrix_type delta_vec (K, 1);
112  delta_vec[0] = -b_vec[0];
113 
115  b_vec,
116  coefficients_mat,
117  hessian_mat,
118  derivative_vec,
119  fixed_active_set,
120  active_set,
121  delta_vec);
122 
123  for (size_t k = 0; k < K; k++)
124  f_dst(k, j) = f_column[k] + delta_vec[k];
125  }
126 
127  return f_dst;
128  }
129 
130  ///
131  /// \return A new-and-improved Q matrix.
132  ///
134  const genotype_matrix_type & g, ///< The G matrix.
135  const matrix_type & q, ///< The Q matrix.
136  const matrix_type & fa, ///< The F matrix.
137  const matrix_type & fb, ///< The 1-F matrix.
138  const matrix_type & qfa, ///< The Q*F matrix.
139  const matrix_type & qfb, ///< The Q*(1-F) matrix.
140  const forced_grouping_type * fg) ///< The force-grouping.
141  {
142  assert(verification_type::validate_gqf_sizes(g, q, fa));
143  assert(verification_type::validate_gqf_sizes(g, q, fb));
145  assert(verification_type::validate_f(fa));
146 
147  const auto I = q.get_height();
148  const auto K = q.get_width();
149 
150  matrix_type q_dst (I, K);
151 
152  const std::vector<size_t> fixed_active_set { K + K };
153 
154  matrix_type derivative_vec (K, 1);
155  matrix_type hessian_mat (K, K);
156 
157  for (size_t i = 0; i < I; i++)
158  {
159  const auto q_row = q.copy_row(i);
160 
162  q,
163  fa,
164  fb,
165  qfa,
166  qfb,
167  i,
168  derivative_vec,
169  hessian_mat);
170 
171  const auto coefficients_mat = _create_coefficients_mat(K, 1);
172 
173  auto b_vec = _create_b_vec(q_row, 1);
174  if (nullptr != fg)
175  {
176  for (size_t k = 0; k < K; k++)
177  {
178  b_vec[k + 0] -= fg->get_min(i, k);
179  b_vec[k + K] += fg->get_max(i, k) - value_type(1);
180  }
181  }
182 
183  std::vector<size_t> active_set { 0 };
184  matrix_type delta_vec (K, 1);
185  delta_vec[0] = -b_vec[0];
186 
188  b_vec,
189  coefficients_mat,
190  hessian_mat,
191  derivative_vec,
192  fixed_active_set,
193  active_set,
194  delta_vec);
195 
196  for (size_t k = 0; k < K; k++)
197  q_dst(i, k) = q_row[k] + delta_vec[k];
198 
199  static const auto epsilon = value_type(1.0e-6);
200  static const auto min = value_type(0.0) + epsilon;
201  static const auto max = value_type(1.0) - epsilon;
202  q_dst.clamp_row(i, min, max);
203 
204  const auto sum = q_dst.get_row_sum(i);
205  q_dst.multiply_row(i, value_type(1) / sum);
206  }
207 
208  return q_dst;
209  }
210 
211  private:
212  // --------------------------------------------------------------------
213  static matrix_type _create_b_vec(
214  const matrix_type & current_values,
215  const size_t row_padding)
216  {
217  assert(current_values.is_vector());
218 
219  const auto K = current_values.get_length();
220 
221  matrix_type b_vec (K + K + row_padding, 1);
222 
223  for (size_t k = 0; k < K; k++)
224  {
225  b_vec[k] = current_values[k];
226  b_vec[k + K] = value_type(1) - current_values[k];
227  }
228 
229  for (size_t k = K + K; k < b_vec.get_height(); k++)
230  b_vec[k] = value_type(0);
231 
232  return b_vec;
233  }
234 
235  // --------------------------------------------------------------------
236  static matrix_type _create_coefficients_mat(
237  const size_t K,
238  const size_t row_padding)
239  {
240  matrix_type c_mat (K + K + row_padding, K);
241 
242  for (size_t k = 0; k < K; k++)
243  {
244  c_mat(k, k) = value_type(-1.0);
245  c_mat(K + k, k) = value_type(+1.0);
246  }
247 
248  for (size_t r = K + K; r < c_mat.get_height(); r++)
249  for (size_t c = 0; c < c_mat.get_width(); c++)
250  c_mat(r, c) = value_type(1.0);
251 
252  return c_mat;
253  }
254  };
255 }
256 
257 #endif // JADE_IMPROVER_HPP__
jade::basic_verification
A template for a class that performs validation on various types of matrices.
Definition: jade.verification.hpp:20
jade::basic_improver::genotype_matrix_type
basic_genotype_matrix< value_type > genotype_matrix_type
The genotype matrix type.
Definition: qpas/jade.improver.hpp:30
jade::basic_forced_grouping::get_max
value_type get_max(const size_t i, const size_t k) const
Definition: cpax/jade.forced_grouping.hpp:135
jade::basic_matrix::get_width
size_t get_width() const
Definition: jade.matrix.hpp:757
jade::basic_improver::improve_f
static matrix_type improve_f(const genotype_matrix_type &g, const matrix_type &q, const matrix_type &fa, const matrix_type &fb, const matrix_type &qfa, const matrix_type &qfb, const matrix_type *fif, const bool frb)
Definition: qpas/jade.improver.hpp:44
jade::basic_genotype_matrix
A template for an abstract class implementing operations for a genotype matrix.
Definition: jade.genotype_matrix.hpp:26
jade::basic_forced_grouping::get_min
value_type get_min(const size_t i, const size_t k) const
Definition: cpax/jade.forced_grouping.hpp:148
jade::basic_improver::value_type
TValue value_type
The value type.
Definition: qpas/jade.improver.hpp:24
jade::basic_verification::validate_f
static bool validate_f(const matrix_type &f)
Validates the F matrix and throws an exception if validation fails.
Definition: jade.verification.hpp:73
jade::basic_improver::verification_type
basic_verification< value_type > verification_type
The verification type.
Definition: qpas/jade.improver.hpp:36
jade::basic_improver::improve_q
static matrix_type improve_q(const genotype_matrix_type &g, const matrix_type &q, const matrix_type &fa, const matrix_type &fb, const matrix_type &qfa, const matrix_type &qfb, const forced_grouping_type *fg)
Definition: qpas/jade.improver.hpp:133
jade::basic_matrix::get_height
size_t get_height() const
Definition: jade.matrix.hpp:603
jade::basic_verification::validate_gqf_sizes
static bool validate_gqf_sizes(const genotype_matrix_type &g, const matrix_type &q, const matrix_type &f)
Validates the sizes of the G, Q, and F matrices and throws an exception if validation fails.
Definition: jade.verification.hpp:211
jade::basic_matrix::multiply_row
void multiply_row(const size_t row, const value_type value)
Multiplies a row by a specified value.
Definition: jade.matrix.hpp:976
jade::basic_improver::forced_grouping_type
basic_forced_grouping< value_type > forced_grouping_type
The forced grouping type.
Definition: qpas/jade.improver.hpp:33
jade::basic_improver::qpas_type
basic_qpas< value_type > qpas_type
The QPAS type.
Definition: qpas/jade.improver.hpp:39
jade::basic_improver::matrix_type
basic_matrix< value_type > matrix_type
The matrix type.
Definition: qpas/jade.improver.hpp:27
jade::basic_verification::validate_q
static bool validate_q(const matrix_type &q)
Validates the Q matrix and throws an exception if validation fails.
Definition: jade.verification.hpp:225
jade::basic_genotype_matrix::get_height
virtual size_t get_height() const =0
jade::basic_matrix::get_row_sum
value_type get_row_sum(const size_t row) const
Definition: jade.matrix.hpp:716
jade::basic_qpas::loop_over_active_set
static void loop_over_active_set(const matrix_type &b_vec, const matrix_type &coefficients_mat, const matrix_type &hessian_mat, const matrix_type &derivative_vec, const std::vector< size_t > &fixed_active_set, std::vector< size_t > &active_set, matrix_type &delta_vec)
Loops over the active set and computes a delta vector and a new active set.
Definition: jade.qpas.hpp:40
jade::basic_genotype_matrix::compute_derivatives_q
virtual void compute_derivatives_q(const matrix_type &q, const matrix_type &fa, const matrix_type &fb, const matrix_type &qfa, const matrix_type &qfb, const size_t i, matrix_type &d_vec, matrix_type &h_mat) const =0
Computes the derivative vector and hessian matrix for a specified individual of the Q matrix.
jade::basic_forced_grouping
A template for a class that implements the forced grouping feature.
Definition: cpax/jade.forced_grouping.hpp:19
jade::basic_matrix::copy_column
basic_matrix copy_column(const size_t column) const
Definition: jade.matrix.hpp:230
jade::basic_matrix< value_type >
jade::basic_matrix::copy_row
basic_matrix copy_row(const size_t row) const
Definition: jade.matrix.hpp:312
jade::basic_genotype_matrix::compute_derivatives_f
virtual void compute_derivatives_f(const matrix_type &q, const matrix_type &fa, const matrix_type &fb, const matrix_type &qfa, const matrix_type &qfb, const size_t j, matrix_type &d_vec, matrix_type &h_mat) const =0
Computes the derivative vector and hessian matrix for a specified marker of the F matrix.
jade::basic_matrix::clamp_row
void clamp_row(const size_t row, const value_type min, const value_type max)
Clamps all values in a row to the specified range.
Definition: jade.matrix.hpp:178
jade::basic_qpas
A template for a class that implements the Quadratic Programming for Active Set algorithm.
Definition: jade.qpas.hpp:20