Click here to Skip to main content
15,884,298 members
Articles / Programming Languages / C#

Reconstruction of Charts from Images

Rate me:
Please Sign up or sign in to vote.
4.92/5 (13 votes)
18 Mar 2010CPOL7 min read 37.9K   4.1K   42  
Usage of universal framework for chart reconstruction
using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;

using MathGraph;

namespace CategoryTheory
{
    /// <summary>
    /// DiagramLimit
    /// </summary>
    public class CategoryDiagram
    {

        /// <summary>
        /// Out of diagram test
        /// </summary>
        static public readonly string ObjectOutOfDiagram = "Diagram does not contains object";

        /// <summary>
        /// Extra object in diagram text
        /// </summary>
        static public readonly string ExtraArrow = "Extra object";

        /// <summary>
        /// Shortage of in diagram text
        /// </summary>
        static public readonly string ArrowsShortage = "Shortage of arrows in diagram";

        /// <summary>
        /// Graph
        /// </summary>
        private Digraph graph;

        /// <summary>
        /// Arrows hashtable
        /// </summary>
        private Dictionary<CategoryObjectPair, ICategoryArrow> arrows = new Dictionary<CategoryObjectPair, ICategoryArrow>();

        /// <summary>
        /// Objects
        /// </summary>
        private IList<ICategoryObject> objects = new List<ICategoryObject>();

        /// <summary>
        /// Sources
        /// </summary>
        private Dictionary<ICategoryObject, IList<ICategoryArrow>> sources = new Dictionary<ICategoryObject, IList<ICategoryArrow>>();

        /// <summary>
        /// Targets
        /// </summary>
        private Dictionary<ICategoryObject, IList<ICategoryArrow>> targets = new Dictionary<ICategoryObject, IList<ICategoryArrow>>();

        /// <summary>
        /// Category
        /// </summary>
        private ICategory category;

        /// <summary>
        /// Limit
        /// </summary>
        private ICategoryObject lim;

        /// <summary>
        /// Limit arrow
        /// </summary>
        private ICategoryArrow limArrow;

        /// <summary>
        /// Limit id arrows
        /// </summary>
        private IList<ICategoryArrow> limIdArrows;

        /// <summary>
        /// Limit function arrowa
        /// </summary>
        private List<ICategoryArrow> limFuncArrows;

        /// <summary>
        /// Lim id arrow
        /// </summary>
        private ICategoryArrow limIdArrow;

        /// <summary>
        /// Limit fuctional arrow
        /// </summary>
        private ICategoryArrow limFuncArrow;

        /// <summary>
        /// Limit arrows
        /// </summary>
        private Dictionary<ICategoryObject, ICategoryArrow> limArrows;

        /// <summary>
        /// Colimit
        /// </summary>
        private ICategoryObject colim;

        /// <summary>
        /// Colimit arrow
        /// </summary>
        private ICategoryArrow colimArrow;

        /// <summary>
        /// Colimit id arrows
        /// </summary>
        private Dictionary<ICategoryObject, ICategoryArrow> colimArrows;

        /// <summary>
        /// Colimit function arrowa
        /// </summary>
        private IList<ICategoryArrow> colimFuncArrows;

        /// <summary>
        /// Colim id arrow
        /// </summary>
        private ICategoryArrow colimIdArrow;

        /// <summary>
        /// Colimit fuctional arrow
        /// </summary>
        private ICategoryArrow colimFuncArrow;

        /// <summary>
        /// Coimit arrows
        /// </summary>
        private IList<ICategoryArrow> colimIdArrows;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="graph">Graph</param>
        /// <param name="category">Category</param>
        public CategoryDiagram(Digraph graph, ICategory category)
        {
            this.graph = graph;
            this.category = category;
            for (int i = 0; i < graph.Count; i++)
            {
                ICategoryObject o = graph[i].Object as ICategoryObject;
                CategoryObjectPair idPair = new CategoryObjectPair(o, o);
                ICategoryArrow id = o.Id;
                arrows[idPair] = id;
                objects.Add(o);
                IList<ICategoryArrow> s = new List<ICategoryArrow>();
                s.Add(id);
                sources[o] = s;
                IList<ICategoryArrow> t = new List<ICategoryArrow>();
                t.Add(id);
                targets[o] = t;
            }
            for (int i = 0; i < graph.Count; i++)
            {
                DigraphVertex o = graph[i];
                getPaths(o, o);
            }
        }

        /// <summary>
        /// Count of objects
        /// </summary>
        public int Count
        {
            get
            {
                return objects.Count;
            }
        }

        /// <summary>
        /// Digraph
        /// </summary>
        public Digraph Graph
        {
            get
            {
                return graph;
            }
        }

        /// <summary>
        /// Access to i th object
        /// </summary>
        public ICategoryObject this[int i]
        {
            get
            {
                return objects[i] as ICategoryObject;
            }
        }

        /// <summary>
        /// Access to arrow by pair
        /// </summary>
        public ICategoryArrow this[CategoryObjectPair p]
        {
            get
            {
                return arrows[p] as ICategoryArrow;
            }
        }

        /// <summary>
        /// Gets outcoming arrows
        /// </summary>
        /// <param name="o">The soutrce</param>
        /// <returns>List of outcoming arrows</returns>
        public IList<ICategoryArrow> GetOutcomingArrows(ICategoryObject o)
        {
            return sources[o];
        }

        /// <summary>
        /// Gets incoming arrows
        /// </summary>
        /// <param name="o">The target</param>
        /// <returns>List of outcoming arrows</returns>
        public IList<ICategoryArrow> GetIncomingArrows(ICategoryObject o)
        {
            return targets[o];
        }

        /// <summary>
        /// Keys of arrows table
        /// </summary>
        public ICollection Keys
        {
            get
            {
                return arrows.Keys;
            }
        }

        /// <summary>
        /// Gets arrow from limit to diagram object
        /// </summary>
        /// <param name="o">The diagram object</param>
        /// <returns>The arrow</returns>
        public ICategoryArrow GetLimArrow(ICategoryObject o)
        {
            return limArrows[o] as ICategoryArrow;
        }

        /// <summary>
        /// Limit
        /// </summary>
        public ICategoryObject Lim
        {
            get
            {
                if (lim == null)
                {
                    createLim();
                }
                return lim;
            }
        }

        /// <summary>
        /// Gets arrow to lim
        /// </summary>
        /// <param name="arrows">Arrows to objects</param>
        /// <returns>The arrow to lim</returns>
        public ICategoryArrow GetArrowToLim(ArrayList arrows)
        {
            Hashtable arrowsHash = new Hashtable();
            ICategoryObject source = null;
            foreach (ICategoryArrow arrow in arrows)
            {
                if (source == null)
                {
                    source = arrow.Source;
                }
                if (source != arrow.Source)
                {
                    throw new CategoryException(CategoryException.DifferentSources,
                        new ICategoryObject[] { source, arrow.Source });
                }
                if (!objects.Contains(arrow.Target))
                {
                    throw new CategoryException(ObjectOutOfDiagram, arrow.Target);
                }
                if (arrowsHash.ContainsKey(arrow.Target))
                {
                    throw new CategoryException(ExtraArrow, arrow);
                }
                arrowsHash[arrow.Target] = arrow;
            }
            foreach (object o in objects)
            {
                if (!arrowsHash.ContainsKey(o))
                {
                    throw new CategoryException(ArrowsShortage, o);
                }
            }
            foreach (CategoryObjectPair pair in Keys)
            {
                ICategoryArrow ar = this[pair];
                ICategoryArrow first = arrowsHash[pair.Source] as ICategoryArrow;
                ICategoryArrow second = arrowsHash[pair.Target] as ICategoryArrow;
                ICategoryArrow composition = ar.Compose(category, first);
                if (!composition.Equals(second))
                {
                    throw new CategoryException(CategoryException.NonCommutativePath, ar);
                }
            }
            Dictionary<int, ICategoryArrow> sortedTable = new Dictionary<int, ICategoryArrow>();
            foreach (ICategoryArrow ar in arrows)
            {
                int i = objects.IndexOf(ar.Target);
                sortedTable[i] = ar;
            }
            IList<ICategoryArrow> sortedArrows = new List<ICategoryArrow>();
            for (int i = 0; i < sortedTable.Count; i++)
            {
                sortedArrows.Add(sortedTable[i]);
            }
            IDirectProductCategory productCategory = category as IDirectProductCategory;
            ICategoryArrow arrowToProduct =
                productCategory.GetArrowToDirectProduct(source, limIdArrow.Source, sortedArrows);
            IEqualizerCategory equalizerCategory = category as IEqualizerCategory;
            ICategoryArrow res = equalizerCategory.GetArrowToEqualizer(limArrow,
                arrowToProduct, limIdArrow, limFuncArrow);
            return res;
        }

        /// <summary>
        /// Gets arrow from limit to diagram object
        /// </summary>
        /// <param name="o">The diagram object</param>
        /// <returns>The arrow</returns>
        public ICategoryArrow GetColimArrow(ICategoryObject o)
        {
            return colimArrows[o] as ICategoryArrow;
        }

        /// <summary>
        /// Limit
        /// </summary>
        public ICategoryObject Colim
        {
            get
            {
                if (colim == null)
                {
                    createColim();
                }
                return colim;
            }
        }

        /// <summary>
        /// Gets arrow from colim
        /// </summary>
        /// <param name="arrows">Arrows from objects</param>
        /// <returns>Arrow from colim</returns>
        public ICategoryArrow GetArrowFromColim(IList<ICategoryArrow> arrows)
        {
            Hashtable arrowsHash = new Hashtable();
            ICategoryObject target = null;
            foreach (ICategoryArrow arrow in arrows)
            {
                if (target == null)
                {
                    target = arrow.Target;
                }
                if (target != arrow.Target)
                {
                    throw new CategoryException(CategoryException.DifferentTargets,
                        new ICategoryObject[] { target, arrow.Target });
                }
                if (!objects.Contains(arrow.Source))
                {
                    throw new CategoryException(ObjectOutOfDiagram, arrow.Source);
                }
                if (arrowsHash.ContainsKey(arrow.Source))
                {
                    throw new CategoryException(ExtraArrow, arrow);
                }
                arrowsHash[arrow.Source] = arrow;
            }
            foreach (object o in objects)
            {
                if (!arrowsHash.ContainsKey(o))
                {
                    throw new CategoryException(ArrowsShortage, o);
                }
            }
            foreach (CategoryObjectPair pair in Keys)
            {
                ICategoryArrow ar = this[pair];
                ICategoryArrow first = arrowsHash[pair.Target] as ICategoryArrow;
                ICategoryArrow second = arrowsHash[pair.Source] as ICategoryArrow;
                ICategoryArrow composition = first.Compose(category, ar);
                if (!composition.Equals(second))
                {
                    throw new CategoryException(CategoryException.NonCommutativePath, ar);
                }
            }
            Dictionary<int, ICategoryArrow> sortedTable = new Dictionary<int, ICategoryArrow>();
            foreach (ICategoryArrow ar in arrows)
            {
                int i = objects.IndexOf(ar.Source);
                sortedTable[i] = ar;
            }
            IList<ICategoryArrow> sortedArrows = new List<ICategoryArrow>();
            for (int i = 0; i < sortedTable.Count; i++)
            {
                sortedArrows.Add(sortedTable[i]);
            }
            IDirectSumCategory sumCategory = category as IDirectSumCategory;
            ICategoryArrow arrowFromSum =
                sumCategory.GetArrowFromDirectSum(target, colimIdArrow.Target, sortedArrows);
            ICoequalizerCategory coequalizerCategory = category as ICoequalizerCategory;
            ICategoryArrow res = coequalizerCategory.GetArrowFromCoequalizer(colimArrow,
                arrowFromSum, colimIdArrow, colimFuncArrow);
            return res;
        }


        /// <summary>
        /// Creates limit
        /// </summary>
        private void createLim()
        {
            if (!(category is IDirectProductCategory))
            {
                throw new CategoryException(CategoryException.DirectProductNotSupported);
            }
            if (!(category is IEqualizerCategory))
            {
                throw new CategoryException(CategoryException.EqualizerNotSupported);
            }
            IDirectProductCategory productCategory = category as IDirectProductCategory;
            IList<ICategoryArrow> firstArrows = new List<ICategoryArrow>();
            ICategoryObject firstProduct = productCategory.GetDirectProduct(objects, firstArrows);
            IList<ICategoryObject> endObjects = new List<ICategoryObject>();
            foreach (CategoryObjectPair o in arrows.Keys)
            {
                ICategoryArrow a = arrows[o] as ICategoryArrow;
                endObjects.Add(a.Target);
            }
            IList<ICategoryArrow> secondArrows = new List<ICategoryArrow>();
            ICategoryObject secondProduct = productCategory.GetDirectProduct(endObjects, secondArrows);
            limIdArrows = new List<ICategoryArrow>();
            foreach (ICategoryArrow tar in secondArrows)
            {
                ICategoryObject t = tar.Target;
                foreach (ICategoryArrow proj in firstArrows)
                {
                    if (proj.Target == t)
                    {
                        limIdArrows.Add(proj);
                        break;
                    }
                }
            }
            limIdArrow = productCategory.GetArrowToDirectProduct(firstProduct, secondProduct, limIdArrows);
            limFuncArrows = new List<ICategoryArrow>();
            foreach (CategoryObjectPair o in arrows.Keys)
            {
                ICategoryArrow tar = this[o];
                foreach (ICategoryArrow proj in firstArrows)
                {
                    if (proj.Target == tar.Source)
                    {
                        ICategoryArrow ar = tar.Compose(category, proj);
                        limFuncArrows.Add(ar);
                        break;
                    }
                }
            }
            limFuncArrow = productCategory.GetArrowToDirectProduct(firstProduct, secondProduct, limFuncArrows);
            IEqualizerCategory equalizerCategory = category as IEqualizerCategory;
            limArrow = equalizerCategory.GetEqualizer(limIdArrow, limFuncArrow);
            lim = limArrow.Source;
            limArrows = new Dictionary<ICategoryObject, ICategoryArrow>();
            foreach (ICategoryArrow proj in firstArrows)
            {
                ICategoryObject t = proj.Target;
                ICategoryArrow ar = proj.Compose(category, limArrow);
                limArrows[t] = ar;
            }
        }


        /// <summary>
        /// Creates limit
        /// </summary>
        private void createColim()
        {
            if (!(category is IDirectSumCategory))
            {
                throw new CategoryException(CategoryException.DirectSumNotSupported);
            }
            if (!(category is IEqualizerCategory))
            {
                throw new CategoryException(CategoryException.CoequalizerNotSupported);
            }
            IDirectSumCategory sumCategory = category as IDirectSumCategory;
            IList<ICategoryArrow> firstArrows = new List<ICategoryArrow>();
            ICategoryObject firstSum = sumCategory.GetDirectSum(objects, firstArrows);
            IList<ICategoryObject> beginObjects = new List<ICategoryObject>();
            foreach (CategoryObjectPair o in arrows.Keys)
            {
                ICategoryArrow a = arrows[o];
                beginObjects.Add(a.Source);
            }
            IList<ICategoryArrow> secondArrows = new List<ICategoryArrow>();
            ICategoryObject secondSum = sumCategory.GetDirectSum(beginObjects, secondArrows);
            colimIdArrows = new List<ICategoryArrow>();
            foreach (ICategoryArrow sar in secondArrows)
            {
                ICategoryObject s = sar.Source;
                foreach (ICategoryArrow proj in firstArrows)
                {
                    if (proj.Source == s)
                    {
                        colimIdArrows.Add(proj);
                        break;
                    }
                }
            }
            colimIdArrow = sumCategory.GetArrowFromDirectSum(firstSum, secondSum, colimIdArrows);
            colimFuncArrows = new List<ICategoryArrow>();
            foreach (CategoryObjectPair o in arrows.Keys)
            {
                ICategoryArrow sar = this[o];
                foreach (ICategoryArrow proj in firstArrows)
                {
                    if (proj.Source == sar.Target)
                    {
                        ICategoryArrow ar = proj.Compose(category, sar);
                        colimFuncArrows.Add(ar);
                        break;
                    }
                }
            }
            colimFuncArrow = sumCategory.GetArrowFromDirectSum(firstSum, secondSum, colimFuncArrows);
            ICoequalizerCategory coequalizerCategory = category as ICoequalizerCategory;
            colimArrow = coequalizerCategory.GetCoequalizer(colimIdArrow, colimFuncArrow);
            colim = colimArrow.Target;
            colimArrows = new Dictionary<ICategoryObject, ICategoryArrow>();
            foreach (ICategoryArrow proj in firstArrows)
            {
                ICategoryObject s = proj.Source;
                ICategoryArrow ar = colimArrow.Compose(category, proj);
                colimArrows[s] = ar;
            }
        }


        /// <summary>
        /// Gets paths
        /// </summary>
        /// <param name="v">Root object</param>
        /// <param name="ob">Current object</param>
        private void getPaths(DigraphVertex v, DigraphVertex ob)
        {
            CategoryObjectPair pair = new CategoryObjectPair(v.Object as ICategoryObject,
                ob.Object as ICategoryObject);
            ICategoryArrow theArrow = this[pair];
            foreach (DigraphEdge edge in ob.OutcomingEdges)
            {
                DigraphVertex vo = edge.Target;
                ICategoryArrow ar = edge.Object as ICategoryArrow;
                CategoryObjectPair p = new CategoryObjectPair(v.Object as ICategoryObject, ar.Target);
                ICategoryArrow newArrow = ar.Compose(category, theArrow);
                if (arrows.ContainsKey(p))
                {
                    ICategoryArrow prev = this[p];
                    ICategoryArrow comp = ar.Compose(category, theArrow);
                    if (!prev.Equals(newArrow))
                    {
                        throw new CategoryException(CategoryException.NonCommutativePath);
                    }
                    continue;
                }
                arrows[p] = newArrow;
                IList<ICategoryArrow> s = sources[p.Source] as IList<ICategoryArrow>;
                s.Add(newArrow);
                IList<ICategoryArrow> t = targets[p.Target] as IList<ICategoryArrow>;
                t.Add(newArrow);
                getPaths(v, vo);
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Russian Federation Russian Federation
Ph. D. Petr Ivankov worked as scientific researcher at Russian Mission Control Centre since 1978 up to 2000. Now he is engaged by Aviation training simulators http://dinamika-avia.com/ . His additional interests are:

1) Noncommutative geometry

http://front.math.ucdavis.edu/author/P.Ivankov

2) Literary work (Russian only)

http://zhurnal.lib.ru/editors/3/3d_m/

3) Scientific articles
http://arxiv.org/find/all/1/au:+Ivankov_Petr/0/1/0/all/0/1

Comments and Discussions