source: trunk/GDE/MUSCLE/src/diaglist.cpp

Last change on this file was 10390, checked in by aboeckma, 11 years ago

added muscle sourcles amd makefile

File size: 9.0 KB
Line 
1#include "muscle.h"
2#include "diaglist.h"
3#include "pwpath.h"
4
5#define MAX(x, y)       ((x) > (y) ? (x) : (y))
6#define MIN(x, y)       ((x) < (y) ? (x) : (y))
7
8void DiagList::Add(const Diag &d)
9        {
10        if (m_uCount == MAX_DIAGS)
11                Quit("DiagList::Add, overflow %u", m_uCount);
12        m_Diags[m_uCount] = d;
13        ++m_uCount;
14        }
15
16void DiagList::Add(unsigned uStartPosA, unsigned uStartPosB, unsigned uLength)
17        {
18        Diag d;
19        d.m_uStartPosA = uStartPosA;
20        d.m_uStartPosB = uStartPosB;
21        d.m_uLength = uLength;
22        Add(d);
23        }
24
25const Diag &DiagList::Get(unsigned uIndex) const
26        {
27        if (uIndex >= m_uCount)
28                Quit("DiagList::Get(%u), count=%u", uIndex, m_uCount);
29        return m_Diags[uIndex];
30        }
31
32void DiagList::LogMe() const
33        {
34        Log("DiagList::LogMe, count=%u\n", m_uCount);
35        Log("  n  StartA  StartB  Length\n");
36        Log("---  ------  ------  ------\n");
37        for (unsigned n = 0; n < m_uCount; ++n)
38                {
39                const Diag &d = m_Diags[n];
40                Log("%3u  %6u  %6u  %6u\n",
41                  n, d.m_uStartPosA, d.m_uStartPosB, d.m_uLength);
42                }
43        }
44
45void DiagList::FromPath(const PWPath &Path)
46        {
47        Clear();
48
49        const unsigned uEdgeCount = Path.GetEdgeCount();
50        unsigned uLength = 0;
51        unsigned uStartPosA;
52        unsigned uStartPosB;
53        for (unsigned uEdgeIndex = 0; uEdgeIndex < uEdgeCount; ++uEdgeIndex)
54                {
55                const PWEdge &Edge = Path.GetEdge(uEdgeIndex);
56
57        // Typical cases
58                if (Edge.cType == 'M')
59                        {
60                        if (0 == uLength)
61                                {
62                                uStartPosA = Edge.uPrefixLengthA - 1;
63                                uStartPosB = Edge.uPrefixLengthB - 1;
64                                }
65                        ++uLength;
66                        }
67                else
68                        {
69                        if (uLength >= g_uMinDiagLength)
70                                Add(uStartPosA, uStartPosB, uLength);
71                        uLength = 0;
72                        }
73                }
74
75// Special case for last edge
76        if (uLength >= g_uMinDiagLength)
77                Add(uStartPosA, uStartPosB, uLength);
78        }
79
80bool DiagList::NonZeroIntersection(const Diag &d) const
81        {
82        for (unsigned n = 0; n < m_uCount; ++n)
83                {
84                const Diag &d2 = m_Diags[n];
85                if (DiagOverlap(d, d2) > 0)
86                        return true;
87                }
88        return false;
89        }
90
91// DialogOverlap returns the length of the overlapping
92// section of the two diagonals along the diagonals
93// themselves; in other words, the length of
94// the intersection of the two sets of cells in
95// the matrix.
96unsigned DiagOverlap(const Diag &d1, const Diag &d2)
97        {
98// Determine where the diagonals intersect the A
99// axis (extending them if required). If they
100// intersect at different points, they do not
101// overlap. Coordinates on a diagonal are
102// given by B = A + c where c is the value of
103// A at the intersection with the A axis.
104// Hence, c = B - A for any point on the diagonal.
105        int c1 = (int) d1.m_uStartPosB - (int) d1.m_uStartPosA;
106        int c2 = (int) d2.m_uStartPosB - (int) d2.m_uStartPosA;
107        if (c1 != c2)
108                return 0;
109
110        assert(DiagOverlapA(d1, d2) == DiagOverlapB(d1, d2));
111        return DiagOverlapA(d1, d2);
112        }
113
114// DialogOverlapA returns the length of the overlapping
115// section of the projection of the two diagonals onto
116// the A axis.
117unsigned DiagOverlapA(const Diag &d1, const Diag &d2)
118        {
119        unsigned uMaxStart = MAX(d1.m_uStartPosA, d2.m_uStartPosA);
120        unsigned uMinEnd = MIN(d1.m_uStartPosA + d1.m_uLength - 1,
121          d2.m_uStartPosA + d2.m_uLength - 1);
122
123        int iLength = (int) uMinEnd - (int) uMaxStart + 1;
124        if (iLength < 0)
125                return 0;
126        return (unsigned) iLength;
127        }
128
129// DialogOverlapB returns the length of the overlapping
130// section of the projection of the two diagonals onto
131// the B axis.
132unsigned DiagOverlapB(const Diag &d1, const Diag &d2)
133        {
134        unsigned uMaxStart = MAX(d1.m_uStartPosB, d2.m_uStartPosB);
135        unsigned uMinEnd = MIN(d1.m_uStartPosB + d1.m_uLength - 1,
136          d2.m_uStartPosB + d2.m_uLength - 1);
137
138        int iLength = (int) uMinEnd - (int) uMaxStart + 1;
139        if (iLength < 0)
140                return 0;
141        return (unsigned) iLength;
142        }
143
144// Returns true if the two diagonals can be on the
145// same path through the DP matrix. If DiagCompatible
146// returns false, they cannot be in the same path
147// and hence "contradict" each other.
148bool DiagCompatible(const Diag &d1, const Diag &d2)
149        {
150        if (DiagOverlap(d1, d2) > 0)
151                return true;
152        return 0 == DiagOverlapA(d1, d2) && 0 == DiagOverlapB(d1, d2);
153        }
154
155// Returns the length of the "break" between two diagonals.
156unsigned DiagBreak(const Diag &d1, const Diag &d2)
157        {
158        int c1 = (int) d1.m_uStartPosB - (int) d1.m_uStartPosA;
159        int c2 = (int) d2.m_uStartPosB - (int) d2.m_uStartPosA;
160        if (c1 != c2)
161                return 0;
162
163        int iMaxStart = MAX(d1.m_uStartPosA, d2.m_uStartPosA);
164        int iMinEnd = MIN(d1.m_uStartPosA + d1.m_uLength - 1,
165          d2.m_uStartPosA + d1.m_uLength - 1);
166        int iBreak = iMaxStart - iMinEnd - 1;
167        if (iBreak < 0)
168                return 0;
169        return (unsigned) iBreak;
170        }
171
172// Merge diagonals that are continuations of each other with
173// short breaks of up to length g_uMaxDiagBreak.
174// In a sorted list of diagonals, we only have to check
175// consecutive entries.
176void MergeDiags(DiagList &DL)
177        {
178        return;
179#if     DEBUG
180        if (!DL.IsSorted())
181                Quit("MergeDiags: !IsSorted");
182#endif
183
184// TODO: Fix this!
185// Breaks must be with no offset (no gaps)
186        const unsigned uCount = DL.GetCount();
187        if (uCount <= 1)
188                return;
189
190        DiagList NewList;
191
192        Diag MergedDiag;
193        const Diag *ptrPrev = &DL.Get(0);
194        for (unsigned i = 1; i < uCount; ++i)
195                {
196                const Diag *ptrDiag = &DL.Get(i);
197                unsigned uBreakLength = DiagBreak(*ptrPrev, *ptrDiag);
198                if (uBreakLength <= g_uMaxDiagBreak)
199                        {
200                        MergedDiag.m_uStartPosA = ptrPrev->m_uStartPosA;
201                        MergedDiag.m_uStartPosB = ptrPrev->m_uStartPosB;
202                        MergedDiag.m_uLength = ptrPrev->m_uLength + ptrDiag->m_uLength
203                          + uBreakLength;
204                        ptrPrev = &MergedDiag;
205                        }
206                else
207                        {
208                        NewList.Add(*ptrPrev);
209                        ptrPrev = ptrDiag;
210                        }
211                }
212        NewList.Add(*ptrPrev);
213        DL.Copy(NewList);
214        }
215
216void DiagList::DeleteIncompatible()
217        {
218        assert(IsSorted());
219
220        if (m_uCount < 2)
221                return;
222
223        bool *bFlagForDeletion = new bool[m_uCount];
224        for (unsigned i = 0; i < m_uCount; ++i)
225                bFlagForDeletion[i] = false;
226
227        for (unsigned i = 0; i < m_uCount; ++i)
228                {
229                const Diag &di = m_Diags[i];
230                for (unsigned j = i + 1; j < m_uCount; ++j)
231                        {
232                        const Diag &dj = m_Diags[j];
233
234                // Verify sorted correctly
235                        assert(di.m_uStartPosA <= dj.m_uStartPosA);
236
237                // If two diagonals are incompatible and
238                // one is is much longer than the other,
239                // keep the longer one.
240                        if (!DiagCompatible(di, dj))
241                                {
242                                if (di.m_uLength > dj.m_uLength*4)
243                                        bFlagForDeletion[j] = true;
244                                else if (dj.m_uLength > di.m_uLength*4)
245                                        bFlagForDeletion[i] = true;
246                                else
247                                        {
248                                        bFlagForDeletion[i] = true;
249                                        bFlagForDeletion[j] = true;
250                                        }
251                                }
252                        }
253                }
254
255        for (unsigned i = 0; i < m_uCount; ++i)
256                {
257                const Diag &di = m_Diags[i];
258                if (bFlagForDeletion[i])
259                        continue;
260
261                for (unsigned j = i + 1; j < m_uCount; ++j)
262                        {
263                        const Diag &dj = m_Diags[j];
264                        if (bFlagForDeletion[j])
265                                continue;
266
267                // Verify sorted correctly
268                        assert(di.m_uStartPosA <= dj.m_uStartPosA);
269
270                // If sort order in B different from sorted order in A,
271                // either diags are incompatible or we detected a repeat
272                // or permutation.
273                        if (di.m_uStartPosB >= dj.m_uStartPosB || !DiagCompatible(di, dj))
274                                {
275                                bFlagForDeletion[i] = true;
276                                bFlagForDeletion[j] = true;
277                                }
278                        }
279                }
280
281        unsigned uNewCount = 0;
282        Diag *NewDiags = new Diag[m_uCount];
283        for (unsigned i = 0; i < m_uCount; ++i)
284                {
285                if (bFlagForDeletion[i])
286                        continue;
287
288                const Diag &d = m_Diags[i];
289                NewDiags[uNewCount] = d;
290                ++uNewCount;
291                }
292        memcpy(m_Diags, NewDiags, uNewCount*sizeof(Diag));
293        m_uCount = uNewCount;
294        delete[] NewDiags;
295        }
296
297void DiagList::Copy(const DiagList &DL)
298        {
299        Clear();
300        unsigned uCount = DL.GetCount();
301        for (unsigned i = 0; i < uCount; ++i)
302                Add(DL.Get(i));
303        }
304
305// Check if sorted in increasing order of m_uStartPosA
306bool DiagList::IsSorted() const
307        {
308        return true;
309        unsigned uCount = GetCount();
310        for (unsigned i = 1; i < uCount; ++i)
311                if (m_Diags[i-1].m_uStartPosA > m_Diags[i].m_uStartPosA)
312                        return false;
313        return true;
314        }
315
316// Sort in increasing order of m_uStartPosA
317// Dumb bubble sort, but don't care about speed
318// because don't get long lists.
319void DiagList::Sort()
320        {
321        if (m_uCount < 2)
322                return;
323
324        bool bContinue = true;
325        while (bContinue)
326                {
327                bContinue = false;
328                for (unsigned i = 0; i < m_uCount - 1; ++i)
329                        {
330                        if (m_Diags[i].m_uStartPosA > m_Diags[i+1].m_uStartPosA)
331                                {
332                                Diag Tmp = m_Diags[i];
333                                m_Diags[i] = m_Diags[i+1];
334                                m_Diags[i+1] = Tmp;
335                                bContinue = true;
336                                }
337                        }
338                }
339        }
340
341//void TestDiag()
342//      {
343//      Diag d1;
344//      Diag d2;
345//      Diag d3;
346//
347//      d1.m_uStartPosA = 0;
348//      d1.m_uStartPosB = 1;
349//      d1.m_uLength = 32;
350//
351//      d2.m_uStartPosA = 55;
352//      d2.m_uStartPosB = 70;
353//      d2.m_uLength = 36;
354//
355//      d3.m_uStartPosA = 102;
356//      d3.m_uStartPosB = 122;
357//      d3.m_uLength = 50;
358//
359//      DiagList DL;
360//      DL.Add(d1);
361//      DL.Add(d2);
362//      DL.Add(d3);
363//
364//      Log("Before DeleteIncompatible:\n");
365//      DL.LogMe();
366//      DL.DeleteIncompatible();
367//
368//      Log("After DeleteIncompatible:\n");
369//      DL.LogMe();
370//
371//      MergeDiags(DL);
372//      Log("After Merge:\n");
373//      DL.LogMe();
374//
375//      DPRegionList RL;
376//      DiagListToDPRegionList(DL, RL, 200, 200);
377//      RL.LogMe();
378//      }
Note: See TracBrowser for help on using the repository browser.