1 // ==========================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ==========================================================================
4 // Copyright (c) 2006-2018, Knut Reinert, FU Berlin
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
15 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
16 // its contributors may be used to endorse or promote products derived
17 // from this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 // DAMAGE.
30 //
31 // ==========================================================================
32 // Author: Rene Rahn <rene.rahn@fu-berlin.de>
33 // ==========================================================================
34 // The dp scout is a structure that stores the current maximal score and its
35 // host position in the underlying dp-matrix.
36 // This class can be overloaded to implement different behaviors of tracking
37 // the maximal score, e.g., for the split breakpoint computation.
38 // ==========================================================================
39 // Author: Hannes Hauswedell <hauswedell@mi.fu-berlin.de>
40 // ==========================================================================
41 // The terminator specialization of dp scout offers the possibility to have
42 // dp generation stop, if specified criteria are met.
43 // To do this, define HasTerminationCriterium_<> for your algorithm and
44 // implement a DPScoutState for your terminator specialization. In your
45 // overloaded _scoutBestScore() or _computeCell() you can call
46 // terminateScout() on your Scout to have DP-generation stop.
47 // see dp_scout_xdrop.h for an example.
48 // ==========================================================================
49
50 #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_TEST_ALIGNMENT_DP_SCOUT_H_
51 #define SEQAN_INCLUDE_SEQAN_ALIGN_TEST_ALIGNMENT_DP_SCOUT_H_
52
53 namespace seqan {
54
55 // ============================================================================
56 // Forwards
57 // ============================================================================
58
59 // ============================================================================
60 // Tags, Classes, Enums
61 // ============================================================================
62
63 // ----------------------------------------------------------------------------
64 // Class Terminator_
65 // ----------------------------------------------------------------------------
66
67 template <typename TSpec = void>
68 struct Terminator_;
69
70 // ----------------------------------------------------------------------------
71 // Class DPScoutState_
72 // ----------------------------------------------------------------------------
73
74 template <typename TSpec>
75 class DPScoutState_;
76
77 template <>
78 class DPScoutState_<Default> : public Nothing // empty member optimization
79 {};
80
81 // ----------------------------------------------------------------------------
82 // Class DPScout_
83 // ----------------------------------------------------------------------------
84
85 template <typename TDPCell, typename TSpec>
86 class DPScout_;
87
88 // The default implementation of the dp scout simply stores one maximum
89 // and its corresponding position.
90 //
91 // The state must be a Nothing and is left untouched and unused.
92 template <typename TDPCell, typename TSpec>
93 class DPScout_
94 {
95 public:
96 using TBase = DPScout_;
97 using TScoreValue = typename Value<TDPCell>::Type;
98
99 TDPCell _maxScore = TDPCell();
100 size_t _maxHostPosition = 0; // The corresponding host position within the underlying dp-matrix.
101
102 DPScout_() = default;
103
DPScout_(DPScoutState_<Default> const &)104 DPScout_(DPScoutState_<Default> const & /*state*/) {}
105 };
106
107 // Terminator_ Specialization
108 template <typename TDPCell, typename TSpec>
109 class DPScout_<TDPCell, Terminator_<TSpec> >
110 : public DPScout_<TDPCell, Default>
111 {
112 public:
113 using TBase = DPScout_<TDPCell, Default>;
114
115 DPScoutState_<Terminator_<TSpec> > * state = nullptr;
116 bool terminationCriteriumMet = false;
117
118 DPScout_() = default;
119
DPScout_(DPScoutState_<Terminator_<TSpec>> & pState)120 DPScout_(DPScoutState_<Terminator_<TSpec> > & pState) :
121 TBase(),
122 state(&pState)
123 {}
124 };
125
126 // ============================================================================
127 // Metafunctions
128 // ============================================================================
129
130 // ----------------------------------------------------------------------------
131 // Metafunction ScoutSpecForAlignmentAlgorithm_
132 // ----------------------------------------------------------------------------
133
134 // Given an alignment algorithm tag such as GlobalAlignment_ or LocalAlignment_, returns the specialization tag for the
135 // corresponding DPScout_ specialization.
136
137 template <typename TAlignmentAlgorithm, typename TScoutState>
138 struct ScoutSpecForAlignmentAlgorithm_
139 {
140 typedef If<HasTerminationCriterium_<TAlignmentAlgorithm>,
141 Terminator_<>,
142 Default> Type;
143 };
144
145 // ----------------------------------------------------------------------------
146 // Metafunction ScoutStateSpecForScout_
147 // ----------------------------------------------------------------------------
148
149 // Given an dp scout this meta-function returns the appropriate specialization for the scout state.
150
151 template <typename TScout>
152 struct ScoutStateSpecForScout_
153 {
154 typedef Default Type;
155 };
156
157 // ============================================================================
158 // Functions
159 // ============================================================================
160
161 // ----------------------------------------------------------------------------
162 // Function _scoutBestScore()
163 // ----------------------------------------------------------------------------
164
165 // Tracks the new score, if it is the new maximum.
166 template <typename TDPCell, typename TSpec, typename TTraceMatrixNavigator,
167 typename TIsLastColumn, typename TIsLastRow>
168 inline void
_scoutBestScore(DPScout_<TDPCell,TSpec> & dpScout,TDPCell const & activeCell,TTraceMatrixNavigator const & navigator,TIsLastColumn const &,TIsLastRow const &)169 _scoutBestScore(DPScout_<TDPCell, TSpec> & dpScout,
170 TDPCell const & activeCell,
171 TTraceMatrixNavigator const & navigator,
172 TIsLastColumn const & /**/,
173 TIsLastRow const & /**/)
174 {
175 if (_scoreOfCell(activeCell) > _scoreOfCell(dpScout._maxScore))
176 {
177 dpScout._maxScore = activeCell;
178 dpScout._maxHostPosition = position(navigator);
179 }
180 }
181
182 // TODO(rmaerker): Why is this needed?
183 template <typename TDPCell, typename TSpec, typename TTraceMatrixNavigator, typename TIsLastColumn>
184 inline void
_scoutBestScore(DPScout_<TDPCell,TSpec> & dpScout,TDPCell const & activeCell,TTraceMatrixNavigator const & navigator,TIsLastColumn const &)185 _scoutBestScore(DPScout_<TDPCell, TSpec> & dpScout,
186 TDPCell const & activeCell,
187 TTraceMatrixNavigator const & navigator,
188 TIsLastColumn const & /**/)
189 {
190 _scoutBestScore(dpScout, activeCell, navigator, TIsLastColumn(), False());
191 }
192
193 // TODO(rmaerker): Why is this needed?
194 template <typename TDPCell, typename TSpec, typename TTraceMatrixNavigator>
195 inline void
_scoutBestScore(DPScout_<TDPCell,TSpec> & dpScout,TDPCell const & activeCell,TTraceMatrixNavigator const & navigator)196 _scoutBestScore(DPScout_<TDPCell, TSpec> & dpScout,
197 TDPCell const & activeCell,
198 TTraceMatrixNavigator const & navigator)
199 {
200 _scoutBestScore(dpScout, activeCell, navigator, False(), False());
201 }
202
203 // ----------------------------------------------------------------------------
204 // Function maxScore()
205 // ----------------------------------------------------------------------------
206
207 // Returns the current maximal score.
208 template <typename TDPCell, typename TScoutSpec>
209 inline typename Value<TDPCell>::Type const
maxScore(DPScout_<TDPCell,TScoutSpec> const & dpScout)210 maxScore(DPScout_<TDPCell, TScoutSpec> const & dpScout)
211 {
212 return _scoreOfCell(dpScout._maxScore);
213 }
214
215 // ----------------------------------------------------------------------------
216 // Function maxHostPosition()
217 // ----------------------------------------------------------------------------
218
219 // Returns the host position that holds the current maximum score.
220 template <typename TDPCell, typename TScoutSpec>
221 inline auto
maxHostPosition(DPScout_<TDPCell,TScoutSpec> const & dpScout)222 maxHostPosition(DPScout_<TDPCell, TScoutSpec> const & dpScout)
223 {
224 return dpScout._maxHostPosition;
225 }
226
227 // ----------------------------------------------------------------------------
228 // Function _terminationCriteriumIsMet()
229 // ----------------------------------------------------------------------------
230
231 template <typename TDPCell, typename TSpec>
232 inline bool
_terminationCriteriumIsMet(DPScout_<TDPCell,Terminator_<TSpec>> const & scout)233 _terminationCriteriumIsMet(DPScout_<TDPCell, Terminator_<TSpec> > const & scout)
234 {
235 return scout.terminationCriteriumMet;
236 }
237
238 // ----------------------------------------------------------------------------
239 // Function terminateScout()
240 // ----------------------------------------------------------------------------
241
242 template <typename TDPCell, typename TSpec>
243 inline void
terminateScout(DPScout_<TDPCell,Terminator_<TSpec>> & scout)244 terminateScout(DPScout_<TDPCell, Terminator_<TSpec> > & scout)
245 {
246 scout.terminationCriteriumMet = true;
247 }
248
249 // ----------------------------------------------------------------------------
250 // Function _preInitScoutHorizontal()
251 // ----------------------------------------------------------------------------
252
253 template <typename TDPCell, typename TSpec>
254 inline void
_preInitScoutHorizontal(DPScout_<TDPCell,TSpec> const &)255 _preInitScoutHorizontal(DPScout_<TDPCell, TSpec> const & /*scout*/)
256 {
257 // no-op.
258 }
259
260 // ----------------------------------------------------------------------------
261 // Function _reachedHorizontalEndPoint()
262 // ----------------------------------------------------------------------------
263
264 template <typename TDPCell, typename TSpec, typename TIter>
265 constexpr inline bool
_reachedHorizontalEndPoint(DPScout_<TDPCell,TSpec> const &,TIter const &)266 _reachedHorizontalEndPoint(DPScout_<TDPCell, TSpec> const & /*scout*/,
267 TIter const & /*hIt*/)
268 {
269 return false;
270 }
271
272 // ----------------------------------------------------------------------------
273 // Function _preInitScoutVertical()
274 // ----------------------------------------------------------------------------
275
276 template <typename TDPCell, typename TSpec>
277 inline void
_preInitScoutVertical(DPScout_<TDPCell,TSpec> const &)278 _preInitScoutVertical(DPScout_<TDPCell, TSpec> const & /*scout*/)
279 {
280 // no-op.
281 }
282
283 // ----------------------------------------------------------------------------
284 // Function _reachedVerticalEndPoint()
285 // ----------------------------------------------------------------------------
286
287 template <typename TDPCell, typename TSpec, typename TIter>
288 constexpr inline bool
_reachedVerticalEndPoint(DPScout_<TDPCell,TSpec> const &,TIter const &)289 _reachedVerticalEndPoint(DPScout_<TDPCell, TSpec> const & /*scout*/,
290 TIter const & /*iter*/)
291 {
292 return false;
293 }
294
295 // ----------------------------------------------------------------------------
296 // Function _nextHorizontalEndPos()
297 // ----------------------------------------------------------------------------
298
299 template <typename TDPCell, typename TSpec>
300 inline void
_nextHorizontalEndPos(DPScout_<TDPCell,TSpec> const &)301 _nextHorizontalEndPos(DPScout_<TDPCell, TSpec> const & /*scout*/)
302 {
303 // no-op.
304 }
305
306 // ----------------------------------------------------------------------------
307 // Function _nextVerticalEndPos()
308 // ----------------------------------------------------------------------------
309
310 template <typename TDPCell, typename TSpec>
311 inline void
_nextVerticalEndPos(DPScout_<TDPCell,TSpec> const &)312 _nextVerticalEndPos(DPScout_<TDPCell, TSpec> const & /*scout*/)
313 {
314 // no-op.
315 }
316
317 // ----------------------------------------------------------------------------
318 // Function _incHorizontalPos()
319 // ----------------------------------------------------------------------------
320
321 template <typename TDPCell, typename TSpec>
322 inline void
_incHorizontalPos(DPScout_<TDPCell,TSpec> const &)323 _incHorizontalPos(DPScout_<TDPCell, TSpec> const & /*scout*/)
324 {
325 // no-op.
326 }
327
328 // ----------------------------------------------------------------------------
329 // Function _incVerticalPos()
330 // ----------------------------------------------------------------------------
331
332 template <typename TDPCell, typename TSpec>
333 inline void
_incVerticalPos(DPScout_<TDPCell,TSpec> const &)334 _incVerticalPos(DPScout_<TDPCell, TSpec> const & /*scout*/)
335 {
336 // no-op.
337 }
338
339 // ----------------------------------------------------------------------------
340 // Function swapStateIf()
341 // ----------------------------------------------------------------------------
342
343 template <typename TSingleMaxState, typename TPredicate>
swapStateIf(TSingleMaxState && lhs,TSingleMaxState && rhs,TPredicate && p)344 inline bool swapStateIf(TSingleMaxState && lhs, TSingleMaxState && rhs, TPredicate && p)
345 {
346 using std::swap;
347
348 if (!p(lhs.mMaxScore, rhs.mMaxScore))
349 return false;
350 swap(lhs, rhs);
351 return true;
352 }
353
354 } // namespace seqan
355
356 #endif // #ifndef SEQAN_INCLUDE_SEQAN_ALIGN_TEST_ALIGNMENT_DP_SCOUT_H_
357