public void Optimize(Story story, PositionTable <double> position) { }
public PositionTable <double> Optimize(Story story, PositionTable <double> position) { int count = -1; List <double> X = new List <double>(); int[,] index = new int[story.Characters.Count, story.FrameCount]; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { index[i, frame] = -2; } } for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { if (frame > 0 && story.SessionTable[i, frame - 1] != -1 && Math.Abs(position[i, frame] - position[i, frame - 1]) < 1e-5) { index[i, frame] = count; } else { index[i, frame] = ++count; X.Add(position[i, frame]); } } } } Dictionary <Tuple <int, int>, double> Q = new Dictionary <Tuple <int, int>, double>(); for (int i = 0; i < X.Count; ++i) { Q.Add(new Tuple <int, int>(i, i), 2); } List <int> li = new List <int>(); List <int> lj = new List <int>(); List <double> lv = new List <double>(); foreach (KeyValuePair <Tuple <int, int>, double> pair in Q) { if (pair.Key.Item1 >= pair.Key.Item2 && pair.Value != 0) { li.Add(pair.Key.Item1); lj.Add(pair.Key.Item2); lv.Add((double)pair.Value); } } int[] qsubi = li.ToArray(); int[] qsubj = lj.ToArray(); double[] qval = lv.ToArray(); List <Tuple <int, int> > listInner = new List <Tuple <int, int> >(); List <Tuple <int, int> > listOuter = new List <Tuple <int, int> >(); for (int frame = 0; frame < story.FrameCount; ++frame) { List <Tuple <int, double> > l = new List <Tuple <int, double> >(); for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { l.Add(new Tuple <int, double>(i, position[i, frame])); } } l.Sort((a, b) => a.Item2.CompareTo(b.Item2)); for (int k = 0; k < l.Count - 1; ++k) { int x = l[k].Item1; int y = l[k + 1].Item1; if (story.SessionTable[x, frame] == story.SessionTable[y, frame]) { if (!listInner.Contains(new Tuple <int, int>(index[x, frame], index[y, frame]))) { listInner.Add(new Tuple <int, int>(index[x, frame], index[y, frame])); } } else { if (!listOuter.Contains(new Tuple <int, int>(index[x, frame], index[y, frame]))) { listOuter.Add(new Tuple <int, int>(index[x, frame], index[y, frame])); } } } } const double infinity = 0; int NumConstraint = listInner.Count + listOuter.Count; int NumVariable = X.Count; double[] blx = new double[NumVariable]; double[] bux = new double[NumVariable]; mosek.boundkey[] bkx = new mosek.boundkey[NumVariable]; for (int i = 0; i < NumVariable; ++i) { bkx[i] = mosek.boundkey.ra; blx[i] = -double.MaxValue; bux[i] = double.MaxValue; } bkx[0] = mosek.boundkey.fx; bkx[0] = 0; bkx[0] = 0; int[][] asub = new int[NumVariable][]; double[][] aval = new double[NumVariable][]; List <int>[] asubList = new List <int> [NumVariable]; List <double>[] avalList = new List <double> [NumVariable]; for (int i = 0; i < NumVariable; ++i) { asubList[i] = new List <int>(); avalList[i] = new List <double>(); } for (int i = 0; i < listInner.Count; ++i) { Tuple <int, int> pair = listInner[i]; int x = pair.Item1; int y = pair.Item2; asubList[x].Add(i); avalList[x].Add(-1); asubList[y].Add(i); avalList[y].Add(1); } for (int i = 0; i < listOuter.Count; ++i) { int j = i + listInner.Count; Tuple <int, int> pair = listOuter[i]; int x = pair.Item1; int y = pair.Item2; asubList[x].Add(j); avalList[x].Add(-1); asubList[y].Add(j); avalList[y].Add(1); } for (int i = 0; i < NumVariable; ++i) { asub[i] = asubList[i].ToArray(); aval[i] = avalList[i].ToArray(); } mosek.boundkey[] bkc = new mosek.boundkey[NumConstraint]; double[] blc = new double[NumConstraint]; double[] buc = new double[NumConstraint]; for (int i = 0; i < listInner.Count; ++i) { bkc[i] = mosek.boundkey.fx; blc[i] = 0; buc[i] = 0; } for (int i = listInner.Count; i < listInner.Count + listOuter.Count; ++i) { bkc[i] = mosek.boundkey.lo; //blc[i] = 84; blc[i] = _app.Status.Config.Style.OuterGap; buc[i] = 1000; } mosek.Task task = null; mosek.Env env = null; double[] xx = new double[NumVariable]; try { env = new mosek.Env(); env.set_Stream(mosek.streamtype.log, new msgclass("")); env.init(); task = new mosek.Task(env, 0, 0); task.set_Stream(mosek.streamtype.log, new msgclass("")); task.putmaxnumvar(NumVariable); task.putmaxnumcon(NumConstraint); task.append(mosek.accmode.con, NumConstraint); task.append(mosek.accmode.var, NumVariable); task.putcfix(0.0); for (int j = 0; j < NumVariable; ++j) { task.putcj(j, -2 * X[j]); task.putbound(mosek.accmode.var, j, bkx[j], blx[j], bux[j]); task.putavec(mosek.accmode.var, j, asub[j], aval[j]); } for (int i = 0; i < NumConstraint; ++i) { task.putbound(mosek.accmode.con, i, bkc[i], blc[i], buc[i]); } task.putobjsense(mosek.objsense.minimize); task.putqobj(qsubi, qsubj, qval); task.optimize(); task.solutionsummary(mosek.streamtype.msg); mosek.solsta solsta; mosek.prosta prosta; task.getsolutionstatus(mosek.soltype.itr, out prosta, out solsta); task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, 0, NumVariable, xx); switch (solsta) { case mosek.solsta.optimal: case mosek.solsta.near_optimal: Console.WriteLine("Optimal primal solution\n"); //for (int j = 0; j < NumVariable; ++j) // Console.WriteLine("x[{0}]:", xx[j]); break; case mosek.solsta.dual_infeas_cer: case mosek.solsta.prim_infeas_cer: case mosek.solsta.near_dual_infeas_cer: case mosek.solsta.near_prim_infeas_cer: Console.WriteLine("Primal or dual infeasibility.\n"); break; case mosek.solsta.unknown: Console.WriteLine("Unknown solution status.\n"); break; default: Console.WriteLine("Other solution status"); break; } } catch (mosek.Exception e) { Console.WriteLine(e.Code); Console.WriteLine(e); } finally { if (task != null) { task.Dispose(); } if (env != null) { env.Dispose(); } } PositionTable <double> result = new PositionTable <double>(story.Characters.Count, story.FrameCount); for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { result[i, frame] = xx[index[i, frame]]; } } } return(result); }
private void EnergyGrad(double[] x, ref double func, double[] grad, object obj) { Tuple <Story, PositionTable <double>, Dictionary <Tuple <int, int>, int> > tuple = obj as Tuple <Story, PositionTable <double>, Dictionary <Tuple <int, int>, int> >; Story story = tuple.Item1; PositionTable <double> position = tuple.Item2; Dictionary <Tuple <int, int>, int> dict = tuple.Item3; // calculate func func = 0; Tuple <double, double, double> tupleInnerDistance; Tuple <double, double, double> tupleOuterDistance; Tuple <double, double, double> tupleLineStraight; // calculate grad for (int frame = 0; frame < story.FrameCount; ++frame) { for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { int index = dict[new Tuple <int, int>(i, frame)]; grad[index] = 0; for (int j = 0; j < story.Characters.Count; ++j) { if (i != j && story.SessionTable[j, frame] != -1) { if (story.SessionTable[i, frame] == story.SessionTable[j, frame]) { var t = InnerEnergy(x[index], x[dict[new Tuple <int, int>(j, frame)]], 1.0, 1.0 * (Ultities.GetGroupCount(story, i, frame) - 1)); func += InnerDistanceConstraintWeight * t.Item1; grad[index] += InnerDistanceConstraintWeight * t.Item2; } else { var t = OuterEnergy(x[index], x[dict[new Tuple <int, int>(j, frame)]], 5.0); func += OutterDistanceConstraintWeight * t.Item1; grad[index] += OutterDistanceConstraintWeight * t.Item2; } } } if (LineStraightFunction == 1 && frame > 0 && frame < story.FrameCount - 1 && story.SessionTable[i, frame - 1] != -1 && story.SessionTable[i, frame + 1] != -1) { var t = StraightEnergy(x[index], x[dict[new Tuple <int, int>(i, frame - 1)]], x[dict[new Tuple <int, int>(i, frame + 1)]]); func += LineStraightWeight * t.Item1; grad[index] += LineStraightWeight * t.Item2; } else { if (frame > 0 && story.SessionTable[i, frame - 1] != -1) { var t = StraightEnergy(x[index], x[dict[new Tuple <int, int>(i, frame - 1)]]); func += LineStraightWeight * t.Item1; grad[index] += LineStraightWeight * t.Item2; } else if (frame < story.FrameCount - 1 && story.SessionTable[i, frame + 1] != -1) { var t = StraightEnergy(x[index], x[dict[new Tuple <int, int>(i, frame + 1)]]); func += LineStraightWeight * t.Item1; grad[index] += LineStraightWeight * t.Item2; } else { } } } } } }
public PositionTable <double> Solve(Story story) { int outerGap = (int)(_app.Status.Config.Style.OuterGap / _app.Status.Config.Style.DefaultInnerGap); PositionTable <int> positionTable = new PositionTable <int>(story.Characters.Count, story.TimeStamps.Length - 1); // 1.put first frame List <Tuple <int, List <int> > > list = Ultities.GetGroups(story, 0); //List<Tuple<int, List<int>>> list = Ultities.GetRandomList<Tuple<int, List<int>>>(Ultities.GetGroups(story, 0)); int yBaseline = 0; foreach (Tuple <int, List <int> > tuple in list) { foreach (int id in tuple.Item2) { positionTable[id, 0] = yBaseline; yBaseline += 1; } yBaseline += outerGap; } // 2.calculate group average for other frames for (int frame = 1; frame < story.TimeStamps.Length - 1; ++frame) { list = Ultities.GetGroups(story, frame); list.Sort((a, b) => - a.Item2.Count.CompareTo(b.Item2.Count)); List <int> occupied = new List <int>(); foreach (Tuple <int, List <int> > tuple in list) { // sort by previous position tuple.Item2.Sort((a, b) => positionTable[a, frame - 1].CompareTo(positionTable[b, frame - 1])); // calculate weighted average position int weight = 0; int value = 0; int sub = 0; bool allNew = true; foreach (int id in tuple.Item2) { if (story.SessionTable[id, frame - 1] != -1) { allNew = false; break; } } int top; if (allNew) { top = 0 - tuple.Item2.Count / 2; } else { for (int i = 0; i < tuple.Item2.Count; ++i) { int id = tuple.Item2[i]; int w = Ultities.GetHistoryLength(story, id, frame); value += w * positionTable[id, frame - 1]; weight += w; sub += w * i; } double bestCenter = (double)value / weight; top = (int)Math.Round((bestCenter * weight - sub) / weight); } // find a place to put it for (int shift = 0; true; ++shift) { int shiftedTop1 = top - shift; int shiftedTop2 = top + shift; bool available = false; int pos = 0; if (IsAvailable(occupied, shiftedTop1 - outerGap, shiftedTop1 + tuple.Item2.Count - 1 + outerGap)) { pos = shiftedTop1; available = true; } else if (IsAvailable(occupied, shiftedTop2 - outerGap, shiftedTop2 + tuple.Item2.Count - 1 + outerGap)) { pos = shiftedTop2; available = true; } if (available) { for (int i = 0; i < tuple.Item2.Count; ++i) { positionTable[tuple.Item2[i], frame] = pos + i; occupied.Add(pos + i); } break; } } } } for (int t = 0; t < 10; ++t) { // shift lines to new positions for (int frame = 1; frame < story.TimeStamps.Length - 2; ++frame) { HashSet <int> deltas = new HashSet <int>(); for (int id = 0; id < story.Characters.Count; ++id) { if (story.SessionTable[id, frame] != -1 && story.SessionTable[id, frame + 1] != -1) { int delta = positionTable[id, frame] - positionTable[id, frame + 1]; if (!deltas.Contains(delta)) { deltas.Add(delta); } } } int minCost = int.MaxValue; int minDelta = 0; foreach (int delta in deltas) { int cost = 0; for (int id = 0; id < story.Characters.Count; ++id) { if (story.SessionTable[id, frame] != -1 && story.SessionTable[id, frame + 1] != -1) { cost += Math.Abs(positionTable[id, frame + 1] + delta - positionTable[id, frame]); if (positionTable[id, frame + 1] + delta == positionTable[id, frame]) { cost -= 100; } } } if (minCost > cost) { minCost = cost; minDelta = delta; } } for (int id = 0; id < story.Characters.Count; ++id) { positionTable[id, frame + 1] += minDelta; } } for (int frame = 1; frame < story.TimeStamps.Length - 2; ++frame) { for (int id = 0; id < story.Characters.Count; ++id) { if (Ultities.GetGroupCount(story, id, frame) == 1 && Ultities.GetGroupCount(story, id, frame + 1) > 1) { bool isHead = true; int f; for (f = frame - 1; f >= 0; --f) { if (Ultities.GetGroupCount(story, id, f) > 1) { isHead = false; break; } else if (story.SessionTable[id, f] == -1) { break; } } //if (!isHead) // continue; //positionTable[id, frame] = -100; //continue; // HashSet <int> tubes = new HashSet <int>(); for (int ii = f + 1; ii <= frame; ++ii) { for (int ch = 0; ch < story.Characters.Count; ++ch) { if (ch != id && story.SessionTable[ch, ii] != -1) { if (!tubes.Contains(positionTable[ch, ii])) { tubes.Add(positionTable[ch, ii]); } } } } var occupied = tubes.ToList <int>(); int p = positionTable[id, frame + 1]; // find a place to put it for (int shift = 0; true; ++shift) { int shiftedTop1 = p - shift; int shiftedTop2 = p + shift; bool available = false; int pp = 0; if (IsAvailable(occupied, shiftedTop1 - outerGap, shiftedTop1 + outerGap)) { pp = shiftedTop1; available = true; } else if (IsAvailable(occupied, shiftedTop2 - outerGap, shiftedTop2 + outerGap)) { pp = shiftedTop2; available = true; } if (available) { for (int ii = f + 1; ii <= frame; ++ii) { //if (Math.Abs(positionTable[id, ii] - pp) > 0) { positionTable[id, ii] = pp; } } break; } } } } } // } PositionTable <double> position = positionTable.Clone <double>(); Debug.WriteLine("Before, Crossing:{0}", Crossing.Count(story, position.Clone <int>())); PositionOptimizer3 optimizer2 = new PositionOptimizer3(); position = optimizer2.Optimize(story, position, 0.4, 0.9, 0.0, 0.0); position = optimizer2.Optimize(story, position, 0.9, 0.9, 0.0, 0.0); PositionOptimizer2 optimizer = new PositionOptimizer2(); position = optimizer.Optimize(story, position, 0.4, 0.5, 0.0, 0.0); position = optimizer2.Optimize(story, position, 0.4, 0.9, 0.0, 0.0); //position = optimizer2.Optimize(story, position, 1.0, 0.1, 0.0, 0.0); //position = optimizer.Optimize(story, position, 1.0, 0.1, 0.0, 0.0); PositionOptimizer1 optimizer1 = new PositionOptimizer1(); //position = optimizer1.Optimize(story, position); int x = 4; while (x-- > 0) { //position = optimizer.Optimize(story, position, 0.6, 0.2, 0.0, 0.0); position = optimizer2.Optimize(story, position, 1.0, 0.5, 0.0, 0.0); position = optimizer1.Optimize(story, position); } // move to positive double min = 0; for (int id = 0; id < story.Characters.Count; ++id) { for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { if (story.SessionTable[id, frame] != -1 && min > position[id, frame]) { min = position[id, frame]; } } } for (int id = 0; id < story.Characters.Count; ++id) { for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { if (story.SessionTable[id, frame] != -1) { position[id, frame] -= min; position[id, frame] *= 5; } } } Debug.WriteLine("Crossing:{0}", Crossing.Count(story, position.Clone <int>())); return(position); positionTable = position.Clone <int>(); int[,] permutationTable = new int[story.Characters.Count, story.TimeStamps.Length - 1]; { for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { List <Tuple <int, int> > l = new List <Tuple <int, int> >(); for (int id = 0; id < story.Characters.Count; ++id) { if (story.SessionTable[id, frame] != -1) { l.Add(new Tuple <int, int>(id, positionTable[id, frame])); } else { l.Add(new Tuple <int, int>(id, 100000)); } } l.Sort((a, b) => a.Item2.CompareTo(b.Item2)); for (int i = 0; i < l.Count; ++i) { permutationTable[l[i].Item1, frame] = i; } } // calculate positions PositionTable <int> posY = new PositionTable <int>(story.Characters.Count, story.TimeStamps.Length - 1); List <int[]>[] intervals = new List <int[]> [story.TimeStamps.Length - 1]; List <int>[] prev = new List <int> [story.TimeStamps.Length - 1]; List <int>[] next = new List <int> [story.TimeStamps.Length - 1]; List <Tuple <int, int, int> >[] lcss = new List <Tuple <int, int, int> > [story.TimeStamps.Length - 1]; for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { // find intervals at this frame int[] t = new int[story.Characters.Count]; for (int i = 0; i < story.Characters.Count; ++i) { t[permutationTable[i, frame]] = i; } List <int> p = new List <int>(); for (int i = 0; i < t.Length; ++i) { if (story.SessionTable[t[i], frame] != -1) { p.Add(t[i]); } } intervals[frame] = new List <int[]>(); prev[frame] = new List <int>(); next[frame] = new List <int>(); lcss[frame] = new List <Tuple <int, int, int> >(); int last = -1; for (int i = 0; i < p.Count; ++i) { if (i == p.Count - 1 || story.SessionTable[p[i], frame] != story.SessionTable[p[i + 1], frame]) { intervals[frame].Add(p.GetRange(last + 1, i - last).ToArray <int>()); last = i; prev[frame].Add(-1); next[frame].Add(-1); lcss[frame].Add(new Tuple <int, int, int>(-1, -1, -1)); } } // calculate the connection with previous frame if (frame > 0) { Tuple <int, int, int>[,] lcs = new Tuple <int, int, int> [intervals[frame - 1].Count, intervals[frame].Count]; for (int i = 0; i < intervals[frame - 1].Count; ++i) { for (int j = 0; j < intervals[frame].Count; ++j) { lcs[i, j] = GetLcs(intervals[frame - 1][i], intervals[frame][j]); } } int[,] dp = new int[intervals[frame - 1].Count + 1, intervals[frame].Count + 1]; Tuple <int, int>[,] path = new Tuple <int, int> [intervals[frame - 1].Count + 1, intervals[frame].Count + 1]; for (int i = 0; i < intervals[frame - 1].Count; ++i) { for (int j = 0; j < intervals[frame].Count; ++j) { dp[i + 1, j + 1] = -1; if (dp[i + 1, j + 1] < dp[i, j] + lcs[i, j].Item3) { dp[i + 1, j + 1] = dp[i, j] + lcs[i, j].Item3; path[i + 1, j + 1] = new Tuple <int, int>(i, j); } if (dp[i + 1, j + 1] < dp[i + 1, j]) { dp[i + 1, j + 1] = dp[i + 1, j]; path[i + 1, j + 1] = new Tuple <int, int>(i + 1, j); } if (dp[i + 1, j + 1] < dp[i, j + 1]) { dp[i + 1, j + 1] = dp[i, j + 1]; path[i + 1, j + 1] = new Tuple <int, int>(i, j + 1); } } } { int i = intervals[frame - 1].Count - 1; int j = intervals[frame].Count - 1; while (i > -1 && j > -1) { if (path[i + 1, j + 1].Item1 == i && path[i + 1, j + 1].Item2 == j) { prev[frame][j] = i; next[frame - 1][i] = j; lcss[frame][j] = lcs[i, j]; } Tuple <int, int> pair = path[i + 1, j + 1]; i = pair.Item1 - 1; j = pair.Item2 - 1; } } } } int[] top = new int[story.TimeStamps.Length - 1]; List <List <Tuple <int, int> > > layers = new List <List <Tuple <int, int> > >(); while (true) { bool[] isAtTop = new bool[story.TimeStamps.Length - 1]; bool exist = false; for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { // now calculate a bool of isAtTop[frame] if (top[frame] >= intervals[frame].Count) // this frame is already empty { continue; } exist = true; bool flag = true; int current = prev[frame][top[frame]]; int currentFrame = frame - 1; while (current > -1) { if (top[currentFrame] != current) { flag = false; break; } current = prev[currentFrame][current]; --currentFrame; } current = next[frame][top[frame]]; currentFrame = frame + 1; while (current > -1) { if (top[currentFrame] != current) { flag = false; break; } current = next[currentFrame][current]; ++currentFrame; } isAtTop[frame] = flag; } if (!exist) { break; } layers.Add(new List <Tuple <int, int> >()); var layer = layers.Last <List <Tuple <int, int> > >(); for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { if (isAtTop[frame]) { layer.Add(new Tuple <int, int>(frame, top[frame])); ++top[frame]; } } } //Point[,] positions = new Point[permutation.FrameCount, permutation.CharacterCount]; //double[,] posY = new double[frameCount, characterCount]; int yBaseline1 = 0; int minY = int.MaxValue; int maxY = int.MinValue; for (int i = 0; i < layers.Count; ++i) { List <Tuple <int, int> > layer = layers[i]; int[] topY = new int[layer.Count]; int[] bottomY = new int[layer.Count]; int lastTopY = -100000; minY = int.MaxValue; maxY = int.MinValue; for (int j = 0; j < layer.Count; ++j) { int frame = layer[j].Item1; int k = layer[j].Item2; if (prev[frame][k] == -1) { topY[j] = 0; lastTopY = 0; } else { topY[j] = lastTopY - lcss[frame][k].Item2 + lcss[frame][k].Item1; lastTopY = topY[j]; } if (minY > topY[j]) { minY = topY[j]; } } for (int j = 0; j < layer.Count; ++j) { int frame = layer[j].Item1; int k = layer[j].Item2; topY[j] -= minY; bottomY[j] = topY[j] + intervals[frame][k].Length; for (int ii = 0; ii < intervals[frame][k].Length; ++ii) { int character = intervals[frame][k][ii]; posY[character, frame] = yBaseline1 + (topY[j] + ii) * (int)_app.Status.Config.Style.DefaultInnerGap; //positions[frame, character] = new Point(frame * styles.TimeScaleFactor, baseline + (topY[j] + ii) * styles.InnerDistance); if (maxY < posY[character, frame]) { maxY = (int)posY[character, frame]; } } } yBaseline1 = maxY + (int)_app.Status.Config.Style.OuterGap; } { // new added, move down the hanging lines from bottom lay to top bool[,] rearranged = new bool[story.Characters.Count, story.TimeStamps.Length - 1]; int[] topOfFrame = new int[story.TimeStamps.Length - 1]; for (int i = 0; i < topOfFrame.Length; ++i) { topOfFrame[i] = maxY; } for (int i = layers.Count - 1; i >= 0; --i) { List <Tuple <int, int> > layer = layers[i]; if (i != layers.Count - 1) // this is not the bottom layer { int minDepth = int.MaxValue; int BottomOfPiece = 0; int TopOfPieceGround = 0; List <Tuple <int, int> > stack = new List <Tuple <int, int> >(); for (int j = 0; j < layer.Count; ++j) { int frame = layer[j].Item1; int k = layer[j].Item2; int max = int.MinValue; for (int ii = 0; ii < intervals[frame][k].Length; ++ii) { int character = intervals[frame][k][ii]; if (max < posY[character, frame]) { max = posY[character, frame]; } } if (prev[frame][k] == -1) { BottomOfPiece = max; TopOfPieceGround = topOfFrame[frame]; stack.Clear(); stack.Add(new Tuple <int, int>(frame, k)); if (intervals[frame][k].Length == 1 && (frame > 0 && story.SessionTable[intervals[frame][k][0], frame - 1] == -1)) { int pos = posY[intervals[frame][k][0], frame]; int f = frame; do { ++f; }while (f < story.TimeStamps.Length - 1 && posY[intervals[frame][k][0], f] == pos); if (f != story.TimeStamps.Length - 1) { HashSet <int> tubes = new HashSet <int>(); for (int ii = frame; ii < f; ++ii) { for (int ch = 0; ch < story.Characters.Count; ++ch) { if (ch != intervals[frame][k][0]) { if (!tubes.Contains(posY[ch, ii])) { tubes.Add(posY[ch, ii]); } } } } var occupied = tubes.ToList <int>(); int p = posY[intervals[frame][k][0], f]; // find a place to put it for (int shift = 0; true; ++shift) { int shiftedTop1 = p - shift; int shiftedTop2 = p + shift; bool available = false; int pp = 0; if (IsAvailable(occupied, shiftedTop1 - (int)_app.Status.Config.Style.OuterGap, shiftedTop1 + (int)_app.Status.Config.Style.OuterGap)) { pp = shiftedTop1; available = true; } else if (IsAvailable(occupied, shiftedTop2 - (int)_app.Status.Config.Style.OuterGap, shiftedTop2 + (int)_app.Status.Config.Style.OuterGap)) { pp = shiftedTop2; available = true; } if (available) { for (int ii = frame; ii < f; ++ii) { if (Math.Abs(posY[intervals[frame][k][0], ii] - pp) > 0) { posY[intervals[frame][k][0], ii] = pp; rearranged[intervals[frame][k][0], ii] = true; } } break; } } } } } else { if (BottomOfPiece < max) { BottomOfPiece = max; } if (TopOfPieceGround > topOfFrame[frame]) { TopOfPieceGround = topOfFrame[frame]; } stack.Add(new Tuple <int, int>(frame, k)); } if (next[frame][k] == -1) { if (TopOfPieceGround - BottomOfPiece > (int)_app.Status.Config.Style.OuterGap * 2 - 1) { // a large gap detected int delta = TopOfPieceGround - BottomOfPiece - (int)_app.Status.Config.Style.OuterGap; int up = 0; int down = 0; foreach (Tuple <int, int> tuple in stack) { int f = tuple.Item1; int kk = tuple.Item2; for (int jj = 0; jj < intervals[f][kk].Length; ++jj) { int ch = intervals[f][kk][jj]; if (f < story.TimeStamps.Length - 1 - 1) { if (story.SessionTable[ch, f + 1] != -1) { if (posY[ch, f] > posY[ch, f + 1]) { ++up; } else if (posY[ch, f] < posY[ch, f + 1]) { ++down; } } } if (f > 0) { if (story.SessionTable[ch, f - 1] != -1) { if (posY[ch, f] > posY[ch, f - 1]) { ++up; } else if (posY[ch, f] < posY[ch, f - 1]) { ++down; } } } } } if (down >= up) { foreach (Tuple <int, int> tuple in stack) { int f = tuple.Item1; int kk = tuple.Item2; for (int ii = 0; ii < intervals[f][kk].Length; ++ii) { int character = intervals[f][kk][ii]; if (!rearranged[character, f]) { posY[character, f] += delta; } } } } } } } } for (int j = 0; j < layer.Count; ++j) { int frame = layer[j].Item1; int k = layer[j].Item2; for (int ii = 0; ii < intervals[frame][k].Length; ++ii) { int character = intervals[frame][k][ii]; if (topOfFrame[frame] > posY[character, frame]) { topOfFrame[frame] = posY[character, frame]; } } } } // over } return(posY.Clone <double>()); } }
public PositionTable <double> Solve(Story story) { //IPermutationCalculator permCalculator = new EfficientBarycenterCalculator(); IPermutationCalculator permCalculator = new CrossingMinimizedCalculator(); PositionTable <int> perm = permCalculator.Calculate(story); PositionTable <double> position = new PositionTable <double>(story.Characters.Count, story.TimeStamps.Length - 1); // transfer perm to position position = perm.Clone <double>(); // new potimize ShortLineConstrainedOptimizer2 opt = new ShortLineConstrainedOptimizer2(); opt.Optimize(story, position); // optimize Debug.WriteLine("Before opt, Crossing:{0}", Crossing.Count(story, position.Clone <int>())); PositionOptimizer3 optimizer2 = new PositionOptimizer3(); PositionOptimizer1 optimizer1 = new PositionOptimizer1(); PositionOptimizer2 optimizer = new PositionOptimizer2(); int x = 0; while (x-- > 0) { //position = optimizer.Optimize(story, position, 0.6, 0.2, 0.0, 0.0); position = optimizer2.Optimize(story, position, 1.0, 0.5, 0.0, 0.0); position = optimizer1.Optimize(story, position, 1.0, 0.0, 0.0, 0.0); } Debug.WriteLine("After opt, Crossing:{0}", Crossing.Count(story, position.Clone <int>())); // move to positive double min = 0; for (int id = 0; id < story.Characters.Count; ++id) { for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { if (story.SessionTable[id, frame] != -1 && min > position[id, frame]) { min = position[id, frame]; } } } for (int id = 0; id < story.Characters.Count; ++id) { for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { if (story.SessionTable[id, frame] != -1) { position[id, frame] -= min; position[id, frame] *= 1; } } } return(position); }
public PersistentOptimizer(StorylineApp app, Story story, PositionTable <int> perm, PositionTable <int> segment, double innerDist, double outerDist) { // restore data structures this._app = app; this.story = story; this.perm = perm; this.segment = segment; // initialize // index for Q at character i, timeframe j index = new int[story.Characters.Count, story.FrameCount]; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { index[i, frame] = -1; // invalid value } } // List <double> X = new List <double>(); int count = -1; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { if (frame > 0 && story.SessionTable[i, frame - 1] != -1 && segment[i, frame] == segment[i, frame - 1]) { index[i, frame] = count; } else { index[i, frame] = ++count; X.Add(perm[i, frame]); // assign perm to X } } } } int NumVariable = X.Count; xCount = X.Count; // calculate sparse objective matrix Q #region Matrix Dictionary <Tuple <int, int>, double> matrix = new Dictionary <Tuple <int, int>, double>(); for (int i = 0; i < X.Count; ++i) { matrix.Add(new Tuple <int, int>(i, i), 0.1);//simon, ctk } for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount - 1; ++frame) { int left = frame; int right = frame + 1; var leftSession = story.SessionTable[i, left]; var rightSession = story.SessionTable[i, right]; var needBreak = false; foreach (var sessionBreak in _app.Status.Config.SessionBreaks) { if (sessionBreak.session1 == leftSession && sessionBreak.session2 == rightSession && sessionBreak.frame == left) { needBreak = true; break; } } if (leftSession != -1 && rightSession != -1 && segment[i, left] != segment[i, right] && !needBreak) { Tuple <int, int> ll = new Tuple <int, int>(index[i, left], index[i, left]); Tuple <int, int> lr = new Tuple <int, int>(index[i, left], index[i, right]); Tuple <int, int> rl = new Tuple <int, int>(index[i, right], index[i, left]); Tuple <int, int> rr = new Tuple <int, int>(index[i, right], index[i, right]); if (!matrix.ContainsKey(ll)) { matrix.Add(ll, 0); } if (!matrix.ContainsKey(lr)) { matrix.Add(lr, 0); } if (!matrix.ContainsKey(rl)) { matrix.Add(rl, 0); } if (!matrix.ContainsKey(rr)) { matrix.Add(rr, 0); } matrix[ll] += 2; matrix[rr] += 2; matrix[lr] -= 2; matrix[rl] -= 2; } } } // sparse representation to matrix Q List <int> li = new List <int>(); List <int> lj = new List <int>(); List <double> lv = new List <double>(); foreach (KeyValuePair <Tuple <int, int>, double> pair in matrix) { if (pair.Key.Item1 >= pair.Key.Item2 && Math.Abs(pair.Value) > 0.000001) { li.Add(pair.Key.Item1); lj.Add(pair.Key.Item2); lv.Add(pair.Value); } } // input must be array instead of list int[] qsubi = li.ToArray(); int[] qsubj = lj.ToArray(); double[] qval = lv.ToArray(); #endregion // calculate inner and outer constraints #region Constraints // constraint { <index of k, index of k+1>: bundle} Dictionary <Tuple <int, int>, int> constraints = new Dictionary <Tuple <int, int>, int>(); List <int>[] asubList = new List <int> [NumVariable]; List <double>[] avalList = new List <double> [NumVariable]; for (int i = 0; i < NumVariable; ++i) { asubList[i] = new List <int>(); avalList[i] = new List <double>(); } List <mosek.boundkey> bkcList = new List <boundkey>(); List <double> blcList = new List <double>(); List <double> bucList = new List <double>(); var sessionInnerGaps = _app.Status.Config.sessionInnerGaps; var sessionOuterGaps = _app.Status.Config.sessionOuterGaps; // for each time frame int constraintCounter = 0; for (int frame = 0; frame < story.FrameCount; ++frame) { // charaters at timeframe List <Tuple <int, int> > l = new List <Tuple <int, int> >(); for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { l.Add(new Tuple <int, int>(i, perm[i, frame])); } } // get character order in current frame // apply result in location tree sort l.Sort((a, b) => a.Item2.CompareTo(b.Item2)); for (int k = 0; k < l.Count - 1; ++k) { int x = l[k].Item1; int y = l[k + 1].Item1; // inner constraints // x is upper character var indexX = index[x, frame]; // y is lower character var indexY = index[y, frame]; var sessionX = story.SessionTable[x, frame]; var sessionY = story.SessionTable[y, frame]; if (sessionX == sessionY) { // lower character index and higher character index Tuple <int, int> tuple = new Tuple <int, int>(indexX, indexY); if (constraints.ContainsKey(tuple)) { var i = constraints[tuple]; Debug.Assert(i >= 0); // change default gaps with respect to sessionInnerGaps buildInnerGapConstraints(sessionInnerGaps, sessionX, blcList, i, bucList); } else { int i = constraintCounter++; // type ra for range, fx for fixed bkcList.Add(mosek.boundkey.ra); // add contraint of innergap +- 2 // lower blcList.Add(Math.Max(innerDist - 2, 2)); // upper bucList.Add(innerDist + 2); buildInnerGapConstraints(sessionInnerGaps, sessionX, blcList, i, bucList); // Row index of non - zeros in column i // sparse array for i-th constraint asubList[indexX].Add(i); // Non - zero Values of column i. avalList[indexX].Add(-1); asubList[indexY].Add(i); avalList[indexY].Add(1); // positive for inner gap // store the index for further modification // assigned in sessionInnerGaps constraints.Add(tuple, i); } } else { Tuple <int, int> tuple = new Tuple <int, int>(indexX, indexY); if (constraints.ContainsKey(tuple)) { var j = constraints[tuple]; Debug.Assert(j <= 0); j *= -1; // change default gaps with respect to sessionOuterGaps buildOuterGapConstraints(sessionOuterGaps, sessionX, sessionY, blcList, j, bucList, bkcList); } else { int j = constraintCounter++; // default setting bkcList.Add(mosek.boundkey.lo); blcList.Add(outerDist); bucList.Add(1000); buildOuterGapConstraints(sessionOuterGaps, sessionX, sessionY, blcList, j, bucList, bkcList); asubList[indexX].Add(j); avalList[indexX].Add(-1); asubList[indexY].Add(j); avalList[indexY].Add(1); // negative for outer gap // store the index for further modification // assigned in sessionInnerGaps constraints.Add(tuple, -j); } } } } foreach (KeyValuePair <Tuple <int, int>, int> pair in constraints) { if (pair.Value >= 0) { innerList.Add(pair.Key); } else { outerList.Add(pair.Key); } } int NumConstraint = innerList.Count + outerList.Count; // to array int[][] asub = new int[NumVariable][]; double[][] aval = new double[NumVariable][]; for (int i = 0; i < NumVariable; ++i) { asub[i] = asubList[i].ToArray(); aval[i] = avalList[i].ToArray(); } mosek.boundkey[] bkc = bkcList.ToArray(); double[] blc = blcList.ToArray(); double[] buc = bucList.ToArray(); Debug.Assert(constraintCounter == NumConstraint); #endregion // calculate variable bound double[] blx = new double[NumVariable]; double[] bux = new double[NumVariable]; mosek.boundkey[] bkx = new mosek.boundkey[NumVariable]; for (int i = 0; i < NumVariable; ++i) { bkx[i] = mosek.boundkey.ra; blx[i] = -12000; bux[i] = 12000; } // addCharacterYConstraints in a +- 10 range foreach (var yConstraint in _app.Status.Config.CharacterYConstraints) { if (yConstraint.frame < 0 || yConstraint.frame > story.FrameCount) { continue; } var i = index[yConstraint.characterId, yConstraint.frame]; if (i != -1) { blx[i] = yConstraint.lowerY; bux[i] = yConstraint.upperY; } } // setup mosek #region Mosek try { env = new mosek.Env(); env.init(); task = new mosek.Task(env, 0, 0); task.putmaxnumvar(NumVariable); task.putmaxnumcon(NumConstraint); task.append(mosek.accmode.con, NumConstraint); task.append(mosek.accmode.var, NumVariable); task.putcfix(0.0); for (int j = 0; j < NumVariable; ++j) { task.putcj(j, 0); task.putbound(mosek.accmode.var, j, bkx[j], blx[j], bux[j]); task.putavec(mosek.accmode.var, j, asub[j], aval[j]); } for (int i = 0; i < NumConstraint; ++i) { task.putbound(mosek.accmode.con, i, bkc[i], blc[i], buc[i]); } task.putobjsense(mosek.objsense.minimize); task.putqobj(qsubi, qsubj, qval); } catch (mosek.Exception e) { Console.WriteLine(e.Code); Console.WriteLine(e); } #endregion }
private int Comp(Tuple <double, List <int>, int> a, Tuple <double, List <int>, int> b, PositionTable <int> perm, int frame, Dictionary <int, int> sublocation) { //return a.Item1.CompareTo(b.Item1); Debug.Assert(a.Item2[0] != b.Item2[0]); // if both location, fit location requirement first if (a.Item3 != -1 && b.Item3 != -1) { Debug.Assert(a.Item3 != b.Item3); return(sublocation[a.Item3].CompareTo(sublocation[b.Item3])); } // compare barycenter if both have if (a.Item1 != -1 && b.Item1 != -1 && a.Item1 != b.Item1) { Debug.Assert(a.Item1 != b.Item1); return(a.Item1.CompareTo(b.Item1)); } // if either one hasn't, try to compare current frame position if (perm[a.Item2[0], frame] != -1 && perm[b.Item2[0], frame] != -1) { Debug.Assert(perm[a.Item2[0], frame] != perm[b.Item2[0], frame]); return(perm[a.Item2[0], frame].CompareTo(perm[b.Item2[0], frame])); } return(a.Item2[0].CompareTo(b.Item2[0])); }
private void initTables() { _oc = new OrderCache(_app); _oc.OnOrder += _oc_OnOrder; _oc.Start(); state = OrderState.ConnectionPending; PST = new PositionTable(_app); PST.WantData(PST.TqlForPositions(), true, false); PST.OnPosition += PST_OnPosition; PST.Start(); XPAT = new XPermsAccountsTable(_app); XPAT.OnXPermsAccounts += XPAT_OnXPermsAccounts; XPAT.WantData(XPAT.TqlForXPermsAccounts(), true, false); XPAT.Start(); TBL = new LiveQuoteTable(_app); TBL.OnData += TBL_OnData; _bw.RunWorkerAsync(); _conn = true; }
private Tuple <double, List <int> > DfsLocationSubtree(Story story, Dictionary <int, List <int> >[] linesInSessions, Dictionary <int, List <int> >[] sessionsInLocations, PositionTable <int> perm, LocationNode node, int frame, int reference) { List <Tuple <double, List <int>, int> > list = new List <Tuple <double, List <int>, int> >(); Dictionary <int, int> sublocation = new Dictionary <int, int>(); //List<double> bclist = new List<double>(); foreach (LocationNode childNode in node.Children) { Tuple <double, List <int> > subTuple = DfsLocationSubtree(story, linesInSessions, sessionsInLocations, perm, childNode, frame, reference); // 每一个结点的排序结果,<barycenterVal, sortedList, locationId> Tuple <double, List <int>, int> tuple = new Tuple <double, List <int>, int>(subTuple.Item1, subTuple.Item2, childNode.Id); if (tuple.Item2.Count > 0) { list.Add(tuple); //bclist.Add(tuple.Item1); sublocation.Add(childNode.Id, sublocation.Count); } } //bclist.Sort(); //for (int i = 0; i < list.Count; ++i) //{ // list[i] = new Tuple<double, List<int>, int>(bclist[i], list[i].Item2, list[i].Item3); //} if (sessionsInLocations[frame].ContainsKey(node.Id)) { foreach (int sessionId in sessionsInLocations[frame][node.Id]) { Tuple <double, List <int> > sessionTuple = DfsSessionSubtree(story, linesInSessions, perm, sessionId, frame, reference); list.Add(new Tuple <double, List <int>, int>(sessionTuple.Item1, sessionTuple.Item2, -1)); } } if (reference == -1) { list.Sort((a, b) => { if (a.Item3 != -1 && b.Item3 != -1) { return(sublocation[a.Item3].CompareTo(sublocation[b.Item3])); } return(a.Item2[0].CompareTo(b.Item2[0])); }); } else { StableSort(list, perm, frame, sublocation); #region conment #endregion } List <int> lineList = new List <int>(); foreach (Tuple <double, List <int>, int> tuple in list) { lineList.AddRange(tuple.Item2); } Tuple <double, List <int> > result; if (reference != -1) { result = new Tuple <double, List <int> >(GetBarycenter(perm, lineList, reference), lineList); } else { result = new Tuple <double, List <int> >(-1, lineList); } return(result); }
//static Random rand = new Random(DateTime.Now.Millisecond); public PositionTable <int> Calculate(Story story) { PositionTable <int> perm = new PositionTable <int>(story.Characters.Count, story.FrameCount); for (int i = 0; i < story.Characters.Count; ++i) { for (int j = 0; j < story.FrameCount; ++j) { perm[i, j] = -1; } } // calculate lines in sessions dictionary to speed up the calculation Dictionary <int, List <int> >[] linesInSessions = new Dictionary <int, List <int> > [story.FrameCount]; Dictionary <int, List <int> >[] sessionsInLocations = new Dictionary <int, List <int> > [story.FrameCount]; for (int frame = 0; frame < story.FrameCount; ++frame) { linesInSessions[frame] = new Dictionary <int, List <int> >(); sessionsInLocations[frame] = new Dictionary <int, List <int> >(); for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { int sessionId = story.SessionTable[i, frame]; if (!linesInSessions[frame].ContainsKey(sessionId)) { linesInSessions[frame].Add(sessionId, new List <int>()); int locationId = story.GetLocationId(sessionId); if (!sessionsInLocations[frame].ContainsKey(locationId)) { sessionsInLocations[frame].Add(locationId, new List <int>()); } sessionsInLocations[frame][locationId].Add(sessionId); } linesInSessions[frame][sessionId].Add(i); } } } CalculateFrame(story, linesInSessions, sessionsInLocations, perm, 0, -1); for (int i = 0; i < 40; ++i) { for (int frame = 1; frame < story.FrameCount; ++frame) { CalculateFrame(story, linesInSessions, sessionsInLocations, perm, frame, frame - 1); } for (int frame = story.FrameCount - 2; frame >= 0; --frame) { CalculateFrame(story, linesInSessions, sessionsInLocations, perm, frame, frame + 1); } } var permBackup = perm; perm = new PositionTable <int>(story.Characters.Count, story.FrameCount); for (int i = 0; i < story.Characters.Count; ++i) { for (int j = 0; j < story.FrameCount; ++j) { perm[i, j] = -1; } } CalculateFrame(story, linesInSessions, sessionsInLocations, perm, story.FrameCount - 1, story.FrameCount - 2); for (int i = 0; i < 40; ++i) { for (int frame = story.FrameCount - 2; frame >= 0; --frame) { CalculateFrame(story, linesInSessions, sessionsInLocations, perm, frame, frame + 1); } for (int frame = 1; frame < story.FrameCount; ++frame) { CalculateFrame(story, linesInSessions, sessionsInLocations, perm, frame, frame - 1); } } int backwardCrossing = Crossing.Count(story, perm); int forwardCrossing = Crossing.Count(story, permBackup); //Console.WriteLine("Forward:{0},Backward:{1}", forwardCrossing, backwardCrossing); if (forwardCrossing < backwardCrossing) { return(permBackup); } else { return(perm); } }
// private void CalculateFrame(Story story, Dictionary <int, List <int> >[] linesInSessions, Dictionary <int, List <int> >[] sessionsInLocations, PositionTable <int> perm, int frame, int reference) { Tuple <double, List <int> > tuple = DfsLocationSubtree(story, linesInSessions, sessionsInLocations, perm, story.LocationRoot, frame, reference); List <int> lineList = tuple.Item2; for (int i = 0; i < lineList.Count; ++i) { int x = lineList[i]; perm[x, frame] = i; } }
public PositionTable <double> Solve(Story story) { int frameCount = story.TimeStamps.Length - 1; int characterCount = story.Characters.Count; int[] orderedSequence = new int[characterCount]; for (int i = 0; i < characterCount; ++i) { orderedSequence[i] = i; } int[] permutation = Ultities.GetFeasiblePermutation(story, 0); PositionTable <int> permutationTable = new PositionTable <int>(characterCount, frameCount); for (int i = 0; i < characterCount; ++i) { for (int j = 0; j < frameCount; ++j) { permutationTable[i, j] = -1; } } for (int id = 0; id < characterCount; ++id) { if (story.SessionTable[id, 0] != -1) { permutationTable[id, 0] = permutation[id]; } } permutationTable = (new EfficientBarycenterCalculator()).Calculate(story); for (int xx = 0; xx < 10; ++xx) { // forward for (int frame = 1; frame < frameCount; ++frame) { Dictionary <int, List <int> > dict = new Dictionary <int, List <int> >(); for (int id = 0; id < characterCount; ++id) { if (story.SessionTable[id, frame] != -1) { if (!dict.ContainsKey(story.SessionTable[id, frame])) { dict.Add(story.SessionTable[id, frame], new List <int>()); } dict[story.SessionTable[id, frame]].Add(id); } } List <Tuple <int, double> > list = new List <Tuple <int, double> >(); foreach (KeyValuePair <int, List <int> > pair in dict) { int sum = 0; int count = 0; int sum_cur = 0; foreach (int x in pair.Value) { if (story.SessionTable[x, frame - 1] != -1) { sum += permutationTable[x, frame - 1]; ++count; } else { } sum_cur += permutationTable[x, frame]; } double average = (double)sum_cur / pair.Value.Count; if (count > 0) { average = (double)sum / count; } list.Add(new Tuple <int, double>(pair.Key, average)); } //list = Ultities.GetRandomList<Tuple<int, double>>(list); list.Sort((a, b) => a.Item2.CompareTo(b.Item2)); int baseline = 0; foreach (Tuple <int, double> tuple in list) { int group = tuple.Item1; List <int> items = dict[group]; //items = Ultities.GetRandomList<int>(items); items.Sort((a, b) => permutationTable[a, frame - 1].CompareTo(permutationTable[b, frame - 1])); foreach (int x in items) { permutationTable[x, frame] = baseline++; } } } Debug.WriteLine("Forward:{0}", Crossing.Count(story, permutationTable)); // backward for (int frame = frameCount - 2; frame >= 0; --frame) { Dictionary <int, List <int> > dict = new Dictionary <int, List <int> >(); for (int id = 0; id < characterCount; ++id) { if (story.SessionTable[id, frame] != -1) { if (!dict.ContainsKey(story.SessionTable[id, frame])) { dict.Add(story.SessionTable[id, frame], new List <int>()); } dict[story.SessionTable[id, frame]].Add(id); } } List <Tuple <int, double> > list = new List <Tuple <int, double> >(); foreach (KeyValuePair <int, List <int> > pair in dict) { int sum = 0; int count = 0; int sum_cur = 0; foreach (int x in pair.Value) { if (story.SessionTable[x, frame + 1] != -1) { sum += permutationTable[x, frame + 1]; ++count; } else { } sum_cur += permutationTable[x, frame]; } double average = (double)sum_cur / pair.Value.Count; if (count > 0) { average = (double)sum / count; } list.Add(new Tuple <int, double>(pair.Key, average)); } //list = Ultities.GetRandomList<Tuple<int, double>>(list); list.Sort((a, b) => a.Item2.CompareTo(b.Item2)); int baseline = 0; foreach (Tuple <int, double> tuple in list) { int group = tuple.Item1; List <int> items = dict[group]; //items = Ultities.GetRandomList<int>(items); items.Sort((a, b) => permutationTable[a, frame + 1].CompareTo(permutationTable[b, frame + 1])); foreach (int x in items) { permutationTable[x, frame] = baseline++; } } } Debug.WriteLine("Backward:{0}", Crossing.Count(story, permutationTable)); } for (int xx = 0; xx < 10; ++xx) { for (int frame = 0; frame < frameCount; ++frame) { Dictionary <int, List <int> > dict = new Dictionary <int, List <int> >(); for (int id = 0; id < characterCount; ++id) { if (story.SessionTable[id, frame] != -1) { if (!dict.ContainsKey(story.SessionTable[id, frame])) { dict.Add(story.SessionTable[id, frame], new List <int>()); } dict[story.SessionTable[id, frame]].Add(id); } } List <Tuple <int, double> > list = new List <Tuple <int, double> >(); foreach (KeyValuePair <int, List <int> > pair in dict) { int sum = 0; int count = 0; int sum_cur = 0; foreach (int x in pair.Value) { if (frame > 0 && story.SessionTable[x, frame - 1] != -1) { sum += permutationTable[x, frame - 1]; ++count; } if (frame < frameCount - 1 && story.SessionTable[x, frame + 1] != -1) { sum += permutationTable[x, frame + 1]; ++count; } sum_cur += permutationTable[x, frame]; } double average = (double)sum_cur / pair.Value.Count; if (count > 0) { average = (double)sum / count; } list.Add(new Tuple <int, double>(pair.Key, average)); } //list = Ultities.GetRandomList<Tuple<int, double>>(list); list.Sort((a, b) => a.Item2.CompareTo(b.Item2)); int baseline = 0; foreach (Tuple <int, double> tuple in list) { int group = tuple.Item1; List <int> items = dict[group]; //items = Ultities.GetRandomList<int>(items); //items.Sort((a, b) => permutationTable[a, frame].CompareTo(permutationTable[b, frame])); if (frame == 0) { items.Sort((a, b) => permutationTable[a, frame + 1].CompareTo(permutationTable[b, frame + 1])); } else { items.Sort((a, b) => permutationTable[a, frame - 1].CompareTo(permutationTable[b, frame - 1])); } foreach (int x in items) { permutationTable[x, frame] = baseline++; } } } // backward continue; for (int frame = frameCount - 1; frame >= 0; --frame) { Dictionary <int, List <int> > dict = new Dictionary <int, List <int> >(); for (int id = 0; id < characterCount; ++id) { if (story.SessionTable[id, frame] != -1) { if (!dict.ContainsKey(story.SessionTable[id, frame])) { dict.Add(story.SessionTable[id, frame], new List <int>()); } dict[story.SessionTable[id, frame]].Add(id); } } List <Tuple <int, double> > list = new List <Tuple <int, double> >(); foreach (KeyValuePair <int, List <int> > pair in dict) { int sum = 0; int count = 0; int sum_cur = 0; foreach (int x in pair.Value) { if (frame > 0 && story.SessionTable[x, frame - 1] != -1) { sum += permutationTable[x, frame - 1]; ++count; } if (frame < frameCount - 1 && story.SessionTable[x, frame + 1] != -1) { sum += permutationTable[x, frame + 1]; ++count; } sum_cur += permutationTable[x, frame]; } double average = (double)sum_cur / pair.Value.Count; if (count > 0) { average = (double)sum / count; } list.Add(new Tuple <int, double>(pair.Key, average)); } //list = Ultities.GetRandomList<Tuple<int, double>>(list); list.Sort((a, b) => a.Item2.CompareTo(b.Item2)); int baseline = 0; foreach (Tuple <int, double> tuple in list) { int group = tuple.Item1; List <int> items = dict[group]; //items = Ultities.GetRandomList<int>(items); //items.Sort((a, b) => permutationTable[a, frame].CompareTo(permutationTable[b, frame])); if (frame == 0) { items.Sort((a, b) => permutationTable[a, frame + 1].CompareTo(permutationTable[b, frame + 1])); } else { items.Sort((a, b) => permutationTable[a, frame - 1].CompareTo(permutationTable[b, frame - 1])); } foreach (int x in items) { permutationTable[x, frame] = baseline++; } } } } //PositionTable<int> permutationTable = (new EfficientBarycenterCalculator()).Calculate(story); permutationTable = (new EfficientBarycenterCalculator()).Calculate(story); //permutationTable = (new CrossingMinimizedCalculator()).Calculate(story); for (int frame = 0; frame < frameCount; ++frame) { int max = -1; for (int id = 0; id < characterCount; ++id) { if (permutationTable[id, frame] > max) { max = permutationTable[id, frame]; } } for (int id = 0; id < characterCount; ++id) { if (permutationTable[id, frame] == -1) { permutationTable[id, frame] = ++max; } } } Debug.WriteLine("Crossing:{0}", Crossing.Count(story, permutationTable)); //PositionTable<int> ans = permutationTable.Clone<int>(); //for (int frame = 0; frame < frameCount; ++frame) //{ // for (int i = 0; i < story.Characters.Count; ++i) // { // ans[i, frame] *= 5; // } //} //return ans; { // calculate positions PositionTable <int> posY = new PositionTable <int>(characterCount, frameCount); List <int[]>[] intervals = new List <int[]> [frameCount]; List <int>[] prev = new List <int> [frameCount]; List <int>[] next = new List <int> [frameCount]; List <Tuple <int, int, int> >[] lcss = new List <Tuple <int, int, int> > [frameCount]; for (int frame = 0; frame < frameCount; ++frame) { // find intervals at this frame int[] t = new int[characterCount]; for (int i = 0; i < characterCount; ++i) { t[permutationTable[i, frame]] = i; } List <int> p = new List <int>(); for (int i = 0; i < t.Length; ++i) { if (story.SessionTable[t[i], frame] != -1) { p.Add(t[i]); } } intervals[frame] = new List <int[]>(); prev[frame] = new List <int>(); next[frame] = new List <int>(); lcss[frame] = new List <Tuple <int, int, int> >(); int last = -1; for (int i = 0; i < p.Count; ++i) { if (i == p.Count - 1 || story.SessionTable[p[i], frame] != story.SessionTable[p[i + 1], frame]) { intervals[frame].Add(p.GetRange(last + 1, i - last).ToArray <int>()); last = i; prev[frame].Add(-1); next[frame].Add(-1); lcss[frame].Add(new Tuple <int, int, int>(-1, -1, -1)); } } // calculate the connection with previous frame if (frame > 0) { Tuple <int, int, int>[,] lcs = new Tuple <int, int, int> [intervals[frame - 1].Count, intervals[frame].Count]; for (int i = 0; i < intervals[frame - 1].Count; ++i) { for (int j = 0; j < intervals[frame].Count; ++j) { lcs[i, j] = GetLcs(intervals[frame - 1][i], intervals[frame][j]); } } int[,] dp = new int[intervals[frame - 1].Count + 1, intervals[frame].Count + 1]; Tuple <int, int>[,] path = new Tuple <int, int> [intervals[frame - 1].Count + 1, intervals[frame].Count + 1]; for (int i = 0; i < intervals[frame - 1].Count; ++i) { for (int j = 0; j < intervals[frame].Count; ++j) { dp[i + 1, j + 1] = -1; if (dp[i + 1, j + 1] < dp[i, j] + lcs[i, j].Item3) { dp[i + 1, j + 1] = dp[i, j] + lcs[i, j].Item3; path[i + 1, j + 1] = new Tuple <int, int>(i, j); } if (dp[i + 1, j + 1] < dp[i + 1, j]) { dp[i + 1, j + 1] = dp[i + 1, j]; path[i + 1, j + 1] = new Tuple <int, int>(i + 1, j); } if (dp[i + 1, j + 1] < dp[i, j + 1]) { dp[i + 1, j + 1] = dp[i, j + 1]; path[i + 1, j + 1] = new Tuple <int, int>(i, j + 1); } } } { int i = intervals[frame - 1].Count - 1; int j = intervals[frame].Count - 1; while (i > -1 && j > -1) { if (path[i + 1, j + 1].Item1 == i && path[i + 1, j + 1].Item2 == j) { prev[frame][j] = i; next[frame - 1][i] = j; lcss[frame][j] = lcs[i, j]; } Tuple <int, int> pair = path[i + 1, j + 1]; i = pair.Item1 - 1; j = pair.Item2 - 1; } } } } int[] top = new int[frameCount]; List <List <Tuple <int, int> > > layers = new List <List <Tuple <int, int> > >(); while (true) { bool[] isAtTop = new bool[frameCount]; bool exist = false; for (int frame = 0; frame < frameCount; ++frame) { // now calculate a bool of isAtTop[frame] if (top[frame] >= intervals[frame].Count) // this frame is already empty { continue; } exist = true; bool flag = true; int current = prev[frame][top[frame]]; int currentFrame = frame - 1; while (current > -1) { if (top[currentFrame] != current) { flag = false; break; } current = prev[currentFrame][current]; --currentFrame; } current = next[frame][top[frame]]; currentFrame = frame + 1; while (current > -1) { if (top[currentFrame] != current) { flag = false; break; } current = next[currentFrame][current]; ++currentFrame; } isAtTop[frame] = flag; } if (!exist) { break; } layers.Add(new List <Tuple <int, int> >()); var layer = layers.Last <List <Tuple <int, int> > >(); for (int frame = 0; frame < frameCount; ++frame) { if (isAtTop[frame]) { layer.Add(new Tuple <int, int>(frame, top[frame])); ++top[frame]; } } } //Point[,] positions = new Point[permutation.FrameCount, permutation.CharacterCount]; //double[,] posY = new double[frameCount, characterCount]; int yBaseline = 0; int minY = int.MaxValue; int maxY = int.MinValue; for (int i = 0; i < layers.Count; ++i) { List <Tuple <int, int> > layer = layers[i]; int[] topY = new int[layer.Count]; int[] bottomY = new int[layer.Count]; int lastTopY = -100000; minY = int.MaxValue; maxY = int.MinValue; for (int j = 0; j < layer.Count; ++j) { int frame = layer[j].Item1; int k = layer[j].Item2; if (prev[frame][k] == -1) { topY[j] = 0; lastTopY = 0; } else { topY[j] = lastTopY - lcss[frame][k].Item2 + lcss[frame][k].Item1; lastTopY = topY[j]; } if (minY > topY[j]) { minY = topY[j]; } } for (int j = 0; j < layer.Count; ++j) { int frame = layer[j].Item1; int k = layer[j].Item2; topY[j] -= minY; bottomY[j] = topY[j] + intervals[frame][k].Length; for (int ii = 0; ii < intervals[frame][k].Length; ++ii) { int character = intervals[frame][k][ii]; posY[character, frame] = yBaseline + (topY[j] + ii) * (int)_app.Status.Config.Style.DefaultInnerGap; //positions[frame, character] = new Point(frame * styles.TimeScaleFactor, baseline + (topY[j] + ii) * styles.InnerDistance); if (maxY < posY[character, frame]) { maxY = (int)posY[character, frame]; } } } yBaseline = maxY + (int)_app.Status.Config.Style.OuterGap; } return(posY.Clone <double>()); PositionTable <double> position = posY.Clone <double>(); for (int frame = 0; frame < frameCount; ++frame) { for (int i = 0; i < story.Characters.Count; ++i) { position[i, frame] /= 5; } } PositionOptimizer3 optimizer2 = new PositionOptimizer3(); PositionOptimizer2 optimizer = new PositionOptimizer2(); position = optimizer.Optimize(story, position, 1.0, 0.05, 0.0, 0.0); PositionOptimizer1 optimizer1 = new PositionOptimizer1(); int x = 0; while (x-- > 0) { position = optimizer1.Optimize(story, position); position = optimizer.Optimize(story, position, 1.0, 0.03, 0.0, 0.0); } double min = 0; for (int id = 0; id < story.Characters.Count; ++id) { for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { if (story.SessionTable[id, frame] != -1 && min > position[id, frame]) { min = position[id, frame]; } } } for (int id = 0; id < story.Characters.Count; ++id) { for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { if (story.SessionTable[id, frame] != -1) { position[id, frame] -= min; position[id, frame] *= 5; } } } return(position); } }
public BundleMapping(Story story, PositionTable <int> perm, PositionTable <int> segments) { bundleMap = new int[story.Characters.Count, story.FrameCount]; bundleList = new List <List <Tuple <int, int> > >(); bundleSessionList = new List <List <int> >(); for (int frame = 0; frame < story.FrameCount; ++frame) { List <Tuple <int, int> > list = new List <Tuple <int, int> >(); for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { list.Add(new Tuple <int, int>(i, perm[i, frame])); } } list.Sort((a, b) => a.Item2.CompareTo(b.Item2)); List <List <int> > groups = new List <List <int> >(); int last = -2; foreach (Tuple <int, int> tuple in list) { if (story.SessionTable[tuple.Item1, frame] != last) { groups.Add(new List <int>()); } groups.Last().Add(tuple.Item1); last = story.SessionTable[tuple.Item1, frame]; } foreach (List <int> group in groups) { int bundleId = -1; if (frame > 0) { foreach (int i in group) { if (segments[i, frame] == segments[i, frame - 1]) { bundleId = bundleMap[i, frame - 1]; break; } } } if (bundleId == -1) { bundleSessionList.Add(new List <int>()); bundleList.Add(new List <Tuple <int, int> >()); bundleId = bundleList.Count - 1; } foreach (int i in group) { bundleMap[i, frame] = bundleId; bundleList[bundleId].Add(new Tuple <int, int>(i, frame)); if (story.SessionTable[i, frame] == 23) { bundleId *= 1; } if (!bundleSessionList[bundleId].Contains(story.SessionTable[i, frame])) { bundleSessionList[bundleId].Add(story.SessionTable[i, frame]); } } } } }
public void SolveStory(Story story) { DateTime start = DateTime.Now; DateTime time = DateTime.Now; //GotoHellYuzuru(story); // Console.WriteLine(Status.isPermDone); // StoryVis18: Reset All Status // add rabbit in session 9999 RabbitAdder.AddRabbit(story); SessionDeleter deleter = new SessionDeleter(); deleter.delete(story, Status.Config.SelectedSessions); Grouper grouper = new Grouper(); grouper.group(story, Status.Config.GroupIds.ToHashSet()); IPermutationCalculator permCalculator = new LocationTreeCalculator(); // IPermutationCalculator permCalculator = new CrossingMinimizedCalculator(); _perm = permCalculator.Calculate(story); ConstraintCalculator ctrCalculator = new ConstraintCalculator(this); PositionTable <int> _newPerm = ctrCalculator.Reorder(story, _perm); _perm = _newPerm; Status.isPermDone = true; //MessageBox.Show((DateTime.Now - start).ToString()); start = DateTime.Now; IAligner aligner = new LocationTreeAligner(this); _segments = aligner.Align(story, _perm); Status.isAlignDone = true; SessionBreaker sessionBreak = new SessionBreaker(this, story); sessionBreak.BreakAt(Status.Config.SessionBreaks); //MessageBox.Show((DateTime.Now - start).ToString()); start = DateTime.Now; IOptimizer persistentOptimizer = new PersistentOptimizer(this, story, _perm, _segments, Status.Config.Style.DefaultInnerGap, Status.Config.Style.OuterGap); var position = persistentOptimizer.Optimize(); _position = position; time = DateTime.Now; Console.WriteLine("persistent time: {0}", time - start); Status.isOptimizeDone = true; MoveToPositive(story, _position); //MessageBox.Show((DateTime.Now - start).ToString()); start = DateTime.Now; time = DateTime.Now; // _bundle = Status.Optimizer.Optimize(); //MessageBox.Show((DateTime.Now - start).ToString()); //start = DateTime.Now; LineRelaxer relaxer = new LineRelaxer(this); if (Status.isBundleMode) { _relaxedPos = relaxer.Relax(story, _bundle); } else { _relaxedPos = relaxer.Relax(story, _position); } Status.isRelaxDone = true; //add for LOR //MessageBox.Show((DateTime.Now - start).ToString()); _framePos = CalculateFramePos(story); Console.WriteLine(Crossing.CountCrossing(story, _perm)); //OutputYuzuru(); // PathOptimizer // PathGenerator pathGenerator = new PathGenerator(); // List<List<Point>> paths = pathGenerator.Generate(_relaxedPos); // Console.WriteLine(Crossing.CountWiggle(story, _segments)); }
private Tuple <double, List <int> > DfsSessionSubtree(Story story, Dictionary <int, List <int> >[] linesInSessions, PositionTable <int> perm, int sessionId, int frame, int reference) { List <int> lineList = new List <int>(linesInSessions[frame][sessionId]); double barycenter; if (reference == -1) { lineList.Sort((a, b) => a.CompareTo(b)); barycenter = -1; } else { lineList.Sort((a, b) => { // if reference existing and both two lines existing at reference if (perm[a, reference] != -1 && perm[b, reference] != -1) // -> (story.Session[a, reference] != -1 && story.Session[b, ref] != -1) { return(perm[a, reference].CompareTo(perm[b, reference])); } // either of reference perm = -1, we compare current frame if they have if (perm[a, frame] != -1 && perm[b, frame] != -1) { return(perm[a, frame].CompareTo(perm[b, frame])); } // put new starting one at bottom if (perm[a, reference] != perm[b, reference]) // both not equal to -1 { return(perm[b, reference].CompareTo(perm[a, reference])); // tricky: i swap the pair here so that -1 will dominate } //return perm[a, reference].CompareTo(perm[b, reference]); return(a.CompareTo(b)); }); barycenter = GetBarycenter(perm, lineList, reference); } return(new Tuple <double, List <int> >(barycenter, lineList)); }
public PositionTable <double> Optimize() { PositionTable <double> result = new PositionTable <double>(story.Characters.Count, story.FrameCount); int count = -1; // if indices are the same, they are aligned for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { if (frame > 0 && story.SessionTable[i, frame - 1] != -1 && segment[i, frame] == segment[i, frame - 1]) { index[i, frame] = count; } else { index[i, frame] = ++count; } } } } int NumVariable = ++count; List <List <Tuple <int, int> > > timeCharacterPermList = new List <List <Tuple <int, int> > >(); for (int frame = 0; frame < story.FrameCount; ++frame) { // charaters at timeframe List <Tuple <int, int> > l = new List <Tuple <int, int> >(); for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { l.Add(new Tuple <int, int>(i, perm[i, frame])); } } // get character order in current frame // apply result in location tree sort l.Sort((a, b) => a.Item2.CompareTo(b.Item2)); timeCharacterPermList.Add(l); if (frame == 0) { for (int k = 0; k < l.Count - 1; ++k) { int x = l[k].Item1; int y = l[k + 1].Item1; // inner constraints var sessionX = story.SessionTable[x, frame]; var sessionY = story.SessionTable[y, frame]; if (k == 0) { // initial lies to origin result[x, frame] = 0; } if (sessionX == sessionY) { var distance = distanceOrInnerGap(sessionX, defaultInnerGap); result[y, frame] = result[x, frame] + distance; } else { var distance = distanceOrOuterGap(sessionX, sessionY, defaultOuterGap); result[y, frame] = result[x, frame] + distance; } } } else { // may trace back // find first aligned for top, if not found, use first character // and use it as base line // if any other aligned character is assigned to a coordinate greater than last time frame, // trace back last time frame and adjust it and all other coordinates under it and before that time frame // a := find first aligned character // k := a's index in perm of current time frame // l := permuation of character at current time frame // llist := list of l (in all previous timeframe) // result[a, frame] = result[a, frame - 1] // for j := k to 1 // x := l[j] // y := l[j - 1] // result[y, frame] = result[x, frame] - (distance according to session gaps) // for j := k to l.Count - 1 // x := l[j] // y := l[j + 1] // result[y, frame] = result[x, frame] + (distance according to session gaps) // if y should align to last timeframe and result[y, frame] < result[y, frame - 1] // result[y, frame] = result[y, frame - 1] (align) // for m := last frame to first frame // lp := llist[m] // for p in lp // if (p should align && result[p, m] < result[p, m + 1]) // result[p, m] = result[p, m + 1] // align last to current // for q := index of p to lp.Count - 1 // x := l[q] // y := l[q + 1] // result[y, frame] = result[x, frame] + (distance according to session gaps) int firstAlignedIndex = 0; // use middle to align as default if no alignment is specified int firstAlignedCharacter = l[firstAlignedIndex].Item1; foreach (var tuple in l) { if (index[tuple.Item1, frame] == index[tuple.Item1, frame - 1]) { // just tired of keeping index firstAlignedCharacter = tuple.Item1; break; } } result[firstAlignedCharacter, frame] = result[firstAlignedCharacter, frame - 1]; for (int j = firstAlignedIndex; j >= 1; j--) { var x = l[j].Item1; var y = l[j - 1].Item1; var sessionX = story.SessionTable[x, frame]; var sessionY = story.SessionTable[y, frame]; if (sessionX == sessionY) { var distance = distanceOrInnerGap(sessionX, defaultInnerGap); result[y, frame] = result[x, frame] - distance; } else { var distance = distanceOrOuterGap(sessionX, sessionY, defaultOuterGap); result[y, frame] = result[x, frame] - distance; } } for (int j = firstAlignedIndex; j < l.Count - 1; j++) { var x = l[j].Item1; var y = l[j + 1].Item1; var sessionX = story.SessionTable[x, frame]; var sessionY = story.SessionTable[y, frame]; if (sessionX == sessionY) { var distance = distanceOrInnerGap(sessionX, defaultInnerGap); result[y, frame] = result[x, frame] + distance; } else { var distance = distanceOrOuterGap(sessionX, sessionY, defaultOuterGap); result[y, frame] = result[x, frame] + distance; } if (index[y, frame] == index[y, frame - 1] && result[y, frame] < result[y, frame - 1]) { // should align result[y, frame] = result[y, frame - 1]; } } for (int m = frame - 1; m >= 0; m--) { var lp = timeCharacterPermList[m]; for (int i = 0; i < lp.Count; i++) { var p = lp[i].Item1; if (index[p, m] == index[p, m + 1] && result[p, m] < result[p, m + 1]) { result[p, m] = result[p, m + 1]; } for (int j = i; j < lp.Count - 1; j++) { var x = lp[j].Item1; var y = lp[j + 1].Item1; var sessionX = story.SessionTable[x, m]; var sessionY = story.SessionTable[y, m]; if (sessionX == sessionY) { var distance = distanceOrInnerGap(sessionX, defaultInnerGap); result[y, m] = result[x, m] + distance; } else { var distance = distanceOrOuterGap(sessionX, sessionY, defaultOuterGap); result[y, m] = result[x, m] + distance; } } } } } } return(result); }
public Dictionary <int, Node> Init(Story story, PositionTable <int> perm, int frame, int reference) { Dictionary <int, Node> nodeDict = new Dictionary <int, Node>(); SessionTable sessionTable = story.SessionTable; Dictionary <int, List <int> > sessionMap = new Dictionary <int, List <int> >(); for (int character = 0; character < story.Characters.Count; character++) { int sessionId = sessionTable[character, frame]; if (sessionId > -1 && !sessionMap.ContainsKey(sessionId)) { sessionMap.Add(sessionId, new List <int>()); } } for (int character = 0; character < story.Characters.Count; character++) { int sessionId = sessionTable[character, frame]; if (sessionId > -1) { List <int> session = sessionMap[sessionId]; session.Add(character); } } int id = -1; int pos = -1; int nodeCount = story.Characters.Count; foreach (var session in sessionMap.Values) { if (session.Count == 1) { id = session[0]; pos = perm[id, frame]; if (pos > -1) { Node tempNode = new Node(id, pos); tempNode.GetBaryCenterRef(perm, id, frame, reference, frameCount); tempNode.L = new List <Node>(); tempNode.L.Add(tempNode); nodeDict.Add(id, tempNode); } } else { List <int> characters = SortCharacters(session, perm, frame); id = nodeCount++; Node sessionNode = new Node(id, -1); foreach (var nodeID in characters) { pos = perm[nodeID, frame]; Node tempNode = new Node(nodeID, pos); tempNode.GetBaryCenterRef(perm, nodeID, frame, reference, frameCount); tempNode.L = new List <Node>(); tempNode.L.Add(tempNode); sessionNode.L.Add(tempNode); } // sort nodes within session sessionNode.L = BaryCenterSort(sessionNode.L); sessionNode.GetBaryCenter2(); nodeDict.Add(id, sessionNode); } } return(nodeDict); }
public Tuple <double, double, double>[][] Relax(Story story, PositionTable <double> position) { // calculate x factor //double xfactor; { double min = int.MaxValue; double max = int.MinValue; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (min > position[i, frame]) { min = position[i, frame]; } if (max < position[i, frame]) { max = position[i, frame]; } } } //xfactor = 3 * (max - min) / story.TimeStamps[story.TimeStamps.Length - 1]; } // build up original table Tuple <double, double, double>[][] result = new Tuple <double, double, double> [story.Characters.Count][]; for (int i = 0; i < story.Characters.Count; ++i) { result[i] = new Tuple <double, double, double> [story.FrameCount]; } double xBaseline = 0; for (int frame = 0; frame < story.FrameCount; ++frame) { double xEnd = xBaseline + _app.Status.Config.Style.XFactor * (story.TimeStamps[frame + 1] - story.TimeStamps[frame]); for (int i = 0; i < story.Characters.Count; ++i) { result[i][frame] = new Tuple <double, double, double>(xBaseline, xEnd, position[i, frame]); } xBaseline = xEnd + _app.Status.Config.Style.XGap; } if (!_app.Status.Config.Relaxing) { return(result); } // relax List <double> pinRight = new List <double>(); for (int id = 0; id < story.Characters.Count; id++) { pinRight.Add(0); } for (int frame = 0; frame < story.FrameCount - 1; frame++) { int frameLeft = frame; int frameRight = frame + 1; //List<List<int>> chNeedRelax = new List<List<int>>(); Dictionary <Tuple <int, int>, List <int> > needRelax = new Dictionary <Tuple <int, int>, List <int> >(); //find the group to relax for (int id = 0; id < story.Characters.Count; id++) { double k = Math.Abs((result[id][frameRight].Item3 - result[id][frameLeft].Item3) / (result[id][frameRight].Item1 - result[id][frameLeft].Item2)); if (story.SessionTable[id, frameLeft] != -1 && story.SessionTable[id, frameRight] != -1 && position[id, frameLeft] != position[id, frameRight] && k > 1) { Tuple <int, int> key = new Tuple <int, int>(story.SessionTable[id, frameLeft], story.SessionTable[id, frameRight]); if (needRelax.ContainsKey(key)) { needRelax[key].Add(id); } else { needRelax.Add(key, new List <int>()); needRelax[key].Add(id); } } } //relax each group foreach (Tuple <int, int> key in needRelax.Keys) { List <int> idList = needRelax[key]; List <double> leftPos = new List <double>(); List <double> rightPos = new List <double>(); foreach (int id in idList) { leftPos.Add(Math.Max(pinRight[id], GetLeftPos(id, frameLeft, frameRight))); rightPos.Add(GetRightPos(id, frameRight, frameRight)); } double leftResult = leftPos.Max(); double rightResult = rightPos.Max(); if (Math.Abs(leftResult - rightResult) > Math.Abs(result[idList[0]][frameRight].Item3 - result[idList[0]][frameLeft].Item3))//can relax { } } } return(result); }
public PositionTable <int> Reorder(Story story, PositionTable <int> perm) { // initialize new ordering PositionTable <int> _perm = new PositionTable <int>(story.Characters.Count, story.FrameCount); frameCount = story.FrameCount; for (int i = 0; i < story.Characters.Count; ++i) { for (int j = 0; j < story.FrameCount; ++j) { _perm[i, j] = perm[i, j]; } } OrderContainer orderContainer = new OrderContainer(frameCount, _app.Status.Config.Orders, _app.Status.Config.OrderTable, story); List <Tuple <int, int> > constraints = orderContainer.OrderTable; // max iteration times int maxItr = 1; for (int i = 0; i < maxItr; i++) { // forward sweep for (int frame = 0; frame < story.FrameCount; frame++) { // NOTICE!!! constraints will be changed during reordering. List <Node> sortedList = ReorderFrame(story, _perm, constraints, frame, frame - 1); // except rabbit case int rabbitId = story.rabbitId; // new ordering for (int j = 0; j < sortedList.Count; j++) { int characterId = sortedList[j].ID; if (characterId > -1) { _perm[characterId, frame] = j; } } List <int> sortedOrder = orderContainer.SortedOrderTable[frame]; if (sortedOrder.Count > 0) { for (int k = 0; k < story.Characters.Count; k++) { if (_perm[k, frame] > -1) { _perm[k, frame] = sortedOrder[k]; } } } // force rabbit to the first place int rabbitPos = _perm[rabbitId, frame]; for (int k = 0; k < story.Characters.Count; k++) { int pos = _perm[k, frame]; if (pos >= 0 && pos < rabbitPos) { _perm[k, frame] += 1; } } _perm[rabbitId, frame] = 0; } } return(_perm); }
public PositionTable <double> Solve(Story story) { int outerGap = (int)(_app.Status.Config.Style.OuterGap / _app.Status.Config.Style.DefaultInnerGap); PositionTable <int> positionTable = new PositionTable <int>(story.Characters.Count, story.TimeStamps.Length - 1); // 1.put first frame List <Tuple <int, List <int> > > list = Ultities.GetGroups(story, 0); //List<Tuple<int, List<int>>> list = Ultities.GetRandomList<Tuple<int, List<int>>>(Ultities.GetGroups(story, 0)); int yBaseline = 0; foreach (Tuple <int, List <int> > tuple in list) { foreach (int id in tuple.Item2) { positionTable[id, 0] = yBaseline; yBaseline += 1; } yBaseline += outerGap; } // 2.calculate group average for other frames for (int frame = 1; frame < story.TimeStamps.Length - 1; ++frame) { list = Ultities.GetGroups(story, frame); list.Sort((a, b) => - a.Item2.Count.CompareTo(b.Item2.Count)); List <int> occupied = new List <int>(); foreach (Tuple <int, List <int> > tuple in list) { // sort by previous position tuple.Item2.Sort((a, b) => positionTable[a, frame - 1].CompareTo(positionTable[b, frame - 1])); // calculate weighted average position int weight = 0; int value = 0; int sub = 0; bool allNew = true; foreach (int id in tuple.Item2) { if (story.SessionTable[id, frame - 1] != -1) { allNew = false; break; } } int top; if (allNew) { top = 0 - tuple.Item2.Count / 2; } else { for (int i = 0; i < tuple.Item2.Count; ++i) { int id = tuple.Item2[i]; int w = Ultities.GetHistoryLength(story, id, frame); value += w * positionTable[id, frame - 1]; weight += w; sub += w * i; } double bestCenter = (double)value / weight; top = (int)Math.Round((bestCenter * weight - sub) / weight); } // find a place to put it for (int shift = 0; true; ++shift) { int shiftedTop1 = top - shift; int shiftedTop2 = top + shift; bool available = false; int pos = 0; if (IsAvailable(occupied, shiftedTop1 - outerGap, shiftedTop1 + tuple.Item2.Count - 1 + outerGap)) { pos = shiftedTop1; available = true; } else if (IsAvailable(occupied, shiftedTop2 - outerGap, shiftedTop2 + tuple.Item2.Count - 1 + outerGap)) { pos = shiftedTop2; available = true; } if (available) { for (int i = 0; i < tuple.Item2.Count; ++i) { positionTable[tuple.Item2[i], frame] = pos + i; occupied.Add(pos + i); } break; } } } } for (int t = 0; t < 10; ++t) { // shift lines to new positions for (int frame = 1; frame < story.TimeStamps.Length - 2; ++frame) { HashSet <int> deltas = new HashSet <int>(); for (int id = 0; id < story.Characters.Count; ++id) { if (story.SessionTable[id, frame] != -1 && story.SessionTable[id, frame + 1] != -1) { int delta = positionTable[id, frame] - positionTable[id, frame + 1]; if (!deltas.Contains(delta)) { deltas.Add(delta); } } } int minCost = int.MaxValue; int minDelta = 0; foreach (int delta in deltas) { int cost = 0; for (int id = 0; id < story.Characters.Count; ++id) { if (story.SessionTable[id, frame] != -1 && story.SessionTable[id, frame + 1] != -1) { cost += Math.Abs(positionTable[id, frame + 1] + delta - positionTable[id, frame]); if (positionTable[id, frame + 1] + delta == positionTable[id, frame]) { cost -= 100; } } } if (minCost > cost) { minCost = cost; minDelta = delta; } } for (int id = 0; id < story.Characters.Count; ++id) { positionTable[id, frame + 1] += minDelta; } } for (int frame = 1; frame < story.TimeStamps.Length - 2; ++frame) { for (int id = 0; id < story.Characters.Count; ++id) { if (Ultities.GetGroupCount(story, id, frame) == 1 && Ultities.GetGroupCount(story, id, frame + 1) > 1) { bool isHead = true; int f; for (f = frame - 1; f >= 0; --f) { if (Ultities.GetGroupCount(story, id, f) > 1) { isHead = false; break; } else if (story.SessionTable[id, f] == -1) { break; } } HashSet <int> tubes = new HashSet <int>(); for (int ii = f + 1; ii <= frame; ++ii) { for (int ch = 0; ch < story.Characters.Count; ++ch) { if (ch != id && story.SessionTable[ch, ii] != -1) { if (!tubes.Contains(positionTable[ch, ii])) { tubes.Add(positionTable[ch, ii]); } } } } var occupied = tubes.ToList <int>(); int p = positionTable[id, frame + 1]; // find a place to put it for (int shift = 0; true; ++shift) { int shiftedTop1 = p - shift; int shiftedTop2 = p + shift; bool available = false; int pp = 0; if (IsAvailable(occupied, shiftedTop1 - outerGap, shiftedTop1 + outerGap)) { pp = shiftedTop1; available = true; } else if (IsAvailable(occupied, shiftedTop2 - outerGap, shiftedTop2 + outerGap)) { pp = shiftedTop2; available = true; } if (available) { for (int ii = f + 1; ii <= frame; ++ii) { //if (Math.Abs(positionTable[id, ii] - pp) > 0) { positionTable[id, ii] = pp; } } break; } } } } } // } // move to positive int min = 0; for (int id = 0; id < story.Characters.Count; ++id) { for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { if (story.SessionTable[id, frame] != -1 && min > positionTable[id, frame]) { min = positionTable[id, frame]; } } } for (int id = 0; id < story.Characters.Count; ++id) { for (int frame = 0; frame < story.TimeStamps.Length - 1; ++frame) { if (story.SessionTable[id, frame] != -1) { positionTable[id, frame] -= min; positionTable[id, frame] *= 5; } } } return(positionTable.Clone <double>()); }
public Constrainer(List <Tuple <int, int> > orders, Dictionary <int, Node> nodes, PositionTable <int> perm, int frame) { nodeDict = nodes; InitConstraints(orders, perm, frame); UpdateConstranedNodes(); }
public PositionTable <double> Optimize() { DateTime start = DateTime.Now; double[] x = new double[xCount]; try { task.optimize(); task.solutionsummary(mosek.streamtype.msg); mosek.solsta solsta; mosek.prosta prosta; task.getsolutionstatus(mosek.soltype.itr, out prosta, out solsta); task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, 0, xCount, x); switch (solsta) { case mosek.solsta.optimal: case mosek.solsta.near_optimal: Console.WriteLine("Optimal primal solution\n"); break; case mosek.solsta.dual_infeas_cer: case mosek.solsta.prim_infeas_cer: case mosek.solsta.near_dual_infeas_cer: case mosek.solsta.near_prim_infeas_cer: Console.WriteLine("Primal or dual infeasibility.\n"); break; case mosek.solsta.unknown: Console.WriteLine("Unknown solution status.\n"); break; default: Console.WriteLine("Other solution status"); break; } } catch (mosek.Exception e) { Console.WriteLine(e.Code); Console.WriteLine(e); } Console.WriteLine("{0}", DateTime.Now - start); PositionTable <double> position = new PositionTable <double>(story.Characters.Count, story.FrameCount); for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { position[i, frame] = x[index[i, frame]]; } } } return(position); }
public void Optimize(Story story, PositionTable <double> position) { int count = 0; List <double> list = new List <double>(); int[,] index = new int[story.Characters.Count, story.FrameCount]; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { index[i, frame] = count++; list.Add(position[i, frame]); } } } double[] X = list.ToArray <double>(); int[,] Q = new int[X.Length, X.Length]; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount - 1; ++frame) { int left = frame; int right = frame + 1; if (story.SessionTable[i, left] != -1 && story.SessionTable[i, right] != -1) { Q[index[i, left], index[i, left]] += 2; Q[index[i, right], index[i, right]] += 2; Q[index[i, left], index[i, right]] -= 2; Q[index[i, right], index[i, left]] -= 2; } } } List <int> li = new List <int>(); List <int> lj = new List <int>(); List <double> lv = new List <double>(); for (int i = 0; i < X.Length; ++i) { for (int j = 0; j <= i; ++j) { if (Q[i, j] != 0) { li.Add(i); lj.Add(j); lv.Add((double)Q[i, j]); } } } int[] qsubi = li.ToArray(); int[] qsubj = lj.ToArray(); double[] qval = lv.ToArray(); List <Tuple <int, int> > listInner = new List <Tuple <int, int> >(); List <Tuple <int, int> > listOuter = new List <Tuple <int, int> >(); for (int frame = 0; frame < story.FrameCount; ++frame) { List <Tuple <int, double> > l = new List <Tuple <int, double> >(); for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { l.Add(new Tuple <int, double>(i, position[i, frame])); } } l.Sort((a, b) => a.Item2.CompareTo(b.Item2)); for (int k = 0; k < l.Count - 1; ++k) { int x = l[k].Item1; int y = l[k + 1].Item1; if (story.SessionTable[x, frame] == story.SessionTable[y, frame]) { listInner.Add(new Tuple <int, int>(index[x, frame], index[y, frame])); } else { listOuter.Add(new Tuple <int, int>(index[x, frame], index[y, frame])); } } } const double infinity = 0; int NumConstraint = listInner.Count + listOuter.Count; int NumVariable = X.Length; double[] blx = new double[NumVariable]; double[] bux = new double[NumVariable]; mosek.boundkey[] bkx = new mosek.boundkey[NumVariable]; for (int i = 0; i < NumVariable; ++i) { bkx[i] = mosek.boundkey.fr; } int[][] asub = new int[NumVariable][]; double[][] aval = new double[NumVariable][]; List <int>[] asubList = new List <int> [NumVariable]; List <double>[] avalList = new List <double> [NumVariable]; for (int i = 0; i < NumVariable; ++i) { asubList[i] = new List <int>(); avalList[i] = new List <double>(); } for (int i = 0; i < listInner.Count; ++i) { Tuple <int, int> pair = listInner[i]; int x = pair.Item1; int y = pair.Item2; asubList[x].Add(i); avalList[x].Add(-1); asubList[y].Add(i); avalList[y].Add(1); } for (int i = 0; i < listOuter.Count; ++i) { int j = i + listInner.Count; Tuple <int, int> pair = listOuter[i]; int x = pair.Item1; int y = pair.Item2; asubList[x].Add(j); avalList[x].Add(-1); asubList[y].Add(j); avalList[y].Add(1); } for (int i = 0; i < NumVariable; ++i) { asub[i] = asubList[i].ToArray(); aval[i] = avalList[i].ToArray(); } mosek.boundkey[] bkc = new mosek.boundkey[NumConstraint]; double[] blc = new double[NumConstraint]; double[] buc = new double[NumConstraint]; for (int i = 0; i < listInner.Count; ++i) { bkc[i] = mosek.boundkey.fx; blc[i] = 28; buc[i] = 28; } for (int i = listInner.Count; i < listInner.Count + listOuter.Count; ++i) { bkc[i] = mosek.boundkey.lo; blc[i] = 84; buc[i] = infinity; } mosek.Task task = null; mosek.Env env = null; double[] xx = new double[NumVariable]; try { env = new mosek.Env(); env.init(); task = new mosek.Task(env, 0, 0); task.putmaxnumvar(NumVariable); task.putmaxnumcon(NumConstraint); task.append(mosek.accmode.con, NumConstraint); task.append(mosek.accmode.var, NumVariable); task.putcfix(0.0); for (int j = 0; j < NumVariable; ++j) { task.putcj(j, 0); task.putbound(mosek.accmode.var, j, bkx[j], blx[j], bux[j]); task.putavec(mosek.accmode.var, j, asub[j], aval[j]); } for (int i = 0; i < NumConstraint; ++i) { task.putbound(mosek.accmode.con, i, bkc[i], blc[i], buc[i]); } task.putobjsense(mosek.objsense.minimize); task.putqobj(qsubi, qsubj, qval); task.optimize(); mosek.solsta solsta; mosek.prosta prosta; task.getsolutionstatus(mosek.soltype.itr, out prosta, out solsta); task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, 0, NumVariable, xx); } catch (mosek.Exception e) { Console.WriteLine(e.Code); Console.WriteLine(e); } finally { if (task != null) { task.Dispose(); } if (env != null) { env.Dispose(); } } for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { position[i, frame] = xx[index[i, frame]]; } } } }
public PositionTable <double> Solve(Story story, PositionTable <double> position) { return(position); }
private void RecalculateFrameFreeSideRemembered(Story story, PositionTable <int> perm, int[] inverted, int frame, int refer) { // first calculate the barycenter Dictionary <int, List <int> > dict = new Dictionary <int, List <int> >(); for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { if (!dict.ContainsKey(story.SessionTable[i, frame])) { dict.Add(story.SessionTable[i, frame], new List <int>()); } dict[story.SessionTable[i, frame]].Add(i); } } List <Tuple <int, double> > bclist = new List <Tuple <int, double> >(); foreach (KeyValuePair <int, List <int> > pair in dict) { double barycenter = -1; double sum = 0; int count = 0; foreach (int x in pair.Value) { if (story.SessionTable[x, refer] != -1) { sum += perm[x, refer]; ++count; } } if (count > 0) { barycenter = sum / count; } else { barycenter = 1e6; } // TODO(Enxun): if count=0 how to handle? bclist.Add(new Tuple <int, double>(pair.Key, barycenter)); } bclist.Sort((a, b) => { if (a.Item2 != b.Item2) { return(a.Item2.CompareTo(b.Item2)); } int diff = 0; foreach (int x in dict[a.Item1]) { if (story.SessionTable[x, refer] != -1) { foreach (int y in dict[b.Item1]) { if (story.SessionTable[y, refer] != -1) { if (perm[x, refer] > perm[y, refer]) { ++diff; } else if (perm[x, refer] < perm[y, refer]) { --diff; } } } } } if (diff > 0) { return(1); } else if (diff < 0) { return(-1); } else { return(0); } }); Dictionary <int, double> bcDict = new Dictionary <int, double>();//bclist.ToDictionary(p => p.Item1, p => p.Item2); for (int i = 0; i < bclist.Count; ++i) { Tuple <int, double> tuple = bclist[i]; if (tuple.Item2 == 1e6) { bcDict.Add(tuple.Item1, -1); } else { bcDict.Add(tuple.Item1, i); } } // sorting List <Tuple <int, double, int, int, int> > tupleList = new List <Tuple <int, double, int, int, int> >(); for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { tupleList.Add(new Tuple <int, double, int, int, int>( inverted[story.GetLocationId(story.SessionTable[i, frame])], bcDict[story.SessionTable[i, frame]], perm[i, refer], perm[i, frame], i)); } } tupleList.Sort((a, b) => { if (a.Item1 != b.Item1) { return(a.Item1.CompareTo(b.Item1)); } if (a.Item2 != -1 && b.Item2 != -1 && a.Item2 != b.Item2) { return(a.Item2.CompareTo(b.Item2)); } if (a.Item3 != -1 && b.Item3 != -1 && a.Item3 != b.Item3) { return(a.Item3.CompareTo(b.Item3)); } if (a.Item4 != -1 && b.Item4 != -1 && a.Item4 != b.Item4) { return(a.Item4.CompareTo(b.Item4)); } return(0); //return a.Item5.CompareTo(b.Item5); }); for (int i = 0; i < tupleList.Count; ++i) { Tuple <int, double, int, int, int> tuple = tupleList[i]; perm[tuple.Item5, frame] = i; } }
public PositionTable <int> Align(Story story, PositionTable <int> permutation) { // location tree => location constraint list List <int> locationList = new List <int>(); BuildLocationList(story, story.LocationRoot, locationList); int[] invertedLocationList = new int[locationList.Count]; for (int i = 0; i < locationList.Count; ++i) { invertedLocationList[locationList[i]] = i; } // initialize segments to -1 or individual value PositionTable <int> segments = new PositionTable <int>(story.Characters.Count, story.FrameCount); int x = 0; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { segments[i, frame] = x++; } else { segments[i, frame] = -1; } } } //for (int i = 0; i < story.Characters.Count; ++i) //{ // for (int j = 0; j < story.FrameCount; ++j) // Console.Write(segments[i, j] + ", "); // Console.WriteLine(); //} // calculate alignmnet for (int frame = 0; frame < story.FrameCount - 1; ++frame) { int leftFrame = frame; int rightFrame = frame + 1; // iterate from different locations for (int li = 0; li < locationList.Count; ++li) { int locationId = locationList[li]; List <List <int> > leftSessions = BuildSessionList(story, permutation, leftFrame, locationId); List <List <int> > rightSessions = BuildSessionList(story, permutation, rightFrame, locationId); double[,] dp = new double[leftSessions.Count + 1, rightSessions.Count + 1]; Tuple <int, int>[,] path = new Tuple <int, int> [leftSessions.Count + 1, rightSessions.Count + 1]; for (int i = 0; i < leftSessions.Count; ++i) { for (int j = 0; j < rightSessions.Count; ++j) { dp[i + 1, j + 1] = -1; Tuple <int, int, int, double> tuple = GetMaximumMatch(story, leftSessions[i], rightSessions[j]); if (dp[i + 1, j + 1] < dp[i, j] + tuple.Item4) { dp[i + 1, j + 1] = dp[i, j] + tuple.Item4; path[i + 1, j + 1] = new Tuple <int, int>(i, j); } if (dp[i + 1, j + 1] < dp[i + 1, j]) { dp[i + 1, j + 1] = dp[i + 1, j]; path[i + 1, j + 1] = new Tuple <int, int>(i + 1, j); } if (dp[i + 1, j + 1] < dp[i, j + 1]) { dp[i + 1, j + 1] = dp[i, j + 1]; path[i + 1, j + 1] = new Tuple <int, int>(i, j + 1); } } } { int i = leftSessions.Count - 1; int j = rightSessions.Count - 1; while (i > -1 && j > -1) { if (path[i + 1, j + 1].Item1 == i && path[i + 1, j + 1].Item2 == j) { //segments[j, rightFrame] = segments[i, leftFrame]; Tuple <int, int, int, double> tuple = GetMaximumMatch(story, leftSessions[i], rightSessions[j]); for (int k = 0; k < tuple.Item3; ++k) { segments[rightSessions[j][tuple.Item2 + k], rightFrame] = segments[leftSessions[i][tuple.Item1 + k], leftFrame]; } } Tuple <int, int> pair = path[i + 1, j + 1]; i = pair.Item1 - 1; j = pair.Item2 - 1; } } } } for (int i = 0; i < story.Characters.Count; ++i) { for (int j = 0; j < story.FrameCount; ++j) { Console.Write(segments[i, j] + ", "); } Console.WriteLine(); } return(segments); }
public PositionTable <double> Optimize(Story story, PositionTable <double> position, double weight1, double weight2, double weight3, double weight4) { // gradient descent optimization //PositionTable<double> position = positionTable.Clone<double>(); double eps = 0.05; double terminal = 0.005; double maxShift = 100.0; int limit = 0; while (maxShift > terminal && ++limit < 200) { eps *= 0.95; PositionTable <double> old = position.Clone <double>(); maxShift = 0.0; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame_start = 0; frame_start < story.TimeStamps.Length - 1; ++frame_start) { if (story.SessionTable[i, frame_start] == -1) { continue; } int frame_end; for (frame_end = frame_start + 1; frame_end < story.TimeStamps.Length - 1 && story.SessionTable[i, frame_end] != -1 && Math.Abs(old[i, frame_end] - old[i, frame_start]) < 0.001; ++frame_end) { } double w = 0; for (int frame = frame_start; frame < frame_end; ++frame) { w += old[i, frame]; } w /= (frame_end - frame_start); for (int frame = frame_start; frame < frame_end; ++frame) { old[i, frame] = w; } double shift = 0.0; for (int frame = frame_start; frame < frame_end; ++frame) { // 1.Inside session { double w1 = weight1; int n = Ultities.GetGroupCount(story, i, frame); for (int j = 0; j < story.Characters.Count; ++j) { if (i != j && story.SessionTable[i, frame] == story.SessionTable[j, frame]) { double d = der1(old[i, frame], old[j, frame], n, 1.0); shift += w1 * eps * d; } } } // 2.Between sessions { double w2 = weight1; for (int j = 0; j < story.Characters.Count; ++j) { if (i != j && story.SessionTable[j, frame] != -1 && story.SessionTable[i, frame] != story.SessionTable[j, frame]) { double d = der2(old[i, frame], old[j, frame], 5.0); shift += w2 * eps * d; } } } // 3.Wiggles { double w3 = weight2; if (frame != 0 && story.SessionTable[i, frame - 1] != -1) { double d = der3(old[i, frame], old[i, frame - 1]); shift += w3 * eps * d; } if (frame != story.TimeStamps.Length - 2 && story.SessionTable[i, frame + 1] != -1) { double d = der3(old[i, frame], old[i, frame + 1]); shift += w3 * eps * d; } } // 4.Smooth { double w4 = weight3; if (frame != 0 && frame != story.TimeStamps.Length - 2 && story.SessionTable[i, frame - 1] != -1 && story.SessionTable[i, frame + 1] != -1) { double d = der3(old[i, frame], (old[i, frame - 1] + old[i, frame + 1]) / 2); shift += w4 * eps * d; } } // 5.Parellel { double w5 = weight4; for (int j = 0; j < story.Characters.Count; ++j) { if (i != j && frame != 0 && story.SessionTable[i, frame] != -1 && story.SessionTable[j, frame] != -1 && story.SessionTable[i, frame - 1] != -1 && story.SessionTable[j, frame - 1] != -1 && story.SessionTable[i, frame] == story.SessionTable[j, frame] && story.SessionTable[i, frame - 1] == story.SessionTable[j, frame - 1]) { double x = old[i, frame] + old[j, frame - 1] - old[i, frame - 1]; double d = der3(old[j, frame], x); shift += w5 * eps * d; } } } } if (maxShift < shift) { maxShift = shift; } for (int frame = frame_start; frame < frame_end; ++frame) { position[i, frame] += shift; } frame_start = frame_end - 1; } } } return(position); }
public void Optimize(Story story, PositionTable <double> position, PositionTable <int> segment) { int count = -1; List <double> X = new List <double>(); int[,] index = new int[story.Characters.Count, story.FrameCount]; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { index[i, frame] = -2; } } for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { if (frame > 0 && story.SessionTable[i, frame - 1] != -1 && segment[i, frame] == segment[i, frame - 1]) { index[i, frame] = count; } else { index[i, frame] = ++count; X.Add(position[i, frame]); } } } } Dictionary <Tuple <int, int>, double> Q = new Dictionary <Tuple <int, int>, double>(); for (int i = 0; i < X.Count; ++i) { Q.Add(new Tuple <int, int>(i, i), 1); } //int[,] Q = new int[X.Count, X.Count]; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount - 1; ++frame) { int left = frame; int right = frame + 1; if (story.SessionTable[i, left] != -1 && story.SessionTable[i, right] != -1 && segment[i, left] != segment[i, right]) { if (!Q.ContainsKey(new Tuple <int, int>(index[i, left], index[i, left]))) { Q.Add(new Tuple <int, int>(index[i, left], index[i, left]), 0); } if (!Q.ContainsKey(new Tuple <int, int>(index[i, right], index[i, right]))) { Q.Add(new Tuple <int, int>(index[i, right], index[i, right]), 0); } if (!Q.ContainsKey(new Tuple <int, int>(index[i, left], index[i, right]))) { Q.Add(new Tuple <int, int>(index[i, left], index[i, right]), 0); } if (!Q.ContainsKey(new Tuple <int, int>(index[i, right], index[i, left]))) { Q.Add(new Tuple <int, int>(index[i, right], index[i, left]), 0); } Q[new Tuple <int, int>(index[i, left], index[i, left])] += 2; Q[new Tuple <int, int>(index[i, right], index[i, right])] += 2; Q[new Tuple <int, int>(index[i, left], index[i, right])] -= 2; Q[new Tuple <int, int>(index[i, right], index[i, left])] -= 2; } } } List <int> li = new List <int>(); List <int> lj = new List <int>(); List <double> lv = new List <double>(); foreach (KeyValuePair <Tuple <int, int>, double> pair in Q) { if (pair.Key.Item1 >= pair.Key.Item2 && pair.Value != 0) { li.Add(pair.Key.Item1); lj.Add(pair.Key.Item2); lv.Add((double)pair.Value); } } int[] qsubi = li.ToArray(); int[] qsubj = lj.ToArray(); double[] qval = lv.ToArray(); List <Tuple <int, int> > listInner = new List <Tuple <int, int> >(); List <Tuple <int, int> > listOuter = new List <Tuple <int, int> >(); for (int frame = 0; frame < story.FrameCount; ++frame) { List <Tuple <int, double> > l = new List <Tuple <int, double> >(); for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { l.Add(new Tuple <int, double>(i, position[i, frame])); } } l.Sort((a, b) => a.Item2.CompareTo(b.Item2)); for (int k = 0; k < l.Count - 1; ++k) { int x = l[k].Item1; int y = l[k + 1].Item1; if (story.SessionTable[x, frame] == story.SessionTable[y, frame]) { if (!listInner.Contains(new Tuple <int, int>(index[x, frame], index[y, frame]))) { listInner.Add(new Tuple <int, int>(index[x, frame], index[y, frame])); } } else { if (!listOuter.Contains(new Tuple <int, int>(index[x, frame], index[y, frame]))) { listOuter.Add(new Tuple <int, int>(index[x, frame], index[y, frame])); } } } } Debug.Assert(!ExistingCircle(listInner, X.Count)); Debug.Assert(!ExistingCircle(listOuter, X.Count)); foreach (Tuple <int, int> tuple in listInner) { Debug.Write(tuple.Item1.ToString() + "->" + tuple.Item2.ToString() + ", "); } const double infinity = 0; int NumConstraint = listInner.Count + listOuter.Count; int NumVariable = X.Count; double[] blx = new double[NumVariable]; double[] bux = new double[NumVariable]; mosek.boundkey[] bkx = new mosek.boundkey[NumVariable]; for (int i = 0; i < NumVariable; ++i) { bkx[i] = mosek.boundkey.ra; blx[i] = -12000; bux[i] = 12000; } bkx[0] = mosek.boundkey.fx; bkx[0] = 0; bkx[0] = 0; int[][] asub = new int[NumVariable][]; double[][] aval = new double[NumVariable][]; List <int>[] asubList = new List <int> [NumVariable]; List <double>[] avalList = new List <double> [NumVariable]; for (int i = 0; i < NumVariable; ++i) { asubList[i] = new List <int>(); avalList[i] = new List <double>(); } for (int i = 0; i < listInner.Count; ++i) { Tuple <int, int> pair = listInner[i]; int x = pair.Item1; int y = pair.Item2; asubList[x].Add(i); avalList[x].Add(-1); asubList[y].Add(i); avalList[y].Add(1); } for (int i = 0; i < listOuter.Count; ++i) { int j = i + listInner.Count; Tuple <int, int> pair = listOuter[i]; int x = pair.Item1; int y = pair.Item2; asubList[x].Add(j); avalList[x].Add(-1); asubList[y].Add(j); avalList[y].Add(1); } for (int i = 0; i < NumVariable; ++i) { asub[i] = asubList[i].ToArray(); aval[i] = avalList[i].ToArray(); } mosek.boundkey[] bkc = new mosek.boundkey[NumConstraint]; double[] blc = new double[NumConstraint]; double[] buc = new double[NumConstraint]; for (int i = 0; i < listInner.Count; ++i) { bkc[i] = mosek.boundkey.fx; //blc[i] = 28; //buc[i] = 28; blc[i] = _app.Status.Config.Style.DefaultInnerGap; buc[i] = _app.Status.Config.Style.DefaultInnerGap; } for (int i = listInner.Count; i < listInner.Count + listOuter.Count; ++i) { bkc[i] = mosek.boundkey.lo; //blc[i] = 84; blc[i] = _app.Status.Config.Style.OuterGap; buc[i] = 1000; } mosek.Task task = null; mosek.Env env = null; double[] xx = new double[NumVariable]; DateTime start = DateTime.Now; try { env = new mosek.Env(); env.set_Stream(mosek.streamtype.log, new msgclass("")); env.init(); task = new mosek.Task(env, 0, 0); task.set_Stream(mosek.streamtype.log, new msgclass("")); task.putmaxnumvar(NumVariable); task.putmaxnumcon(NumConstraint); //task.putdouparam(mosek.dparam.intpnt_nl_tol_pfeas, 1.0e-1); //task.putdouparam(mosek.dparam.intpnt_tol_dfeas, 1.0e-1); //task.putdouparam(mosek.dparam.intpnt_nl_tol_rel_gap, 1.0e-1); //task.putdouparam(mosek.dparam.intpnt_co_tol_infeas, 1.0e-13); //task.putdouparam(mosek.dparam.intpnt_nl_tol_mu_red, 1.0e-13); task.append(mosek.accmode.con, NumConstraint); task.append(mosek.accmode.var, NumVariable); task.putcfix(0.0); for (int j = 0; j < NumVariable; ++j) { task.putcj(j, 0); task.putbound(mosek.accmode.var, j, bkx[j], blx[j], bux[j]); task.putavec(mosek.accmode.var, j, asub[j], aval[j]); } for (int i = 0; i < NumConstraint; ++i) { task.putbound(mosek.accmode.con, i, bkc[i], blc[i], buc[i]); } task.putobjsense(mosek.objsense.minimize); task.putqobj(qsubi, qsubj, qval); task.optimize(); task.solutionsummary(mosek.streamtype.msg); mosek.solsta solsta; mosek.prosta prosta; task.getsolutionstatus(mosek.soltype.itr, out prosta, out solsta); task.getsolutionslice(mosek.soltype.itr, mosek.solitem.xx, 0, NumVariable, xx); switch (solsta) { case mosek.solsta.optimal: case mosek.solsta.near_optimal: Console.WriteLine("Optimal primal solution\n"); //for (int j = 0; j < NumVariable; ++j) // Console.WriteLine("x[{0}]:", xx[j]); break; case mosek.solsta.dual_infeas_cer: case mosek.solsta.prim_infeas_cer: case mosek.solsta.near_dual_infeas_cer: case mosek.solsta.near_prim_infeas_cer: Console.WriteLine("Primal or dual infeasibility.\n"); break; case mosek.solsta.unknown: Console.WriteLine("Unknown solution status.\n"); break; default: Console.WriteLine("Other solution status"); break; } } catch (mosek.Exception e) { Console.WriteLine(e.Code); Console.WriteLine(e); } finally { if (task != null) { task.Dispose(); } if (env != null) { env.Dispose(); } } Console.WriteLine("///{0}", DateTime.Now - start); for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { position[i, frame] = xx[index[i, frame]]; } } } }
public PositionTable <double> Solve(Story story) { int frameCount = story.TimeStamps.Length - 1; int characterCount = story.Characters.Count; int[,] permutaion = new int[characterCount, frameCount]; { List <int[]>[] states = new List <int[]> [frameCount]; List <int>[] dp = new List <int> [frameCount]; List <int>[] path = new List <int> [frameCount]; int[] orderedSequence = new int[characterCount]; for (int i = 0; i < characterCount; ++i) { orderedSequence[i] = i; } for (int frame = 0; frame < frameCount; ++frame) { states[frame] = new List <int[]>(); dp[frame] = new List <int>(); path[frame] = new List <int>(); int[] permutation = (int[])orderedSequence.Clone(); do { if (IsValidPermutation(permutation, story.SessionTable, frame)) { states[frame].Add((int[])permutation.Clone()); } }while (NextPermutation <int>(permutation)); for (int i = 0; i < states[frame].Count; ++i) { if (frame == 0) { dp[frame].Add(0); path[frame].Add(0); } else { int min = int.MaxValue; int from = -1; for (int j = 0; j < states[frame - 1].Count; ++j) { int d = dp[frame - 1][j] + GetCost(states[frame - 1][j], states[frame][i], story.SessionTable, frame); if (d < min) { min = d; from = j; } } dp[frame].Add(min); path[frame].Add(from); } } } // int cost = int.MaxValue; int index = -1; int count = 0; for (int i = 0; i < dp[frameCount - 1].Count; ++i) { if (cost > dp[frameCount - 1][i]) { cost = dp[frameCount - 1][i]; index = i; count = 1; } else if (cost == dp[frameCount - 1][i]) { ++count; } } for (int frame = frameCount - 1; frame > -1; --frame) { for (int id = 0; id < characterCount; ++id) { permutaion[id, frame] = states[frame][index][id]; } index = path[frame][index]; } } // calculate positions PositionTable <int> posY = new PositionTable <int>(characterCount, frameCount); { List <int[]>[] intervals = new List <int[]> [frameCount]; List <int>[] prev = new List <int> [frameCount]; List <int>[] next = new List <int> [frameCount]; List <Tuple <int, int, int> >[] lcss = new List <Tuple <int, int, int> > [frameCount]; for (int frame = 0; frame < frameCount; ++frame) { // find intervals at this frame int[] t = new int[characterCount]; for (int i = 0; i < characterCount; ++i) { t[permutaion[i, frame]] = i; } List <int> p = new List <int>(); for (int i = 0; i < t.Length; ++i) { if (story.SessionTable[t[i], frame] != -1) { p.Add(t[i]); } } intervals[frame] = new List <int[]>(); prev[frame] = new List <int>(); next[frame] = new List <int>(); lcss[frame] = new List <Tuple <int, int, int> >(); int last = -1; for (int i = 0; i < p.Count; ++i) { if (i == p.Count - 1 || story.SessionTable[p[i], frame] != story.SessionTable[p[i + 1], frame]) { intervals[frame].Add(p.GetRange(last + 1, i - last).ToArray <int>()); last = i; prev[frame].Add(-1); next[frame].Add(-1); lcss[frame].Add(new Tuple <int, int, int>(-1, -1, -1)); } } // calculate the connection with previous frame if (frame > 0) { Tuple <int, int, int>[,] lcs = new Tuple <int, int, int> [intervals[frame - 1].Count, intervals[frame].Count]; for (int i = 0; i < intervals[frame - 1].Count; ++i) { for (int j = 0; j < intervals[frame].Count; ++j) { lcs[i, j] = GetLcs(intervals[frame - 1][i], intervals[frame][j]); } } int[,] dp = new int[intervals[frame - 1].Count + 1, intervals[frame].Count + 1]; Tuple <int, int>[,] path = new Tuple <int, int> [intervals[frame - 1].Count + 1, intervals[frame].Count + 1]; for (int i = 0; i < intervals[frame - 1].Count; ++i) { for (int j = 0; j < intervals[frame].Count; ++j) { dp[i + 1, j + 1] = -1; if (dp[i + 1, j + 1] < dp[i, j] + lcs[i, j].Item3) { dp[i + 1, j + 1] = dp[i, j] + lcs[i, j].Item3; path[i + 1, j + 1] = new Tuple <int, int>(i, j); } if (dp[i + 1, j + 1] < dp[i + 1, j]) { dp[i + 1, j + 1] = dp[i + 1, j]; path[i + 1, j + 1] = new Tuple <int, int>(i + 1, j); } if (dp[i + 1, j + 1] < dp[i, j + 1]) { dp[i + 1, j + 1] = dp[i, j + 1]; path[i + 1, j + 1] = new Tuple <int, int>(i, j + 1); } } } { int i = intervals[frame - 1].Count - 1; int j = intervals[frame].Count - 1; while (i > -1 && j > -1) { if (path[i + 1, j + 1].Item1 == i && path[i + 1, j + 1].Item2 == j) { prev[frame][j] = i; next[frame - 1][i] = j; lcss[frame][j] = lcs[i, j]; } Tuple <int, int> pair = path[i + 1, j + 1]; i = pair.Item1 - 1; j = pair.Item2 - 1; } } } } int[] top = new int[frameCount]; List <List <Tuple <int, int> > > layers = new List <List <Tuple <int, int> > >(); while (true) { bool[] isAtTop = new bool[frameCount]; bool exist = false; for (int frame = 0; frame < frameCount; ++frame) { // now calculate a bool of isAtTop[frame] if (top[frame] >= intervals[frame].Count) // this frame is already empty { continue; } exist = true; bool flag = true; int current = prev[frame][top[frame]]; int currentFrame = frame - 1; while (current > -1) { if (top[currentFrame] != current) { flag = false; break; } current = prev[currentFrame][current]; --currentFrame; } current = next[frame][top[frame]]; currentFrame = frame + 1; while (current > -1) { if (top[currentFrame] != current) { flag = false; break; } current = next[currentFrame][current]; ++currentFrame; } isAtTop[frame] = flag; } if (!exist) { break; } layers.Add(new List <Tuple <int, int> >()); var layer = layers.Last <List <Tuple <int, int> > >(); for (int frame = 0; frame < frameCount; ++frame) { if (isAtTop[frame]) { layer.Add(new Tuple <int, int>(frame, top[frame])); ++top[frame]; } } } //Point[,] positions = new Point[permutation.FrameCount, permutation.CharacterCount]; //double[,] posY = new double[frameCount, characterCount]; int baseline = 0; int minY = int.MaxValue; int maxY = int.MinValue; for (int i = 0; i < layers.Count; ++i) { List <Tuple <int, int> > layer = layers[i]; int[] topY = new int[layer.Count]; int[] bottomY = new int[layer.Count]; int lastTopY = -100000; minY = int.MaxValue; maxY = int.MinValue; for (int j = 0; j < layer.Count; ++j) { int frame = layer[j].Item1; int k = layer[j].Item2; if (prev[frame][k] == -1) { topY[j] = 0; lastTopY = 0; } else { topY[j] = lastTopY - lcss[frame][k].Item2 + lcss[frame][k].Item1; lastTopY = topY[j]; } if (minY > topY[j]) { minY = topY[j]; } } for (int j = 0; j < layer.Count; ++j) { int frame = layer[j].Item1; int k = layer[j].Item2; topY[j] -= minY; bottomY[j] = topY[j] + intervals[frame][k].Length; for (int ii = 0; ii < intervals[frame][k].Length; ++ii) { int character = intervals[frame][k][ii]; posY[character, frame] = baseline + (topY[j] + ii) * (int)_app.Status.Config.Style.DefaultInnerGap; //positions[frame, character] = new Point(frame * styles.TimeScaleFactor, baseline + (topY[j] + ii) * styles.InnerDistance); if (maxY < posY[character, frame]) { maxY = (int)posY[character, frame]; } } } baseline = maxY + (int)_app.Status.Config.Style.OuterGap; } // new added, move down the hanging lines from bottom lay to top int[] topOfFrame = new int[story.TimeStamps.Length - 1]; for (int i = 0; i < topOfFrame.Length; ++i) { topOfFrame[i] = maxY; } for (int i = layers.Count - 1; i >= 0; --i) { List <Tuple <int, int> > layer = layers[i]; if (i != layers.Count - 1) // this is not the bottom layer { int minDepth = int.MaxValue; int BottomOfPiece = 0; int TopOfPieceGround = 0; List <Tuple <int, int> > stack = new List <Tuple <int, int> >(); for (int j = 0; j < layer.Count; ++j) { int frame = layer[j].Item1; int k = layer[j].Item2; int max = int.MinValue; for (int ii = 0; ii < intervals[frame][k].Length; ++ii) { int character = intervals[frame][k][ii]; if (max < posY[character, frame]) { max = posY[character, frame]; } } if (prev[frame][k] == -1) { BottomOfPiece = max; TopOfPieceGround = topOfFrame[frame]; stack.Clear(); stack.Add(new Tuple <int, int>(frame, k)); } else { if (BottomOfPiece < max) { BottomOfPiece = max; } if (TopOfPieceGround > topOfFrame[frame]) { TopOfPieceGround = topOfFrame[frame]; } stack.Add(new Tuple <int, int>(frame, k)); } if (next[frame][k] == -1) { if (TopOfPieceGround - BottomOfPiece > (int)_app.Status.Config.Style.OuterGap * 2 - 1) { // a large gap detected int delta = TopOfPieceGround - BottomOfPiece - (int)_app.Status.Config.Style.OuterGap; int up = 0; int down = 0; foreach (Tuple <int, int> tuple in stack) { int f = tuple.Item1; int kk = tuple.Item2; for (int jj = 0; jj < intervals[f][kk].Length; ++jj) { int ch = intervals[f][kk][jj]; if (f < frameCount - 1) { if (story.SessionTable[ch, f + 1] != -1) { if (posY[ch, f] > posY[ch, f + 1]) { ++up; } else if (posY[ch, f] < posY[ch, f + 1]) { ++down; } } } if (f > 0) { if (story.SessionTable[ch, f - 1] != -1) { if (posY[ch, f] > posY[ch, f - 1]) { ++up; } else if (posY[ch, f] < posY[ch, f - 1]) { ++down; } } } } } if (down >= up) { foreach (Tuple <int, int> tuple in stack) { int f = tuple.Item1; int kk = tuple.Item2; for (int ii = 0; ii < intervals[f][kk].Length; ++ii) { int character = intervals[f][kk][ii]; posY[character, f] += delta; } } } } } } } for (int j = 0; j < layer.Count; ++j) { int frame = layer[j].Item1; int k = layer[j].Item2; for (int ii = 0; ii < intervals[frame][k].Length; ++ii) { int character = intervals[frame][k][ii]; if (topOfFrame[frame] > posY[character, frame]) { topOfFrame[frame] = posY[character, frame]; } } } } // over } Debug.WriteLine("Crossing:{0}", Crossing.Count(story, posY)); return(posY.Clone <double>()); }
public void Optimize(Story story, PositionTable <double> position) { int count = 0; List <double> list = new List <double>(); int[,] index = new int[story.Characters.Count, story.FrameCount]; for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { index[i, frame] = count++; list.Add(position[i, frame]); } } } double[] X = list.ToArray <double>(); List <Tuple <int, int> > listInner = new List <Tuple <int, int> >(); List <Tuple <int, int> > listOuter = new List <Tuple <int, int> >(); for (int frame = 0; frame < story.FrameCount; ++frame) { List <Tuple <int, double> > l = new List <Tuple <int, double> >(); for (int i = 0; i < story.Characters.Count; ++i) { if (story.SessionTable[i, frame] != -1) { l.Add(new Tuple <int, double>(i, position[i, frame])); } } l.Sort((a, b) => a.Item2.CompareTo(b.Item2)); for (int k = 0; k < l.Count - 1; ++k) { int x = l[k].Item1; int y = l[k + 1].Item1; if (story.SessionTable[x, frame] == story.SessionTable[y, frame]) { listInner.Add(new Tuple <int, int>(index[x, frame], index[y, frame])); } else { listOuter.Add(new Tuple <int, int>(index[x, frame], index[y, frame])); } } } double[,] C = new double[listInner.Count + listOuter.Count, X.Length + 1]; int[] CT = new int[listInner.Count + listOuter.Count]; for (int i = 0; i < listInner.Count; ++i) { Tuple <int, int> pair = listInner[i]; int x = pair.Item1; int y = pair.Item2; C[i, x] = -1; C[i, y] = 1; C[i, X.Length] = 1.0; CT[i] = 0; } for (int i = 0; i < listOuter.Count; ++i) { int j = i + listInner.Count; Tuple <int, int> pair = listOuter[i]; int x = pair.Item1; int y = pair.Item2; C[j, x] = -1; C[j, y] = 1; C[j, X.Length] = 5.0; CT[j] = 1; } // optimization alglib.minbleicstate state; alglib.minbleicreport rep; double epsg = 0.01; double epsf = 0; double epsx = 0; int maxits = 0; alglib.minbleiccreate(X, out state); alglib.minbleicsetlc(state, C, CT); alglib.minbleicsetcond(state, epsg, epsf, epsx, maxits); Tuple <Story, PositionTable <double>, int[, ]> param = new Tuple <Story, PositionTable <double>, int[, ]>(story, position, index); alglib.minbleicoptimize(state, EnergyGrad, null, param); alglib.minbleicresults(state, out X, out rep); for (int i = 0; i < story.Characters.Count; ++i) { for (int frame = 0; frame < story.FrameCount; ++frame) { if (story.SessionTable[i, frame] != -1) { position[i, frame] = X[index[i, frame]]; } } } }
private void Sweep(Story story, ref PositionTable <int> ans, PositionTable <int> perm, bool forward, bool backward) { int frameCount = story.TimeStamps.Length - 1; int characterCount = story.Characters.Count; PositionTable <int> backup1 = null; PositionTable <int> backup2 = null; bool change = false; int loop = 0; do { change = false; if (forward) { // forward for (int frame = 1; frame < frameCount; ++frame) { Dictionary <int, List <int> > dict = new Dictionary <int, List <int> >(); for (int id = 0; id < characterCount; ++id) { if (story.SessionTable[id, frame] != -1) { if (!dict.ContainsKey(story.SessionTable[id, frame])) { dict.Add(story.SessionTable[id, frame], new List <int>()); } dict[story.SessionTable[id, frame]].Add(id); } } List <Tuple <int, double> > list = new List <Tuple <int, double> >(); foreach (KeyValuePair <int, List <int> > pair in dict) { int sum = 0; int count = 0; int sum_cur = 0; foreach (int x in pair.Value) { if (story.SessionTable[x, frame - 1] != -1) { sum += perm[x, frame - 1]; ++count; } else { } sum_cur += perm[x, frame]; } double average = (double)sum_cur / pair.Value.Count; if (count > 0) { average = (double)sum / count; } list.Add(new Tuple <int, double>(pair.Key, average)); } //list = Ultities.GetRandomList<Tuple<int, double>>(list); list.Sort((a, b) => a.Item2.CompareTo(b.Item2)); int baseline = 0; foreach (Tuple <int, double> tuple in list) { int group = tuple.Item1; List <int> items = dict[group]; items.Sort((a, b) => perm[a, frame - 1].CompareTo(perm[b, frame - 1])); foreach (int x in items) { perm[x, frame] = baseline++; } } } Update(story, ref ans, perm); if (backup1 == null || !backup1.Equals(perm)) { backup1 = perm.Clone <int>(); change = true; } } if (backward) { // backward for (int frame = frameCount - 2; frame >= 0; --frame) { Dictionary <int, List <int> > dict = new Dictionary <int, List <int> >(); for (int id = 0; id < characterCount; ++id) { if (story.SessionTable[id, frame] != -1) { if (!dict.ContainsKey(story.SessionTable[id, frame])) { dict.Add(story.SessionTable[id, frame], new List <int>()); } dict[story.SessionTable[id, frame]].Add(id); } } List <Tuple <int, double> > list = new List <Tuple <int, double> >(); foreach (KeyValuePair <int, List <int> > pair in dict) { int sum = 0; int count = 0; int sum_cur = 0; foreach (int x in pair.Value) { if (story.SessionTable[x, frame + 1] != -1) { sum += perm[x, frame + 1]; ++count; } else { } sum_cur += perm[x, frame]; } double average = (double)sum_cur / pair.Value.Count; if (count > 0) { average = (double)sum / count; } list.Add(new Tuple <int, double>(pair.Key, average)); } //list = Ultities.GetRandomList<Tuple<int, double>>(list); list.Sort((a, b) => a.Item2.CompareTo(b.Item2)); int baseline = 0; foreach (Tuple <int, double> tuple in list) { int group = tuple.Item1; List <int> items = dict[group]; items.Sort((a, b) => perm[a, frame + 1].CompareTo(perm[b, frame + 1])); foreach (int x in items) { perm[x, frame] = baseline++; } } } Update(story, ref ans, perm); if (backup2 == null || !backup2.Equals(perm)) { backup2 = perm.Clone <int>(); change = true; } } }while (change && loop++ < 100); }