00001
00002
00003
00004
00005
00006 #include <stdlib.h>
00007 #include "cbmrdtw.h"
00008
00009 #define WINDOW_WIDTH 2
00010
00011 typedef struct
00012 {
00013 int dist;
00014 int matchLength;
00015 } DTWtableStruct;
00016
00017 DTWtableStruct *DTWtable[WINDOW_WIDTH];
00018
00019 void newDTWtable(int height)
00020 {
00021 int i;
00022
00023 for (i = 0; i < WINDOW_WIDTH; i++)
00024 DTWtable[i] = new DTWtableStruct[height];
00025 }
00026
00027 void delDTWtable(void)
00028 {
00029 int i;
00030
00031 for (i = 0; i < WINDOW_WIDTH; i++)
00032 delete[] DTWtable[i];
00033 }
00034
00035 int dtw(int *data1, int size1, int *data2, int size2,
00036 bool fixLeft, int *pathLength, int threshold)
00037 {
00038 int i, j, k;
00039 int startj, endj;
00040 int tableColumn;
00041 int finali, finalj;
00042 int preDistance, minDistance;
00043 int preMatchLength;
00044 int parentIndex[WINDOW_WIDTH][WINDOW_WIDTH] = {{1, 0}, {0, 1}}, *pIndex;
00045 int minDistOfCol;
00046 int minDistOfCols[WINDOW_WIDTH];
00047
00048 if (size2 <= (size1 + WINDOW_WIDTH - 2) / WINDOW_WIDTH)
00049 {
00050 *pathLength = 0;
00051 return INFINITE_INT;
00052 }
00053
00054 newDTWtable(size2 + WINDOW_WIDTH);
00055
00056 for (i = 0; i < WINDOW_WIDTH; i++)
00057 for (j = 0; j < size2 + WINDOW_WIDTH; j++)
00058 DTWtable[i][j].dist = INFINITE_INT;
00059
00060
00061 if (!fixLeft)
00062 {
00063 minDistOfCol = INFINITE_INT;
00064 for (j = size2 - (size1 + WINDOW_WIDTH - 2) / WINDOW_WIDTH - 1; j >= 0; j--)
00065 {
00066 if ((DTWtable[0][j + WINDOW_WIDTH].dist = abs(data1[0] - data2[j])) < minDistOfCol)
00067 minDistOfCol = DTWtable[0][j + WINDOW_WIDTH].dist;
00068 DTWtable[0][j + WINDOW_WIDTH].matchLength = 1;
00069 }
00070 minDistOfCols[0] = minDistOfCol;
00071 }
00072 else
00073 {
00074 DTWtable[0][WINDOW_WIDTH].dist = abs(data1[0] - data2[0]);
00075 DTWtable[0][WINDOW_WIDTH].matchLength = 1;
00076 minDistOfCols[0] = DTWtable[0][WINDOW_WIDTH].dist;
00077 }
00078 for (i = 1; i < WINDOW_WIDTH; i++)
00079 minDistOfCols[i] = INFINITE_INT;
00080
00081 tableColumn = 0;
00082 startj = 1;
00083 for (i = 1; i < size1; i++)
00084 {
00085 if (++tableColumn == WINDOW_WIDTH)
00086 tableColumn = 0;
00087
00088 endj = size2 - (size1 + WINDOW_WIDTH - 2 - i) / WINDOW_WIDTH - 1;
00089 if (fixLeft)
00090 if (endj > i * WINDOW_WIDTH)
00091 endj = i * WINDOW_WIDTH;
00092
00093 pIndex = parentIndex[tableColumn];
00094 minDistOfCol = INFINITE_INT;
00095 for (j = endj; j >= startj; j--)
00096 {
00097 preDistance = DTWtable[pIndex[0]][j + WINDOW_WIDTH - 1].dist;
00098 preMatchLength = DTWtable[pIndex[0]][j + WINDOW_WIDTH - 1].matchLength;
00099 if (DTWtable[pIndex[1]][j + WINDOW_WIDTH - 1].dist < preDistance)
00100 {
00101 preDistance = DTWtable[pIndex[1]][j + WINDOW_WIDTH - 1].dist;
00102 preMatchLength = DTWtable[pIndex[1]][j + WINDOW_WIDTH - 1].matchLength;
00103 }
00104 if (DTWtable[pIndex[0]][j + WINDOW_WIDTH - 2].dist < preDistance)
00105 {
00106 preDistance = DTWtable[pIndex[0]][j + WINDOW_WIDTH - 2].dist;
00107 preMatchLength = DTWtable[pIndex[0]][j + WINDOW_WIDTH - 2].matchLength;
00108 }
00109
00110 DTWtable[tableColumn][j + WINDOW_WIDTH].dist = preDistance < INFINITE_INT? preDistance + abs(data1[i] - data2[j]) : INFINITE_INT;
00111 DTWtable[tableColumn][j + WINDOW_WIDTH].matchLength = preMatchLength + 1;
00112
00113 if (DTWtable[tableColumn][j + WINDOW_WIDTH].dist < minDistOfCol)
00114 minDistOfCol = DTWtable[tableColumn][j + WINDOW_WIDTH].dist;
00115 }
00116
00117 for (j = startj - WINDOW_WIDTH; j < startj; j++)
00118 DTWtable[tableColumn][j + WINDOW_WIDTH].dist = INFINITE_INT;
00119
00120 if (tableColumn == 0)
00121 startj++;
00122
00123 minDistOfCols[tableColumn] = minDistOfCol;
00124 for (k = 0; k < WINDOW_WIDTH; k++)
00125 if (minDistOfCols[k] < minDistOfCol)
00126 minDistOfCol = minDistOfCols[k];
00127 if (minDistOfCol > threshold)
00128 {
00129 *pathLength = 0;
00130 delDTWtable();
00131 return INFINITE_INT;
00132 }
00133 }
00134
00135 minDistance = INFINITE_INT;
00136 finali = tableColumn;
00137 k = (size1 + WINDOW_WIDTH - 2) / WINDOW_WIDTH;
00138 for (j = size2 - 1; j >= k; j--)
00139 if (DTWtable[finali][j + WINDOW_WIDTH].dist < minDistance)
00140 {
00141 minDistance = DTWtable[finali][j + WINDOW_WIDTH].dist;
00142 finalj = j + WINDOW_WIDTH;
00143 }
00144 *pathLength = DTWtable[finali][finalj].matchLength;
00145 delDTWtable();
00146 return minDistance;
00147 }
00148