/// <summary> /// Funkcja znajdująca najlepsze dopasowanie podciągów. /// </summary> /// <param name="v">pierwszy ciąg wejściowy</param> /// <param name="w">drugi ciąg wejściowy</param> /// <param name="alignment">obiekt opisujący najlepsze dopasowanie podciągów. /// Uwaga, w wersji z podciągami ustaw: /// al.VStart = indeks pierwszego elementu optymalnego podciągu v, który dopasowywaliśmy /// al.WStart = indeks pierwszego elementu optymalnego podciągu w, który dopasowywaliśmy /// al.VEnd = indeks pierwszego elementu za optymalnym podciągiem v, który dopasowywaliśmy /// al.WEnd = indeks pierwszego elementu za optymalnym podciągiem w, który dopasowywaliśmy /// </param> /// <returns>wartość najlepszego dopasowania</returns> public int FindSubsequenceAlignment(string v, string w, out Alignment alignment) { alignment = new Alignment(); int globalMax = int.MinValue; int[,] assessments = new int[w.Length + 1, v.Length + 1]; LastOp[,] operations = new LastOp[w.Length + 1, v.Length + 1]; List <char> sbv = new List <char>(); List <char> sbw = new List <char>(); for (int i = 1; i < w.Length + 1; i++) { assessments[i, 0] = i * Epsilon; operations[i, 0] = LastOp.GapV; } for (int i = 1; i < v.Length + 1; i++) { assessments[0, i] = i * Epsilon; operations[0, 1] = LastOp.GapW; } for (int i = 1; i < w.Length + 1; i++) { for (int j = 1; j < v.Length + 1; j++) { int cost = Matrix[w[i - 1], v[j - 1]]; int maxValue; if (assessments[i - 1, j] + Epsilon > assessments[i, j - 1] + Epsilon) { if (assessments[i - 1, j - 1] + cost > assessments[i - 1, j] + Epsilon) { maxValue = assessments[i - 1, j - 1] + cost; operations[i, j] = LastOp.Change; } else { maxValue = assessments[i - 1, j] + Epsilon; operations[i, j] = LastOp.GapV; } } else { if (assessments[i - 1, j - 1] + cost > assessments[i, j - 1] + Epsilon) { maxValue = assessments[i - 1, j - 1] + cost; operations[i, j] = LastOp.Change; } else { maxValue = assessments[i, j - 1] + Epsilon; operations[i, j] = LastOp.GapW; } } if (maxValue < cost) { assessments[i, j] = cost; operations[i, j] = LastOp.Skip; if (cost > globalMax) { globalMax = cost; alignment.WEnd = i; alignment.VEnd = j; } } else { assessments[i, j] = maxValue; if (maxValue > globalMax) { globalMax = maxValue; alignment.WEnd = i; alignment.VEnd = j; } } } } int iv = alignment.VEnd, iw = alignment.WEnd; bool skipDetected = false; for (; !skipDetected && iv > 0 && iw > 0;) { if (operations[iw, iv] == LastOp.Change) { sbv.Add(v[iv - 1]); sbw.Add(w[iw - 1]); iv--; iw--; } else { if (operations[iw, iv] == LastOp.GapV) { sbv.Add('-'); sbw.Add(w[iw - 1]); iw--; } else { if (operations[iw, iv] == LastOp.GapW) { sbw.Add('-'); sbv.Add(v[iv - 1]); iv--; } else { sbv.Add(v[iv - 1]); sbw.Add(w[iw - 1]); iv--; iw--; skipDetected = true; } } } } alignment.VStart = iv; alignment.WStart = iw; sbv.Reverse(); sbw.Reverse(); alignment.AlignedV = String.Concat(sbv.ToArray()); alignment.AlignedW = String.Concat(sbw.ToArray()); return(globalMax); }
/// <summary> /// Funkcja znajdująca najlepsze dopasowanie ciągów (bez uwzględniania podciągów). /// </summary> /// <param name="v">pierwszy ciąg wejściowy</param> /// <param name="w">drugi ciąg wejściowy</param> /// <param name="alignment">obiekt opisujący najlepsze dopasowanie. /// Uwaga, w wersji bez uwzględniania podciągów ustaw: /// alignment.VStart = 0; /// alignment.WStart = 0; /// alignment.VEnd = v.Length; /// alignment.WEnd = w.Length; /// </param> /// <returns>wartość najlepszego dopasowania</returns> public int FindAlignment(string v, string w, out Alignment alignment) { alignment = new Alignment(); int a = v.Length, b = w.Length; int[,] matrix = new int[v.Length + 1, w.Length + 1]; LastOp[,] action = new LastOp[v.Length + 1, w.Length + 1]; for (int i = 0; i <= a; i++) { matrix[i, 0] = i * Epsilon; action[i, 0] = LastOp.GapW; } for (int i = 0; i <= b; i++) { matrix[0, i] = i * Epsilon; action[0, i] = LastOp.GapV; } for (int i = 1; i <= a; i++) { for (int j = 1; j <= b; j++) { matrix[i, j] = Maximum( matrix[i - 1, j] + Epsilon, matrix[i, j - 1] + Epsilon, matrix[i - 1, j - 1] + Matrix[v[i - 1], w[j - 1]], out action[i, j] ); } } StringBuilder vRes = new StringBuilder(); StringBuilder wRes = new StringBuilder(); while (a > 0 || b > 0) { switch (action[a, b]) { case LastOp.GapV: vRes.Append('-'); wRes.Append(w[b - 1]); --b; break; case LastOp.GapW: vRes.Append(v[a - 1]); wRes.Append('-'); --a; break; case LastOp.Change: vRes.Append(v[a - 1]); wRes.Append(w[b - 1]); --a; --b; break; } } var alignedV = vRes.ToString().ToCharArray(); Array.Reverse(alignedV); var alignedW = wRes.ToString().ToCharArray(); Array.Reverse(alignedW); alignment.VStart = 0; alignment.WStart = 0; alignment.VEnd = v.Length; alignment.WEnd = w.Length; alignment.AlignedV = new string(alignedV); alignment.AlignedW = new string(alignedW); //----------------------------------------- //Console.WriteLine(); //Console.WriteLine("Alignment with cost: {0}", matrix[v.Length, w.Length]); //Console.WriteLine("Word v: {0}", alignment.AlignedV); //Console.WriteLine("Word w: {0}", alignment.AlignedW); //----------------------------------------- return(matrix[v.Length, w.Length]); }
/// <summary> /// Funkcja znajdująca najlepsze dopasowanie ciągów (bez uwzględniania podciągów). /// </summary> /// <param name="v">pierwszy ciąg wejściowy</param> /// <param name="w">drugi ciąg wejściowy</param> /// <param name="alignment">obiekt opisujący najlepsze dopasowanie. /// Uwaga, w wersji bez uwzględniania podciągów ustaw: /// al.VStart = 0; /// al.WStart = 0; /// al.VEnd = v.Length; /// al.WEnd = w.Length; /// </param> /// <returns>wartość najlepszego dopasowania</returns> public int FindAlignment(string v, string w, out Alignment alignment) { alignment = new Alignment(); alignment.VStart = 0; alignment.WStart = 0; alignment.VEnd = v.Length; alignment.WEnd = w.Length; int[,] assessments = new int[w.Length + 1, v.Length + 1]; LastOp[,] operations = new LastOp[w.Length + 1, v.Length + 1]; List <char> sbv = new List <char>(); List <char> sbw = new List <char>(); operations[0, 0] = LastOp.Skip; for (int i = 1; i < w.Length + 1; i++) { assessments[i, 0] = i * Epsilon; operations[i, 0] = LastOp.GapV; } for (int i = 1; i < v.Length + 1; i++) { assessments[0, i] = i * Epsilon; operations[0, 1] = LastOp.GapW; } for (int i = 1; i < w.Length + 1; i++) { for (int j = 1; j < v.Length + 1; j++) { int cost = Matrix[w[i - 1], v[j - 1]]; if (assessments[i - 1, j] + Epsilon > assessments[i, j - 1] + Epsilon) { if (assessments[i - 1, j - 1] + cost > assessments[i - 1, j] + Epsilon) { assessments[i, j] = assessments[i - 1, j - 1] + cost; operations[i, j] = LastOp.Change; } else { assessments[i, j] = assessments[i - 1, j] + Epsilon; operations[i, j] = LastOp.GapV; } } else { if (assessments[i - 1, j - 1] + cost > assessments[i, j - 1] + Epsilon) { assessments[i, j] = assessments[i - 1, j - 1] + cost; operations[i, j] = LastOp.Change; } else { assessments[i, j] = assessments[i, j - 1] + Epsilon; operations[i, j] = LastOp.GapW; } } } } int iv = v.Length, iw = w.Length; for (; iw > 0 || iv > 0;) { if (operations[iw, iv] == LastOp.Change) { sbv.Add(v[iv - 1]); sbw.Add(w[iw - 1]); iv--; iw--; } else { if (operations[iw, iv] == LastOp.GapV) { sbv.Add('-'); sbw.Add(w[iw - 1]); iw--; } else { sbw.Add('-'); sbv.Add(v[iv - 1]); iv--; } } } sbv.Reverse(); sbw.Reverse(); alignment.AlignedV = String.Concat(sbv.ToArray()); alignment.AlignedW = String.Concat(sbw.ToArray()); return(assessments[w.Length, v.Length]); }
/// <summary> /// Funkcja znajdująca najlepsze dopasowanie podciągów. /// </summary> /// <param name="v">pierwszy ciąg wejściowy</param> /// <param name="w">drugi ciąg wejściowy</param> /// <param name="alignment">obiekt opisujący najlepsze dopasowanie podciągów. /// Uwaga, w wersji z podciągami ustaw: /// alignment.VStart = indeks pierwszego elementu optymalnego podciągu v, który dopasowywaliśmy /// alignment.WStart = indeks pierwszego elementu optymalnego podciągu w, który dopasowywaliśmy /// alignment.VEnd = indeks pierwszego elementu za optymalnym podciągiem v, który dopasowywaliśmy /// alignment.WEnd = indeks pierwszego elementu za optymalnym podciągiem w, który dopasowywaliśmy /// </param> /// <returns>wartość najlepszego dopasowania</returns> public int FindSubsequenceAlignment(string v, string w, out Alignment alignment) { alignment = new Alignment(); int bestV = 0, bestW = 0, best = 0; LastOp[,] action = new LastOp[v.Length + 1, w.Length + 1]; int[,] matrix = new int[v.Length + 1, w.Length + 1]; for (int i = 0; i <= v.Length; i++) { matrix[i, 0] = 0; action[i, 0] = LastOp.Skip; } for (int j = 0; j <= w.Length; j++) { matrix[0, j] = 0; action[0, j] = LastOp.Skip; } for (int i = 1; i <= v.Length; i++) { for (int j = 1; j <= w.Length; j++) { var max = Maximum( matrix[i - 1, j] + Epsilon, matrix[i, j - 1] + Epsilon, matrix[i - 1, j - 1] + Matrix[v[i - 1], w[j - 1]], out action[i, j] ); if (max > 0) { matrix[i, j] = max; if (max > best) { best = max; bestV = i; bestW = j; } } else { action[i, j] = LastOp.Skip; matrix[i, j] = 0; } } } int a = bestV, b = bestW; StringBuilder vRes = new StringBuilder(); StringBuilder wRes = new StringBuilder(); while (action[a, b] != LastOp.Skip) { switch (action[a, b]) { case LastOp.GapV: vRes.Append('-'); wRes.Append(w[b - 1]); b--; break; case LastOp.GapW: vRes.Append(v[a - 1]); wRes.Append('-'); a--; break; case LastOp.Change: vRes.Append(v[a - 1]); wRes.Append(w[b - 1]); a--; b--; break; } } var alignedV = vRes.ToString().ToCharArray(); Array.Reverse(alignedV); var alignedW = wRes.ToString().ToCharArray(); Array.Reverse(alignedW); alignment.VStart = a; alignment.WStart = b; alignment.VEnd = bestV; alignment.WEnd = bestW; alignment.AlignedV = new string(alignedV); alignment.AlignedW = new string(alignedW); //----------------------------------------- //Console.WriteLine(); //Console.WriteLine("Alignment with cost: {0}", matrix[v.Length, w.Length]); //Console.WriteLine("Word v: {0}", alignment.AlignedV); //Console.WriteLine("Word w: {0}", alignment.AlignedW); //----------------------------------------- return(matrix[bestV, bestW]); }