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