using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
namespace CategoryTheory
{
/// <summary>
/// Standard category operations
/// </summary>
public class CategoryOperations
{
/// <summary>
/// Gets arrow to equalizer
/// </summary>
/// <param name="equalizer">The qualizer</param>
/// <param name="arrow">Arrow to object</param>
/// <returns>Arrow to equalizer</returns>
public static ICategoryArrow GetArrowToEqualizer(ICategoryArrow equalizer, ICategoryArrow arrow)
{
ICategoryObject s = arrow.Source;
ICategoryObject t = equalizer.Source;
ICategoryArrow[,] arrows = new ICategoryArrow[1, 3];
arrows[0, 0] = arrow;
arrows[0, 1] = arrow.Source.Id;
arrows[0, 2] = equalizer;
IDiagramRestoredObject r = s as IDiagramRestoredObject;
FindResults res;
return r.RestoreArrow(t, arrows, out res);
}
/// <summary>
/// Gets arrow to coequalizer
/// </summary>
/// <param name="coequalizer">The qualizer</param>
/// <param name="arrow">Arrow to object</param>
/// <returns>Arrow from equalizer</returns>
public static ICategoryArrow GetArrowFromCoequalizer(ICategoryArrow coequalizer, ICategoryArrow arrow)
{
ICategoryObject s = arrow.Target;
ICategoryObject t = coequalizer.Source;
ICategoryArrow[,] arrows = new ICategoryArrow[1, 3];
arrows[0, 0] = arrow;
arrows[0, 1] = coequalizer;
arrows[0, 2] = arrow.Source.Id;
IDiagramRestoredObject r = s as IDiagramRestoredObject;
FindResults res;
return r.RestoreArrow(s, arrows, out res);
}
/// <summary>
/// Gets colimit
/// </summary>
/// <param name="category">The category</param>
/// <param name="arrows">Diagram arrows</param>
/// <param name="coequalizer">Coequalizer</param>
/// <param name="objectArrows">Arrows to colimit</param>
/// <param name="productArrows">Sum arrows</param>
/// <returns>The colimit</returns>
public static ICategoryObject GetColim(ICategory category, IList<ICategoryArrow> arrows,
ref ICategoryArrow coequalizer, ref IList<ICategoryArrow> objectArrows, ref IList<ICategoryArrow> productArrows)
{
IList<ICategoryObject> objects = new List<ICategoryObject>();
IList<ICategoryObject> sources = new List<ICategoryObject>();
IDirectSumCategory direct = category as IDirectSumCategory;
ICoequalizerCategory coequ = category as ICoequalizerCategory;
foreach (ICategoryArrow arrow in arrows)
{
if (!objects.Contains(arrow.Source))
{
objects.Add(arrow.Source);
}
if (!objects.Contains(arrow.Target))
{
objects.Add(arrow.Source);
}
sources.Add(arrow.Source);
}
IList<ICategoryArrow> productSourceArrows = new List<ICategoryArrow>();
productArrows = new List<ICategoryArrow>();
ICategoryObject product = direct.GetDirectSum(objects, productArrows);
ICategoryObject productSource = direct.GetDirectSum(sources, productSourceArrows);
IList<ICategoryArrow> coequList = new List<ICategoryArrow>();
IList<ICategoryArrow> arrList = new List<ICategoryArrow>();
foreach (ICategoryArrow arr in productArrows)
{
ICategoryObject target = arr.Target;
foreach (ICategoryObject t in sources)
{
if (t == target)
{
arrList.Add(arr);
}
}
}
ICategoryArrow first = direct.GetArrowFromDirectSum(product, productSource, arrList);
foreach (ICategoryArrow arr in arrows)
{
int num = objects.IndexOf(arr.Target);
ICategoryArrow pr = productArrows[num] as ICategoryArrow;
ICategoryArrow eq = pr.Compose(category, arr);
coequList.Add(eq);
}
ICategoryArrow second = direct.GetArrowFromDirectSum(product, productSource, coequList);
coequalizer = coequ.GetCoequalizer(first, second);
objectArrows = new List<ICategoryArrow>();
foreach (ICategoryArrow arrow in productArrows)
{
ICategoryArrow arr = coequalizer.Compose(category, arrow);
objectArrows.Add(arr);
}
return coequalizer.Target;
}
/// <summary>
/// Composition with identical morphism
/// </summary>
/// <param name="first">First morphism</param>
/// <param name="second">Second morphism</param>
/// <returns>The composition</returns>
static public ICategoryArrow CompositionWithId(ICategoryArrow first, ICategoryArrow second)
{
if (first == first.Target.Id)
{
return second;
}
if (second == second.Source.Id)
{
return first;
}
return null;
}
/// <summary>
/// Gets interface of object
/// </summary>
/// <param name="obj">object</param>
/// <param name="interfaceName">Interface name</param>
/// <returns>The interface</returns>
static protected object GetInterface(IAssociatedObject obj, string interfaceName)
{
Type t = obj.GetType();
Type ti = t.GetInterface(interfaceName);
if (ti != null)
{
return obj;
}
if (obj is IChildrenObject)
{
IChildrenObject co = obj as IChildrenObject;
IAssociatedObject[] ch = co.Children;
if (ch != null)
{
foreach (IAssociatedObject ob in ch)
{
if (ob != null)
{
object o = GetInterface(ob, interfaceName);
if (o != null)
{
return o;
}
}
}
}
}
return null;
}
/// <summary>
/// Gets object of predefined type
/// </summary>
/// <typeparam name="T">The type</typeparam>
/// <param name="obj">The prototype</param>
/// <returns>The object of predefined type</returns>
public static T GetObject<T>(IAssociatedObject obj) where T : class
{
if (obj is T)
{
return obj as T;
}
if (obj is IChildrenObject)
{
IChildrenObject co = obj as IChildrenObject;
IAssociatedObject[] ch = co.Children;
if (ch != null)
{
foreach (IAssociatedObject ob in ch)
{
T a = GetObject<T>(ob);
if (a != null)
{
return a;
}
}
}
}
return null;
}
/// <summary>
/// Try to get object of predefined type
/// </summary>
/// <typeparam name="T">The type</typeparam>
/// <param name="obj">The prototype</param>
/// <param name="message">The exception message</param>
/// <returns>The object of predefined type</returns>
public static T GetObject<T>(IAssociatedObject obj, string message) where T : class
{
T a = GetObject<T>(obj);
if (a != null)
{
return a;
}
throw new Exception(message);
}
/// <summary>
/// Try to get source of the arrow
/// </summary>
/// <typeparam name="T">Source type</typeparam>
/// <param name="obj">The prototype</param>
/// <returns>The source</returns>
public static T GetSource<T>(IAssociatedObject obj) where T : class
{
return GetObject<T>(obj, CategoryException.IllegalSource);
}
/// <summary>
/// Try to get target of arrow
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj">Target type</param>
/// <returns>The target</returns>
public static T GetTarget<T>(IAssociatedObject obj) where T : class
{
return GetObject<T>(obj, CategoryException.IllegalTarget);
}
/// <summary>
/// Gets simple object
/// </summary>
/// <typeparam name="T">Type of object</typeparam>
/// <param name="o">Initial object</param>
/// <returns>The object</returns>
public static T GetSimpleObject<T>(object o) where T : class
{
if (o is T)
{
return o as T;
}
return null;
}
/// <summary>
/// Gets simple object
/// </summary>
/// <typeparam name="T">Type of object</typeparam>
/// <param name="o">Initial object</param>
/// <param name="message">Exception message</param>
/// <returns>The object</returns>
public static T GetSimpleObject<T>(object o, string message) where T : class
{
T t = GetSimpleObject<T>(o);
if (t != null)
{
return t;
}
throw new Exception(message);
}
/// <summary>
/// Sets associated object to object and all its children;
/// </summary>
/// <param name="ao">The associated object</param>
/// <param name="obj">The object to set</param>
static public void SetAssociatedObject(IAssociatedObject ao, object obj)
{
ao.Object = obj;
if (ao is IChildrenObject)
{
IChildrenObject co = ao as IChildrenObject;
IAssociatedObject[] ch = co.Children;
if (ch != null)
{
foreach (IAssociatedObject o in ch)
{
if (o != null)
{
SetAssociatedObject(o, obj);
}
}
}
}
}
}
}