public void Optimize(Story story, PositionTable <double> position)
 {
 }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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
                            {
                            }
                        }
                    }
                }
            }
        }
Beispiel #4
0
        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);
        }
Beispiel #6
0
        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
        }
Beispiel #7
0
 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]));
 }
Beispiel #8
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;
        }
Beispiel #9
0
        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);
        }
Beispiel #10
0
        //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);
            }
        }
Beispiel #11
0
        //
        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;
            }
        }
Beispiel #12
0
        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);
            }
        }
Beispiel #13
0
        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]);
                        }
                    }
                }
            }
        }
Beispiel #14
0
        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));
        }
Beispiel #15
0
        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));
        }
Beispiel #16
0
        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);
        }
Beispiel #17
0
        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);
        }
Beispiel #18
0
        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);
        }
Beispiel #19
0
        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);
        }
Beispiel #20
0
        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>());
        }
Beispiel #21
0
 public Constrainer(List <Tuple <int, int> > orders, Dictionary <int, Node> nodes, PositionTable <int> perm, int frame)
 {
     nodeDict = nodes;
     InitConstraints(orders, perm, frame);
     UpdateConstranedNodes();
 }
Beispiel #22
0
        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);
        }
Beispiel #23
0
        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]];
                    }
                }
            }
        }
Beispiel #24
0
 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);
        }
Beispiel #27
0
        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]];
                    }
                }
            }
        }
Beispiel #31
0
        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);
        }