// ----------------------------------------------------------------------------
//
//  Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ----------------------------------------------------------------------------

using System;
using System.Text;
using System.Collections;
using Microsoft.Contracts;

namespace DataStructs
{
    using System;
    using System.Text;
    using System.IO;
    using System.Collections;
    using System.Collections.Specialized;
    using System.Diagnostics;


    /// <summary>
    /// Represents an object that can be copied deeply, as opposed to the shallow ICloneable.
    /// </summary>
    public interface ICopyable
    {
        object! Copy();
    }

    public interface ISet : ICollection, ICopyable
    {
        /// <summary>
        /// Checks whether a given element is part of <c>this</c> set.
        /// </summary>
        /// <param name="elem">element searched into the set</param>
        /// <returns><c>true</c> if <c>elem</c> is in the set, <c>false</c> otherwise</returns>
        bool Contains(Object! o);

    }


    /// <summary>
    /// Interface for the set abstraction: collection of distinct elements.
    /// </summary>
    public interface IMutableSet: ISet, ICloneable
    {
        /// <summary>
        /// Adds an element to <c>this</c> set.
        /// </summary>
        /// <param name="elem">element to add</param>
        /// <returns><c>true</c> if <c>this</c> set was modified as a result of this operation</returns>
        /// 
        bool Add(Object! o);

        /// <summary>
        /// Removes an element from <c>this</c> set. 
        /// </summary>
        /// <param name="elem"></param>
        /// <returns><c>true</c> if <c>this</c> set was modified as a result of this operation</returns>
        bool Remove(Object! o);

        /// <summary>
        /// Adds several elements from <c>this</c> set.
        /// </summary>
        /// <param name="eable"><c>IEnumerable</c> that contains the elements to be added</param>
        /// <returns><c>true</c> if <c>this</c> set was modified as a result of this operation</returns>
        bool AddAll(IEnumerable! eable);

        /// <summary>
        /// Removes several elements from <c>this</c> set.
        /// </summary>
        /// <param name="eable"><c>IEnumerable</c> containing the elements to be removed</param>
        /// <returns><c>true</c> if <c>this</c> set was modified as a result of this operation</returns>
        bool RemoveAll(IEnumerable! eable);

        /// <summary>
        /// Deletes all the elements of <c>this</c> set. As a result the <c>Count</c> property will be <c>0</c>.
        /// </summary>
        /// <returns><c>true</c> if <c>this</c> set was modified as a result of this operation</returns>
        bool Clear();

    }

    public delegate IMutableSet! DSetFactory();
    public delegate IDictionary! DDictionaryFactory();

    /// <summary>
    /// Summary description for DataStructsUtil.
    /// </summary>
    public abstract class DataStructUtil
    {   
        public static readonly DSetFactory! DefaultSetFactory = new DSetFactory(default_set_factory);
        private static IMutableSet! default_set_factory()
        {
            return new HashSet(1);
        }


        public static readonly DSetFactory! SmallSetFactory = new DSetFactory(small_set_factory);
        private static IMutableSet! small_set_factory()
        {
            return new ArraySet(1);
        }


        public static readonly DDictionaryFactory! DefaultDictionaryFactory = new DDictionaryFactory(default_dict_factory);
        private static IDictionary! default_dict_factory()
        {
            return new Hashtable(1);
        }
        

        public static readonly DDictionaryFactory! SmallDictionaryFactory = new DDictionaryFactory(small_dict_factory);
        private static IDictionary! small_dict_factory()
        {
            return new ListDictionary();
        }
        

        public static ISet! EMPTY_SET = new ImmutableSetWrapper(new HashSet());

        public static ISet singleton(object! elem)
        {
            return new SingletonSet(elem);
        }


        public static IList SortedCollection(ICollection! coll)
        {
            return SortedCollection(coll, null);
        }

        public static IList SortedCollection(ICollection! coll,  IComparer comp)
        {
            ArrayList al = new ArrayList(coll);
            if (comp == null)
                al.Sort();
            else
                al.Sort(comp);
            return al;
        }

        /// <summary>
        /// Produces a string representation of an <c>IEnumerable</c> object,
        /// using <c>o2s</c> to produce the string representation of each
        /// element.
        /// </summary>
        /// <param name="eable"></param>
        /// <param name="o2s"></param>
        /// <returns></returns>
        /// 
        public static string! IEnum2String(IEnumerable! eable,  DObj2String o2s)
        {
            StringBuilder buff = new StringBuilder();
            buff.Append("[");
            bool first = true;
            foreach (object o in eable) {
                if (first) first = false;
                else buff.Append(",");
                if (o2s != null)
                    buff.Append(o2s(o));
                else
                    buff.Append(o);
            }
            buff.Append("]");
            return buff.ToString();
        }


    }

    /// <summary>
    /// Conversion object -> string. Useful for classes for which we cannot
    /// modify / override the <c>ToString</c> method. A <c>null</c> value
    /// should be interpreted as the classic <c>ToString</c> method.
    /// </summary>
    public delegate string DObj2String(object obj);

    internal class SingletonSet: ISet
    {
        private object! elem;

        public SingletonSet(object! elem)
        {
            this.elem = elem;
        }

        public bool Contains(object! elem)
        {
            return this.elem.Equals(elem);
        }

        public int Count { 
            [Pure]
            get { return 1; } }

        public override int GetHashCode()
        {
            return elem.GetHashCode();
        }

        public IEnumerator GetEnumerator()
        {
            return new SingletonEnumerator(elem);
        }

        private class SingletonEnumerator: IEnumerator
        {
            private object elem;
            private int index = -1;

            [NotDelayed]
            public SingletonEnumerator(object elem)
            {
                this.elem = elem;
                Reset();
            }

            public virtual object Current
            {
                get 
                {
                    if (index == 0) return elem;
                    else
                        throw new InvalidOperationException();
                }
            }

            public virtual bool MoveNext()
            {
                switch (index) {
                    case -1:
                        index++;
                        return true;
                    case 0:
                        index++;
                        return false;
                    case 1:
                    default:
                        return false;
                }
            }

            public virtual void Reset()
            {
                index = -1;
            }
        }

        public object! Copy()
        {
            SingletonSet copy = (SingletonSet) this.MemberwiseClone();
            assert(copy != null);
            copy.elem = (this.elem is ICopyable) ? ((ICopyable) this.elem).Copy() : this.elem;
            return copy;
        }

        void ICollection.CopyTo (Array! target, int index) 
        {
            assume(target != null);
            target.SetValue(this.elem, index);
        }

        object! ICollection.SyncRoot
        {
            [Pure]
            get 
            {
                return this;
            }
        }

        bool ICollection.IsSynchronized 
        {
            [Pure]
            get { return false; }
        }
    }
    
    
    
    public class OneToManyMap/*<KEY,ELEM>*/ : Hashtable//<KEY,ArrayList<ELEM>>  
    {
        public override void Add (Object! key, Object newItem)
        {
            ArrayList items = base[key] as ArrayList;
            if (items == null) {
                items = new ArrayList();
                base[key] = items;
            }
            items.Add(newItem);
        }


        public virtual bool Contains (Object! key, Object item)
        {
            ArrayList items = base[key] as ArrayList;
            if (items == null)
                return false;
            return items.Contains(item);
        }


        public new ArrayList/*<Object>*/ this [Object! key] 
        {
            get { return base[key] as ArrayList; }
            set { base[key] = value; }
        }

    }



    public class DoubleTable/*<KEY1,KEY2,ELEM>*/ : Hashtable//<KEY1,Hashtable<KEY2,ELEM>>  
    {
        public DoubleTable () : base() { }

        private DoubleTable (Hashtable table) : base(table) { }


        public new Hashtable this [object! key]
        {
            get 
            {
                return base[key] as Hashtable;
                //
                //  if (table == null) {
                //      table = new Hashtable();
                //      base[key] = table;
                //  }
                //  return table;
                //    
            }

            set
            {
                base[key] = value;
            }
        }


        public void Insert (object! key1, object! key2, object element)
        {
            Hashtable table = this[key1];
            if (table == null) {
                table = new Hashtable();
                this[key1] = table;
            }
            table[key2] = element;
        }


        
        public object Lookup (object! key1, object! key2) 
        {
            Hashtable range = this[key1];
            if (range != null) {
                return range[key2];
            }
            else {
                return null;
            }
        }
        
        public override object! Clone ()
        {
            // careful. We have to deep clone the targets of the underlying hashtable.
            DoubleTable copy = new DoubleTable();
            foreach (object key in (IEnumerable!)this.Keys) {
                Hashtable x = this[key];

                assert(x != null);
                copy.Add(key, x.Clone());
            }
            return copy;
        }

        public DoubleTable Copy() 
        {
            return (DoubleTable)this.Clone();
        }
    }


    
    
    /// <summary>
    /// An attempt to make coding with datatypes more pleasant in C#
    /// </summary>
    /// <remarks>
    /// Use <c>Datatype</c> as a base class on each of your abstract data type base classes. When doing
    /// case analysis on such a value, use the method <c>Tag</c> to get a String representation of the 
    /// dynamic class name. This can be matched in the <c>case</c> branches of a switch. 
    /// <p>
    /// For pairwise matching, use <c>x.Tag + y.Tag</c> and <c>case "Foo"+"Bar"</c>.</p>
    /// <p>
    /// Can be extended to compute the set of tags of each abstract datatype instance and utility methods.</p>
    /// </remarks>
    public abstract class Datatype 
    {
        private int tag;

        private static Hashtable!/*<Type,DatatypeInfo>*/ typeTable = new Hashtable();

        private class DatatypeInfo 
        {
            IList!/*<Type>*/ members;
            Type abstractBaseType;
            public DatatypeInfo(Type abstractBaseType) 
            {
                members = new ArrayList();
                this.abstractBaseType = abstractBaseType;
            }

            public void Add(Type variant) 
            {
                members.Add(variant);
            }

            public ICollection! Members { get { return members; } }
        }

        
        private void AddToTable (Type! variant) 
        {
            DatatypeInfo info = GetBaseInfo(variant);
            info.Add(variant);
            typeTable[variant] = info;
        }

        
        private DatatypeInfo! GetBaseInfo (Type! variant) 
        {
            Type abase = FindBase(variant);
            DatatypeInfo info = (DatatypeInfo)Datatype.typeTable[abase];
            if (info == null) {
                // first time we see anything in this class tree.
                info = new DatatypeInfo(abase);
                Datatype.typeTable[abase] = info;
            }
            return info;
        }

        
        private Type! FindBase(Type! variant) 
        {
            Type abase = variant.BaseType;
            assume(abase != null);
            if (abase.IsAbstract) {

                // check that it is not datatype
                if (abase == typeof(Datatype)) {
                    Debug.Assert(false, "Every datatype should have an abstract base class that is a subtype of Datatype: " + variant.Name + " does not.");
                }

                // check if its base is Datatype
                if (abase.BaseType == typeof(Datatype)) {
                    return abase;
                }
                else {
                    // intermediate abstract base
                    return FindBase(abase);
                }
            }
            // recurse until we find abstract base
            return FindBase(abase);
        }

        [NotDelayed]
        protected Datatype (int tag) 
        {
            Type realType = this.GetType();
            assume(realType != null);
            this.tag = tag; //realType.Name;
            if (typeTable[realType] == null) {
                // add this first instance to the type table
                this.AddToTable(realType);
            }
        }

        public virtual int Tag
        {
            get { return tag; }
        }

        public void IncompleteMatch() 
        {
            Type realType = this.GetType();
            assume(realType != null);
            DatatypeInfo info = (DatatypeInfo)Datatype.typeTable[realType];

            assert(info != null);

            System.Text.StringBuilder buffer = new StringBuilder();
            foreach (object member in info.Members) {
                Type m = member as Type;

                assert(m != null);

                buffer.Append(" ");
                buffer.Append(m.Name);
            }

            Console.Write("Incomplete match: {0} was not matched.\nDatatype contains the following variants {1}\n",
                this.Tag, buffer.ToString());
            Debug.Assert(false, "incomplete match");
        }
    }

    public class ConvertingEnumerable : IEnumerator, IEnumerable
    {
        public delegate object ObjectConverter(object o);

        private IEnumerator! underlying;
        private ObjectConverter! objConverter;

        [NotDelayed]
        public ConvertingEnumerable(IEnumerable! underlying, ObjectConverter! objConverter)
        {
            this.underlying = underlying.GetEnumerator();
            this.objConverter = objConverter;
            base();
            Reset();
        }

        public object Current
        {
            get 
            {
                return objConverter(underlying.Current);
            }
        }

        public bool MoveNext()
        {
            return underlying.MoveNext();
        }

        public void Reset()
        {
            underlying.Reset();
        }

        public IEnumerator GetEnumerator()
        {
            return this;
        }
    }

}

namespace DataStructs
{
    using System;
    using System.Text;
    using System.Collections;



    public abstract class Set
    {
        public static ISet Difference(IEnumerable! a, ISet! b)
        {
            IMutableSet diff = new HashSet();
            foreach (object elem in a)
                if(!b.Contains(elem))
                    diff.Add(elem);
            return diff;
        }


        public static ISet Union(ISet! a, ISet! b)
        {
            IMutableSet union = new HashSet(a);
            union.AddAll(b);
            return union;
        }


        public static ISet Intersect(ISet! a, ISet! b) 
        {
            IMutableSet inter = new HashSet();

            if (a.Count < b.Count) {
                ISet c = a;
                a = b;
                b = c;
            }
            foreach (object elem in a) {
                if (b.Contains(elem)) {
                    inter.Add(elem);
                }
            }   
            return inter;
        }

        
        /// <summary>
        /// Returns null if A included in B. Otherwise, returns an element in
        /// A that is not in B.
        /// </summary>
        
        public static object NonSubsetWitness(ISet! a, ISet! b)
        {
            foreach (object elem in a) {
                if (!b.Contains(elem)) {
                    return elem;
                }
            }
            return null;
        }


        public delegate bool SetFilter(object! obj);

        public static ISet Filter(ISet! a, SetFilter! filter) 
        {
            IMutableSet inter = new HashSet();

            foreach (object elem in a) {
                if (filter(elem)) {
                    inter.Add(elem);
                }
            }   
            return inter;
        }


        public static readonly ISet Empty = new ArraySet(0);
    }



    public abstract class AbstrSet: IMutableSet
    {
        public abstract bool Add(object! elem);
        public virtual bool AddAll(IEnumerable! eable) 
        {
            bool modified = false;
            foreach (object elem in eable)
                if(Add(elem)) modified = true;
            return modified;
        }

        public abstract bool Remove(object! elem);

        public virtual bool RemoveAll(IEnumerable! eable)
        {   
            ISet iset = eable as ISet;
            if ((iset != null) && (iset.Count > 2 * this.Count)) {
                // optimized code for the special case when eable is a large ISet
                ArrayList to_remove = new ArrayList();
                foreach (object elem in this)
                    if(iset.Contains(elem))
                        to_remove.Add(elem);
                if (to_remove.Count != 0) {
                    foreach (object elem in to_remove)
                        this.Remove(elem);
                    return true;
                }
                return false;
            }
            
            bool modified = false;
            foreach (object elem in eable)
                if(Remove(elem)) modified = true;
            return modified;
        }           


        public abstract bool Contains(object! elem);
        public abstract bool Clear();
        public abstract int Count { get; }


        public abstract IEnumerator GetEnumerator();

        public virtual void CopyTo(Array! array, int index) 
        {
            foreach (object o in this) 
                array.SetValue(o, index++);
        }


        void ICollection.CopyTo(Array! a, int index) { 
            Array! b = a;
            this.CopyTo(b, index);
        }



        [Confined]
        public override string! ToString()
        {
            return DataStructUtil.IEnum2String(this, null);
        }

        public override int GetHashCode()
        {
            throw new InvalidOperationException("GetHashCode is unimplemented");
        }

        [Confined]
        public override bool Equals(object o)
        {
            ISet iset2 = o as ISet;
            // if o is not an ISet, is a set with a different number of
            // elements, obviously o != this 
            if ((iset2 == null) ||
                (iset2.Count != this.Count))
                return false;
            foreach (object elem in this)
                if(!iset2.Contains(elem))
                    return false;
            return true;
        }

        public virtual bool IsSynchronized { get { return false; } }
        
        public virtual object! SyncRoot {  [Pure] get { return this; } }

        public abstract object! Clone();

        object ICloneable.Clone() { 
            return this.Clone();
        }

        public abstract object! Copy();
    }



    public class ArraySet : AbstrSet
    {
        public ArraySet(int initial_size)
        {
            array = new object[initial_size];
        }

        public ArraySet(object singleton) 
        {
            array = new object[] {singleton};
            count = 1;
        }

        public ArraySet() : this(5) { }

        private object[]! array;
        private int count = 0;

        public override bool Add(object! elem)
        {
            assert(elem != null);

            for (int i = 0; i < count; i++)
                if(elem.Equals(array[i]))
                    return false;
            if (count == array.Length) {
                object[] array2 = new object[count*2];
                for (int i = 0; i < count; i++)
                    array2[i] = array[i];
                array = array2;
            }
            array[count++] = elem;
            return true;
        }

        public override bool Remove(object! elem)
        {
            assert(elem != null);

            for (int i = 0; i < count; i++)
                if(elem.Equals(array[i]))
                {
                    if (i < count - 1)
                        array[i] = array[count-1];
                    // no memory leaks
                    array[count-1] = null;
                    count--;
                    return true;
                }
            return false;
        }

        public override bool Contains(object! elem)
        {
            assert(elem != null);

            for (int i = 0; i < count; i++)
                if(elem.Equals(array[i]))
                    return true;
            return false;
        }

        public override bool Clear()
        {
            bool result = count > 0;
            count = 0;
            return result;
        }

        public override int Count { get { return count; } }

        public override IEnumerator GetEnumerator()
        {
            return new ArrayEnumerator(array, count);
        }

        public override object! Clone()
        {
            ArraySet set2 = (ArraySet) this.MemberwiseClone();
            assume(set2 != null);
            set2.array = (object[]) this.array.Clone();
            return set2;
        }

        public override object! Copy()
        {
            ArraySet set2 = (ArraySet) this.MemberwiseClone();
            assume(set2 != null);

            set2.array = (object[]) this.array.Clone();
            for (int i = 0; i < set2.count; i++) {
                ICopyable elem = set2.array[i] as ICopyable;
                if (elem != null)
                    set2.array[i] = elem.Copy();
            }
            return set2;
        }

    }



    public class ImmutableSetWrapper: IMutableSet
    {
        private ISet! real_set;

        public ImmutableSetWrapper(ISet! s)
        {
            real_set = s;
        }

        public bool Add(object! key)
        {
            throw new ModifyImmutableCollException();
        }

        
        public bool AddAll(IEnumerable! keys)
        {
            throw new ModifyImmutableCollException();
        }


        public bool Remove(object! key)
        {
            throw new ModifyImmutableCollException();
        }


        public bool RemoveAll(IEnumerable! keys)
        {
            throw new ModifyImmutableCollException();
        }


        public bool Clear()
        {
            throw new ModifyImmutableCollException();
        }
        

        public object Clone()
        {
            // memberwise clone is enough because no destructive operations
            // are allowed on this kind of objects.
            return this.MemberwiseClone();
        }

        public bool Contains(object! key)
        {
            return real_set.Contains(key);
        }

        public IEnumerator GetEnumerator()
        {
            return real_set.GetEnumerator();
        }

        public override int GetHashCode()
        {
            return real_set.GetHashCode();
        }

        public int Count { 
            [Pure]
            get { return real_set.Count; } }

        void ICollection.CopyTo(Array! target, int index) 
        {
            this.real_set.CopyTo(target, index);
        }

        bool ICollection.IsSynchronized 
        {
            [Pure]
            get { return this.real_set.IsSynchronized; }
        }

        object! ICollection.SyncRoot 
        {
            [Pure]
            get { return this.real_set.SyncRoot; }
        }

        public object! Copy()
        {
            ImmutableSetWrapper copy = (ImmutableSetWrapper) this.MemberwiseClone();
            assume(copy != null);

            // ISet implements ICopyable so we always do a deep copy of real_set
            copy.real_set = (ISet) this.real_set.Copy();
            return copy;
        }


    }


    public class ModifyImmutableCollException: SystemException
    {
        public ModifyImmutableCollException():
            base("Attempt to modify an immutable collection") {}
    }



    /// <summary>
    /// Full implementation of the <c>ISet</c> interface, backed by a <c>Hashtable</c>.
    /// </summary>
    /// <remarks>
    /// As each <c>HashSet</c> is backed by a
    /// <see cref="System.Collections.Hashtable">Hashtable</see>, all requirements that
    /// apply for the <c>Hashtable</c> keys apply for the elements of a <c>HashSet</c>
    /// as well.
    ///
    /// <p>The <c>HashSet</c> class overrides the methods
    /// <see cref="GetHashCode">GetHashCode</see> and <see cref="Equals">Equals</see>
    /// (inherited from <see cref="System.Object">Object</see>) in order to provide
    /// structural equality:
    /// two sets are equal iff they contain the same elements (where the semantics of "same"
    /// is defined by the <c>Equals</c> method of those objects).  You can put HashSets into
    /// HashSets; however, to avoid infinite loops, you should never insert a <c>HashSet</c>
    /// into itself.
    /// The hashcode of a <c>HashSet</c> is defined as the "xor" of the hashcodes of the set
    /// elements. </p>
    /// 
    /// <p>
    /// The <c>GetHashCode</c> function of a <c>HashSet</c> executes in <c>O(1)</c> time:
    /// the hashcode is dynamically updated after each operation that modifies the set.
    /// If the hashcode functions used for all the other involved objects is good and
    /// is computed in <c>O(1)</c> time, one element addition and removal execute in
    /// <c>O(1)</c> time; <c>Equals</c> works in time linear to the number of elements of
    /// <c>this</c> set.
    /// </p> 
    /// </remarks>
    public class HashSet: AbstrSet
    {
        // the Hashtable that backs up the implementation of this HashSet
        // an element is in the set if it's a key in the Hashtable
        protected Hashtable! hash;

        private Hashtable! Hash { get { return this.hash; } }

        // all keys are associated with the bogus value VALUE
        protected static object VALUE = new object();

        /// <summary>
        /// Constructs an empty <c>HashSet</c>.
        /// </summary>
        public HashSet() : this(0)
        {
        }

        public HashSet(int initialsize)
        {
            if (initialsize != 0) {
                hash = new Hashtable(initialsize);
            }
            else {
                hash = new Hashtable();
            }
            set_hash_code = 0;
            base();
        }

        
        /// <summary>
        /// Constructs a <c>HashSet</c> initialized to contain all
        /// elements from an <c>IEnumerable</c>.
        /// </summary>
        public HashSet(IEnumerable! eable) : this()
        {
            AddAll(eable);
        }

        public override bool Contains(object! elem)
        {
            return hash.ContainsKey(elem);
        }

        public override bool Add(object! elem) 
        {
            if (elem == null)
                throw new ApplicationException("null set element");

            // element already present in the set
            if (hash.ContainsKey(elem)) return false;
            // new element!
            hash[elem] = VALUE;
            set_hash_code ^= elem.GetHashCode();
            return true;
        }

        public override bool Remove(object! elem)
        {
            assert(elem != null);

            if (!hash.ContainsKey(elem)) return false;
            hash.Remove(elem);
            // a^b^b = a; we eliminate the influence of "elem" on the
            // hash code for the entire set
            set_hash_code ^= elem.GetHashCode();
            return true;
        }

        public override bool Clear()
        {
            set_hash_code = 0;
            bool result = (this.Count != 0);
            hash.Clear();
            return result;
        }

        public override int Count { get { return hash.Count; } }

        protected class HashSetEnumerator: IEnumerator 
        {
            HashSet! hash_set;
            IEnumerator! hash_e;

            public HashSetEnumerator(HashSet! hash_set) 
            {
                this.hash_set  = hash_set;
                this.hash_e    = hash_set.Hash.GetEnumerator();
                base();
            }
            
            public object Current
            {
                get
                {
                    DictionaryEntry de = (DictionaryEntry)hash_e.Current;
                    return de.Key;
                }
            }

            public bool MoveNext() 
            {
                return hash_e.MoveNext();
            }

            public void Reset() 
            {
                hash_e.Reset();
            }
        }


        
        public override IEnumerator GetEnumerator() 
        {
            return new HashSetEnumerator(this);
        }
        
        public override int GetHashCode()
        {
            return set_hash_code;
        }
        // hash_code of this set; dynamically maintained after each
        // operation on this set
        protected int set_hash_code;

        // Copy constructor
        private HashSet(HashSet! old, bool deep) : this(old.Count) {
            foreach (object elem in old) {
                if (deep) { 
                    this.Add(elem);
                }
                else {
                    this.Add((elem is ICopyable) ? ((ICopyable) elem).Copy() : elem);
                }
            }
        }

        public override object! Clone()
        {
            return new HashSet(this, false);
        }

        public override object! Copy()
        {
            return new HashSet(this, true);
        }
    }
}

namespace DataStructs
{

    public interface IRelation 
    {
        bool ContainsKey(object! key);

        bool Contains(object! key, object! value);

        ICollection! GetKeys();

        ISet! GetValues(object! key);

        IRelation! Reverse();
    }


    public interface IMutableRelation : IRelation, ICloneable, ICopyable
    {
        bool Add(object! key, object! value);

        bool AddAll(object! key, IEnumerable! values);

        /// <summary>
        /// Adds an entire relation to <d>this</d> relation.
        /// </summary>
        /// <param name="relation">Relation that is unioned with this relation.</param>
        /// <returns><c>true</c> iff <c>this</c> relation changed.</returns>
        bool AddRelation(IRelation! relation);

        bool Remove(object! key, object! value);
        bool RemoveAll(object! key, IEnumerable! values);

        bool RemoveKey(object! key);
        bool RemoveSeveralKeys(IEnumerable! keys); 

        bool RemoveSeveralValues(IEnumerable! values);

        new
        IMutableRelation! Reverse();

    }


    /// <summary>
    /// Full <c>IMutableRelation</c> implementation.
    /// </summary>
    public class Relation: IMutableRelation
    {
        /// <summary>
        /// Full power relation constructor that allows you to finely tune the memory consumption.
        /// Internally, a relation is a dictionary that assigns to each key the set of values that are
        /// in relation with it.  This constructor allows you to specify the dictionary and the set
        /// factory.
        /// </summary>
        /// <param name="dict_fact">Dictionary factory used to construct the underlying dictionary.</param>
        /// <param name="set_fact">Set factory used to construct the set that will store the values
        /// assoctiated with each key.</param>
        public Relation(DDictionaryFactory! dict_fact, DSetFactory! set_fact)
        {
            this.dict_fact = dict_fact;
            this.set_fact  = set_fact;
            this.hash = dict_fact();
            base();
        }

        /// <summary>
        /// Default constructor.  Uses the default factory for dictionaries (i.e., equiv. to new Hashtable())
        /// and sets (i.e., equiv. to new HashSet()).
        /// </summary>
        public Relation() :
            this(DataStructUtil.DefaultDictionaryFactory, DataStructUtil.DefaultSetFactory) {}

        private readonly DDictionaryFactory! dict_fact;
        private readonly DSetFactory!        set_fact;

        // underlying structure that stores the information attached with this relation
        private IDictionary! hash/*<object, ISet<object>>*/;

        public virtual bool Add(object! key, object! value)
        {
            return get_set_for_add(key).Add(value);
        }

        public virtual bool AddAll(object! key, IEnumerable! values)
        {
            return get_set_for_add(key).AddAll(values);
        }

        public virtual bool AddRelation(IRelation! relation)
        {
            if (relation == null) return false;
            bool changed = false;
            foreach (object key in relation.GetKeys())
                if(this.AddAll(key, relation.GetValues(key)))
                    changed = true;
            return changed;
        }

        private IMutableSet! get_set_for_add(object! key)
        {
            IMutableSet s = (IMutableSet) hash[key];
            if (s == null) {
                s = set_fact();
                hash[key] = s;
            }
            return s;
        }

        public virtual ISet! GetValues(object! key)
        {
            ISet s = (ISet) hash[key];
            if (s == null)
                s = DataStructUtil.EMPTY_SET;
            else
                s = new ImmutableSetWrapper(s);
            return s;
        }

        public virtual bool ContainsKey(object! key)
        {
            return hash.Contains(key);
        }

        public virtual bool Contains(object! key, object! value)
        {
            return ((ISet) GetValues(key)).Contains(value);
        }

        public virtual bool Remove(object! key, object! value)
        {
            IMutableSet s = (IMutableSet) hash[key];
            if (s == null)
                return false;

            bool result = s.Remove(value);
            if (s.Count == 0)
                hash.Remove(key);

            return result;
        }

        public virtual bool RemoveAll(object! key, IEnumerable! values)
        {
            IMutableSet s = (IMutableSet) hash[key];
            if (s == null)
                return false;

            bool result = s.RemoveAll(values);
            if (s.Count == 0)
                hash.Remove(key);

            return result;
        }


        public virtual bool RemoveKey(object! key)
        {
            if (hash.Contains(key)) {
                hash.Remove(key);
                return true;
            }
            return false;
        }

        public virtual bool RemoveSeveralKeys(IEnumerable! keys)
        {
            ISet iset_keys = keys as ISet;
            if (iset_keys != null) {
                ICollection keys_of_this = this.GetKeys();
                if (iset_keys.Count > 2 * keys_of_this.Count) {
                    // optimized code for the special case when "keys" is a large ISet
                    // UGLY code! comodif. + IEnumerator has no remove method
                    ArrayList to_remove = new ArrayList();
                    foreach (object key in keys_of_this)
                        // set membership is O(1) :)
                        if (iset_keys.Contains(key))
                            to_remove.Add(key);
                    if (to_remove.Count > 0) {
                        foreach (object key in to_remove)
                            hash.Remove(key);
                        return true;
                    }
                    return false;
                }

            }

            bool modified = false;
            foreach (object key in keys)
                if(hash.Contains(key))
                {
                    hash.Remove(key);
                    modified = true;
                }
            return modified;
        }


        public virtual bool RemoveSeveralValues(IEnumerable! values)
        {
            bool modified = false;

            // the following code is inneficient ... this is due to:
            // 1. the need to avoid Comodification exceptions
            // 2. the lack of a remove method in IEnumerator()
            ArrayList keys = new ArrayList(GetKeys());
            foreach (object key in keys) {
                IMutableSet s = (IMutableSet) hash[key];
                assert(s != null);
                if (s.RemoveAll(values)) {
                    modified = true;
                    if (s.Count == 0)
                        hash.Remove(key);
                }
            }

            return modified;
        }

        
        public virtual ICollection! GetKeys()
        {
            return (ICollection!)hash.Keys;
        }

        public virtual IMutableRelation! Reverse()
        {
            IMutableRelation reverse = new Relation();
            foreach (object key in GetKeys())
                foreach(object value in GetValues(key))
                    reverse.Add(value, key);
            return reverse;
        }

        IRelation! IRelation.Reverse() 
        {
            return this.Reverse();
        }

        /// Copy constructor
        private Relation(Relation! old, bool deep) : this(old.dict_fact, old.set_fact)
        {
            foreach (object key in old.GetKeys()) {
                // deep copy of the key, if requested && possible
                object key2 = (deep && key is ICopyable) ? ((ICopyable) key).Copy() : key;
                foreach (object val in old.GetValues(key)) {
                    // deep copy of the value, if requested && possible
                    object val2 = (deep && val is ICopyable) ? ((ICopyable) val).Copy() : val;
                    this.Add(key2, val2);
                }
            }
        }

        /// <summary>
        /// "Shallow" copy of a relation.  Produces an independent copy of <c>this</c> <c>Relation</c>.
        /// The keys and values are not duplicated.  Operations on the
        /// resulting <c>Relation</c> and on <c>this</c> <c>Relation</c> don't interact.
        /// </summary>
        /// <returns>An independent copy of <c>this</c> Relation.</returns>
        public virtual object Clone()
        {
            return new Relation(this, false);
        }

        /// <summary>
        /// Deep copy of a relation.  Produces an independent copy of <c>this</c> <c>Relation</c>,
        /// in which even the keys and values are duplicated (using deep copy) if they implement
        /// the ICopyable interface.  Operations on the resulting <c>Relation</c> and on <c>this</c>
        /// <c>Relation</c> don't interact.
        /// </summary>
        /// <returns>A really deep copy of <c>this</c> <c>Relation</c>.</returns>
        public virtual object! Copy()
        {
            return new Relation(this, true);
        }


        [Confined]
        public override string! ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("[");
            foreach (object key in this.GetKeys()) {
                sb.Append("\n  ");
                sb.Append(key);
                sb.Append(" -> " );
                sb.Append(this.GetValues(key));
            }
            sb.Append("]");
            return sb.ToString();
        }

        public static Hashtable/*<Key,Value[]>*/ Compact(IRelation!/*<Key,Value>*/ irel, Type! value_type) 
        {
            Hashtable hash = new Hashtable();
            foreach (object key in irel.GetKeys()) {
                ISet vals = irel.GetValues(key);
                if (vals.Count == 0)
                    continue;
                System.Array array_vals = System.Array.CreateInstance(value_type, vals.Count);
                vals.CopyTo(array_vals, 0);
                hash.Add(key, array_vals);
            }
            return hash;
        }
    }

}

namespace DataStructs
{
    using System;
    using System.Text;
    using System.Collections;
    using System.Diagnostics;


    
    
    /// <summary>
    /// Interface for Strongly Connected Methods.
    /// </summary>
    public interface IStronglyConnectedComponent
    {
        /// <summary>
        /// Returns the nodes contained into <c>this</c> StronglyConnectedComponent.
        /// </summary>
        IEnumerable! Nodes { get; }

        bool Contains (object! node);

        /// <summary>
        /// Returns the number of nodes in <c>this</c> StronglyConnectedComponent.
        /// </summary>
        /// <returns></returns>
        int Size { get; }

        /// <summary>
        /// Returns the SCCs that are end points of the arcs that starts in
        /// <c>this</c> StronglyConnectedComponent, i.e., the successors of <c>this</c> StronglyConnectedComponent in the
        /// component graph. Does not contain <c>this</c> StronglyConnectedComponent.
        /// </summary>
        IEnumerable! NextComponents { get; }

        /// <summary>
        /// Returns the SCCs that are starting points for arcs that end
        /// in <c>this</c> StronglyConnectedComponent, i.e., the predecessors of <c>this</c> StronglyConnectedComponent
        /// in the component graph. Does not contain <c>this</c> StronglyConnectedComponent.
        /// </summary>
        IEnumerable! PreviousComponents { get; }
        /// <summary>
        /// Checks whether <c>this</c> StronglyConnectedComponent is a cycle, i.e., if it has more than
        /// one node or it has a single node which points to itself.  The only
        /// StronglyConnectedComponent that does not contain a cycle is a StronglyConnectedComponent composed of a single node
        /// which doesn't point to itself.
        /// </summary>
        /// <returns></returns>
        bool ContainsCycle { get; }

        /// <summary>
        /// Detailed text representation of <c>this</c> StronglyConnectedComponent.
        /// <c>ToString</c> will return just a unique text id of the StronglyConnectedComponent,
        /// while the detailed text representation will be produced by
        /// <c>FullToString</c>
        /// </summary>
        /// <returns></returns>
        string! FullToString();
    }



    /// <summary>
    /// StronglyConnectedComponent is a full implementation of the interface <c>ISCC</c>.
    /// It comes with a producer static method that constructs the
    /// component graph for a given graph. 
    /// </summary>
    public sealed class StronglyConnectedComponent: IStronglyConnectedComponent
    {
        // unique numeric id for debug purposes 
        private int id;

        private IMutableSet! nodes     = new HashSet();
        private IMutableSet! next_SCCs = new HashSet();
        private IMutableSet! prev_SCCs = new HashSet();
        private bool contains_cycle = true;


        // SCCs should be created only by Util.ConstructSCCs
        private StronglyConnectedComponent () { }

        private StronglyConnectedComponent (int id)
        {
            this.id = id;
        }


        public IEnumerable! Nodes { get { return this.nodes; } }


        public bool Contains (object! node)
        {
            return nodes.Contains(node);
        }


        public int Size { get { return this.nodes.Count; } }


        public IEnumerable! NextComponents { get { return this.next_SCCs; } }


        public IEnumerable! PreviousComponents { get { return this.prev_SCCs; } }


        public bool ContainsCycle { get { return this.contains_cycle; } }


        /// <summary>
        /// Detailed text representation of <c>this</c> StronglyConnectedComponent.
        /// </summary>
        /// <returns></returns>
        public string! FullToString ()
        {
            StringBuilder buff = new StringBuilder();
            buff.Append(this);
            buff.Append(" (");
            buff.Append(Size);
            buff.Append(") {\n");
            buff.Append(" Nodes: ");
            buff.Append(Nodes);
            buff.Append("\n");
            buff.Append(" ContainsCycle: ");
            buff.Append(ContainsCycle);
            buff.Append("\n");
            if (next_SCCs.Count > 0) {
                buff.Append(" Next: ");
                buff.Append(NextComponents);
                buff.Append("\n");
            }
            if (prev_SCCs.Count > 0) {
                buff.Append(" Prev: ");
                buff.Append(PreviousComponents);
                buff.Append("\n");
            }
            buff.Append("}");
            return buff.ToString();
        }

        /// <summary>
        /// Simplified text representation for debug purposes: "StronglyConnectedComponent" + numeric id.
        /// </summary>
        /// <returns></returns>
        [Confined]
        public override string! ToString()
        {
            return "StronglyConnectedComponent" + id;
        }


        /// <summary>
        /// Use the <c>nav</c> navigator to explore the graph rooted in the
        /// objects from the <c>roots</c> set, decomposes it into strongly
        /// connected components. Returns the set of strongly connected components.
        /// </summary>
        public static IEnumerable!/*<StronglyConnectedComponent>*/ ConstructSCCs(IEnumerable! roots, IGraphNavigator! navigator)
        {
            return (new SCCFactory(navigator)).ConstructSCCs(roots);
        }

        // private class that does the actual job behind ConstructSCCs
        private sealed class SCCFactory
        {
            public SCCFactory (IGraphNavigator! navigator) { this.navigator = navigator; base(); }

            public IEnumerable!/*<StronglyConnectedComponent>*/ ConstructSCCs (IEnumerable! roots)
            {
                
#if DEBUG_GRAPH
                Console.WriteLine("ConstructSCCs doing 1st dfs...");
#endif
                GraphUtil.SearchDepthFirst(
                    roots,
                    navigator,
                    null,
                    null,
                    null,
                    new DNodeVisitor(first_dfs_end_visitor)
                );

#if DEBUG_GRAPH
                Console.WriteLine("ConstructSCCs doing 2nd dfs...");
#endif

                GraphUtil.SearchDepthFirst(
                    nodes_desc_order,
                    new BackwardGraphNavigator(navigator),
                    new DNodePredicate(second_dfs_avoid),
                    new DNodeVisitor(create_new_SCC),
                    new DNodeVisitor(second_dfs_begin_visitor),
                    null
                );

#if DEBUG_GRAPH
                Console.WriteLine("ConstructSCCs doing put_arcs...");
#endif
                put_arcs();

                return all_SCCs;
            }


            // navigator through the graph
            private IGraphNavigator! navigator;
            // the nodes in the subgraph rooted in the roots
            private IMutableSet!  nodes_in_graph = new HashSet();
            // holds all the nodes in the explored subgraph; the top of the stack
            // is the node whose dfs traversal finished last 
            private Stack! nodes_desc_order = new Stack();

            private StronglyConnectedComponent current_scc = null;
            private ArrayList! all_SCCs = new ArrayList();
            private Hashtable!/*<object,StronglyConnectedComponent>*/ node2scc = new Hashtable();

            // numeric id used to generate distinct ids for the generated SCCs
            private int scc_id = 0;

            private void first_dfs_end_visitor(object! node)
            {
                nodes_in_graph.Add(node);
                nodes_desc_order.Push(node);
            }

            // the second dfs will avoid the nodes that are not in the subgraph rooted
            // in the root nodes; this way, the reversed navigator cannot lead us to
            // unexplored regions.
            private bool second_dfs_avoid (object! node)
            {
                return ! nodes_in_graph.Contains(node);
            }

            private void create_new_SCC (object! node)
            {
                current_scc = new StronglyConnectedComponent(scc_id++);
                all_SCCs.Add(current_scc);
            }

            private void second_dfs_begin_visitor (object! node)
            {
                assert current_scc != null;
                current_scc.nodes.Add(node);
                node2scc.Add(node, current_scc);
            }


            private void put_arcs()
            {
                foreach (object node in nodes_in_graph) {
                    StronglyConnectedComponent scc = (StronglyConnectedComponent) node2scc[node];
                    assert(scc != null);
                    // add the arcs from scc to successor SCCs
                    foreach (object next_node in navigator.NextNodes(node)) 
                        if(nodes_in_graph.Contains(next_node))
                        {
                            StronglyConnectedComponent next = (StronglyConnectedComponent) node2scc[next_node];
                            assert(next != null);
                            scc.next_SCCs.Add(next);
                        }
                    // add the arcs from scc to predecessor SCCs
                    foreach (object prev_node in navigator.PreviousNodes(node))
                        if(nodes_in_graph.Contains(prev_node))
                        {
                            StronglyConnectedComponent prev = (StronglyConnectedComponent) node2scc[prev_node];
                            assert(prev != null);
                            scc.prev_SCCs.Add(prev);
                        }
                }

                foreach (StronglyConnectedComponent scc in all_SCCs) {
                    scc.contains_cycle = scc.next_SCCs.Contains(scc);
                    scc.next_SCCs.Remove(scc);
                    scc.prev_SCCs.Remove(scc);
                }
            }
        }

    }

}

namespace DataStructs
{
    using System;
    using System.Collections;

    /// <summary>
    /// Interface for navigating into a graph.
    /// </summary>
    public interface IGraphNavigator
    {
        /// <summary>
        /// Returns the nodes that can be reached from <c>node</c> by
        /// navigating one level along the graph edges.
        /// </summary>
        IEnumerable! NextNodes (object! node);
        /// <summary>
        /// Returns the nodes that can be reached from <c>node</c> by
        /// navigating one level AGAINST the graph edges (i.e., from edge
        /// target to the edge source).
        /// </summary>
        IEnumerable! PreviousNodes (object! node);
    }


    /// <summary>
    /// Navigator for the graph obtained by unioning two graphs.
    /// </summary>
    public class UnionGraphNavigator: IGraphNavigator
    {
        /// <summary>
        /// Constructs a navigator into a graph which is the union of two graphs
        /// (where the graphs are seen as edge sets).
        /// </summary>
        /// <param name="nav1">Navigator for the first graph.</param>
        /// <param name="nav2">Navigator for the second graph.</param>
        public UnionGraphNavigator(IGraphNavigator! nav1, IGraphNavigator! nav2)
        {
            this.nav1 = nav1;
            this.nav2 = nav2;
        }
        private IGraphNavigator! nav1;
        private IGraphNavigator! nav2;

        /// <summary>
        /// In a union graph, the list of successors of a node includes its successors in
        /// the first graph followed by its successors in the second graph.
        /// </summary>
        public virtual IEnumerable! NextNodes (object! node)
        {
            return new CompoundEnumerable(nav1.NextNodes(node), nav2.NextNodes(node));
        }

        /// <summary>
        /// In a union graph, the list of predecessors of a node includes the its predecessors in
        /// the first graph followed by its predecessors in the second graph.
        /// </summary>
        public virtual IEnumerable! PreviousNodes (object! node)
        {
            return new CompoundEnumerable(nav1.PreviousNodes(node), nav2.PreviousNodes(node));
        }
    }


    public abstract class ForwardOnlyGraphNavigator: IGraphNavigator
    {
        public abstract IEnumerable! NextNodes (object! node);

        public virtual IEnumerable! PreviousNodes (object! node)
        {
            throw new InvalidOperationException("should never be called!");
        }
    }

    /// <summary>
    /// Navigator for an inversed graph.  The successors (i.e., <c>NextNodes</c>)
    /// of a node are the predecessors of the node in the original graph.  Analogously
    /// for the predecessors.
    /// </summary>
    public class BackwardGraphNavigator: IGraphNavigator
    {
        private readonly IGraphNavigator! navigator;

        /// <summary>
        /// Constructs a <c>BackwardGraphNavigator</c> that reverses an
        /// <c>IGraphNavigator</c>.
        /// </summary>
        /// <param name="navigator">The navigator that is reversed.</param>
        public BackwardGraphNavigator(IGraphNavigator! navigator)
        {
            this.navigator = navigator;
            base();
        }

        public IEnumerable! NextNodes (object! node)
        {
            return navigator.PreviousNodes(node);
        }

        public IEnumerable! PreviousNodes (object! node)
        {
            return navigator.NextNodes(node);
        }
    }

    
    public class FilteredGraphNavigator : IGraphNavigator
    {

        IGraphNavigator! graph;
        ISet! nodes;

        /// <summary>
        /// Only nodes in given set are considered part of the graph.
        /// </summary>
        public FilteredGraphNavigator(ISet! nodes, IGraphNavigator! graph) 
        {
            this.graph = graph;
            this.nodes = nodes;
        }

        #region IGraphNavigator Members

        public IEnumerable! NextNodes (object! node)
        {
            return new FilterEnumerable(this.nodes, this.graph.NextNodes(node));
        }

        public IEnumerable! PreviousNodes (object! node)
        {
            return new FilterEnumerable(this.nodes, this.graph.PreviousNodes(node));
        }

        private class FilterEnumerable : IEnumerable
        {
            ISet! nodes;
            IEnumerable! edges;

            public FilterEnumerable(ISet! nodes, IEnumerable! edges) 
            {
                this.nodes = nodes;
                this.edges = edges;
                base();
            }

            public IEnumerator GetEnumerator() { return new FilterEnumerator(this.nodes, this.edges.GetEnumerator()); }


            private class FilterEnumerator : IEnumerator
            {
                ISet! nodes;
                IEnumerator! edges;

                public FilterEnumerator(ISet! nodes, IEnumerator! edges) 
                {
                    this.nodes = nodes;
                    this.edges = edges;
                    base();
                }

                #region IEnumerator Members

                public void Reset()
                {
                    this.edges.Reset();
                }

                public object Current
                {
                    get
                    {
                        return this.edges.Current;
                    }
                }

                public bool MoveNext()
                {
                    while (this.edges.MoveNext()) {
                        if (this.nodes.Contains(this.Current)) {
                            return true;
                        }
                    }
                    return false;
                }

                #endregion

            }
        }
        #endregion
    }


    public class MapBasedNavigator: IGraphNavigator
    {
        protected IMutableRelation! n2next;
        protected IMutableRelation! n2prev;

        public MapBasedNavigator (IMutableRelation! nextRelation, IMutableRelation! previousRelation) 
        {
            n2next = nextRelation; 
            n2prev = previousRelation;
        }

        public MapBasedNavigator (IMutableRelation! nextRelation) 
            : this(nextRelation, nextRelation.Reverse())
        {
        }

        public virtual IEnumerable! NextNodes (object! node)
        {
            return n2next.GetValues(node);
        }

        public virtual IEnumerable! PreviousNodes (object! node)
        {
            return n2prev.GetValues(node);
        }       
    }


    public class GraphBuilder : MapBasedNavigator 
    {
        public GraphBuilder () 
            : base (new Relation(), new Relation())
        {
        }

        public IEnumerable Nodes 
        {
            get 
            { 
                return new UnionEnumerable(n2next.GetKeys(), n2prev.GetKeys()); 
            }
        }

        public void AddEdge(object! from, object! to) 
        {
            this.n2next.Add(from, to);
            this.n2prev.Add(to, from);
        }
    }


    /// <summary>
    /// Navigator in a component graph (an acyclic graph of ISCCs).
    /// </summary>
    public class SccNavigator: IGraphNavigator
    {
        public virtual IEnumerable! NextNodes (object! node)
        {
            return ((IStronglyConnectedComponent) node).NextComponents;
        }

        public virtual IEnumerable! PreviousNodes (object! node)
        {
            return ((IStronglyConnectedComponent) node).PreviousComponents;
        }
    }


    public class CyclicGraphException: Exception { }

    public delegate bool DNodePredicate (Object! node);
    public delegate void DNodeVisitor (Object! node);
    public delegate void DEdgeVisitor (Object! from, Object! to);

    public abstract class GraphUtil
    {
        public static ISet! ReachableNodes (IEnumerable! roots, IGraphNavigator! navigator,  DNodePredicate avoid)
        {
            ReachableNodesData data = new ReachableNodesData();
            SearchDepthFirst(roots, navigator, avoid, null,
                new DNodeVisitor(data.reachable_visitor), null);
            return data.all_nodes;
        }

        private class ReachableNodesData
        {
            public IMutableSet! all_nodes  = new HashSet();
            public void reachable_visitor(object! node)
            {
                all_nodes.Add(node);
            }
        }

        public static ISet! ReachableNodes (IEnumerable! roots, IGraphNavigator! navigator) 
        {
            return ReachableNodes(roots, navigator, null);
        }


        /// <summary>
        /// Topologically sorts the graph rooted in <c>roots</c> and described by
        /// <c>nav</c>. Throws a <c>CyclicGraphException</c> if the graph contains
        /// a cycle. Otherwise, returns a topologically sorted list of the graph nodes. 
        /// The returned list is in ascending order: it starts with the nodes that don't
        /// have any out-arc (i.e., arcs going out of them) and ends with the nodes
        /// that don't have any in-arcs (i.e., arcs going into them).  If the navigator
        /// works in constant time, the topological sort works in time linear with the
        /// number of nodes plus the number of edges. 
        /// 
        /// </summary>
        public static IList TopologicallySortGraph (IEnumerable! roots, IGraphNavigator! navigator)
        {
            TopSortData data = new TopSortData();
            data.all_nodes.AddAll(ReachableNodes(roots, navigator));
            if (data.all_nodes.Count == 0)
                return data.list;

            // find the real roots: those nodes with no arcs pointing to them
            data.real_roots.AddAll(roots);
            foreach (object node in data.all_nodes)
                foreach(object next_node in navigator.NextNodes(node))
                    data.real_roots.Remove(next_node);
            // if there is no real root, we have a cycle
            if (data.real_roots.Count == 0)
                throw new CyclicGraphException();

            dfs(data.real_roots, navigator, null, null,
                new DNodeVisitor(data.sort_end_visitor));

#if NEVER
            // check for cyles
            IMutableSet seen = new HashSet();
            foreach (object node in data.list) {
                foreach (object next_node in navigator.NextNodes(node))
                    // all arcs must go behind in the list, to already seen nodes
                    if (!seen.Contains(next_node))
                        throw new CyclicGraphException();
                seen.Add(node);
            }
#endif
            return data.list;
        }

        private class TopSortData
        {
            public ArrayList! list  = new ArrayList();
            public IMutableSet! all_nodes  = new HashSet();
            public IMutableSet! real_roots = new HashSet();
            public void sort_end_visitor(object! node)
            {
                list.Add(node);
            }
        }


        /// <summary>
        /// Topologically sorts a component graph: a graph whose nodes are the
        /// strongly connected components of the original graph (such a graph is
        /// clearly acyclic). Calls the full-fledged TopSortComponentGraph with
        /// the standard <c>ISCCNavigator</c>.
        /// 
        /// </summary>
        /// <param name="roots">The set of the root SCCs, only the SCCs reacheable
        /// from these roots will be considered by the topological sort.</param>
        /// <returns></returns>
        public static IList//<IStronglyConnectedComponent>   
            TopologicallySortComponentGraph(IEnumerable!/*<IStronglyConnectedComponent>*/ roots)
        {
            return TopologicallySortGraph(roots, iscc_navigator);
        }
        // private navigator for TopSortComponentGraph
        private static SccNavigator! iscc_navigator = new SccNavigator();

        /// <summary>
        /// DFS traversal of the (sub)graph rooted in a set of nodes.
        /// </summary>
        /// <param name="roots">Roots of the traversed subgraph. The subgraph
        /// rooted in the first root will be traversed in dfs order; next, if
        /// the second root wasn't reached yet, the subgraph rooted in it will
        /// be traversed in dfs order and so on. The order of
        /// the roots is given by the corresponding <c>IEnumerator</c>.</param>
        /// <param name="navigator">Navigator that describes the graph structure.</param>
        /// <param name="avoid">Encountered nodes that satisfy this predicate will be
        /// ignored by the DFS traversal (together with their attached arcs). <c>null</c>
        /// corresponds to the predicate that is always false (i.e., no encountered node
        /// will be ignored).</param>
        /// <param name="new_subgraph_visitor">Visitor for the root node of each
        /// new subgraph: the roots (see the <see cref="roots">roots</see> parameter)
        /// are explored in order; if a root node has not been already reached
        /// by the dfs traversal of the previous roots, <c>new_subgraph_visitor</c>
        /// will be called on it, and next the subgraph rooted in it will be dfs
        /// traversed.</param>
        /// <param name="begin_visitor">Node visitor to be called when a node is reached
        /// for the first time by the DFS traversal. <c>null</c> corresponds to no
        /// visitor.</param>
        /// <param name="end_visitor">Node visitor to be called when the exploration of
        /// a node has finished. <c>null</c> corresponds to no visitor.</param>
        public static void SearchDepthFirst (
            IEnumerable! roots, 
            IGraphNavigator! navigator,
             DNodePredicate avoid,
             DNodeVisitor new_subgraph_visitor,
             DNodeVisitor begin_visitor,
             DNodeVisitor end_visitor
            )
        {
            // set of already seen nodes
            IMutableSet seen_nodes = new HashSet();
            // DFS Stack: holds the currently explored path; simulates the call
            // stack of a recursive implementation of dfs.
            Stack/*<NodeInfo>*/ stack = new Stack();

            foreach (object root in roots) {
                if (((avoid != null) && avoid(root)) ||
                    seen_nodes.Contains(root)) continue;

                call_visitor(new_subgraph_visitor, root);

                seen_nodes.Add(root);
                call_visitor(begin_visitor, root);
                stack.Push(new NodeInfo(root, navigator));
                while (stack.Count != 0) {
                    NodeInfo info = (NodeInfo) (object!)stack.Peek();
                    if (info.enext.MoveNext()) {
                        object next_node = info.enext.Current;
                        // ignore nodes as dictated by "avoid"
                        if ((avoid != null) && avoid(next_node))
                            continue;
                        
                        if (!seen_nodes.Contains(next_node)) {
                            // new and non-avoidable node!
                            // mark it as seen,
                            seen_nodes.Add(next_node);
                            // call the begin visitor,
                            call_visitor(begin_visitor, next_node);
                            // and put the node on the DFS stack
                            stack.Push(new NodeInfo(next_node, navigator));
                        }
                    }
                    else {
                        // the visit of info.node has finished
                        // apply end visitor
                        call_visitor(end_visitor, info.node);
                        // remove the top of the stack
                        stack.Pop();
                    }
                }
            }
        }


        /// <summary>
        /// Convenient <c>dfs</c> function.  Call the full <c>dfs</c> function
        /// with new_subgraph_visitor set to <c>null</c>.
        /// </summary>
        public static void dfs (
            IEnumerable! roots, 
            IGraphNavigator! navigator,
             DNodePredicate avoid,
             DNodeVisitor begin_visitor,
             DNodeVisitor end_visitor)
        {
            SearchDepthFirst(roots, navigator, avoid, null, begin_visitor, end_visitor);
        }

        private static void call_visitor(  DNodeVisitor visitor, object! node)
        {
            if (visitor != null)
                visitor(node);
        }

        // private class used internally by the dfs method.
        private struct NodeInfo
        {
            public object! node;
            public IEnumerator! enext ;
            public NodeInfo(object! node, IGraphNavigator! navigator)
            {
                this.node  = node;
                this.enext = navigator.NextNodes(node).GetEnumerator();
            }
        }



        /// <summary>
        /// Does a breadth first traversal of the given graph
        /// </summary>
        /// <param name="roots">The roots of the traversal.</param>
        /// <param name="avoid">If not null, is a predicate to avoid certain nodes</param>
        /// <param name="visitRoot">If not null, called for each root that is not avoided.</param>
        /// <param name="visitEdge">Called for each edges in the bf traversal, i.e., only for edges going to unvisited nodes.</param>
        public static void bfs(IEnumerable! roots, IGraphNavigator! navigator,
             DNodePredicate avoid,
             DNodeVisitor visitRoot,
             DEdgeVisitor! visitEdge)
        {
            Queue queue = new Queue();
            IMutableSet seen = new HashSet();

            // initialize queue with roots
            foreach (object o in roots) {
                if (avoid == null || !avoid(o)) {
                    queue.Enqueue(o);
                    seen.Add(o);
                    if (visitRoot != null) visitRoot(o);
                }
            }

            while (queue.Count > 0) {
                object node = queue.Dequeue();
                assert(node != null);
                foreach (object succ in navigator.NextNodes(node)) {
                    if ((avoid == null || !avoid(succ)) && !seen.Contains(succ)) {
                        seen.Add(succ);
                        queue.Enqueue(succ);
                        visitEdge(node, succ);
                    }
                }
            }
        }




        private class BFSpanningBuilder : MapBasedNavigator
        {
            public BFSpanningBuilder () 
                : base (new Relation(), new Relation())
            {
            }

            public void VisitEdge(object! from, object! to) 
            {
                this.n2next.Add(from, to);
                this.n2prev.Add(to, from);
            }
        }

        public static IGraphNavigator BFSpanningTree(IEnumerable! roots, IGraphNavigator! navigator, 
             DNodePredicate avoid) 
        {
            BFSpanningBuilder bfb = new BFSpanningBuilder();

            bfs(roots, navigator, avoid, null, new DEdgeVisitor(bfb.VisitEdge));

            return bfb;
        }
    }

}


namespace DataStructs
{
    using System;
    using System.Collections;


    public class ArrayEnumerable : IEnumerable
    {
        object[]! array;
        int size;

        public ArrayEnumerable(object[]! array, int size) 
        {
            this.array = array;
            this.size = size;
        }

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return new ArrayEnumerator(this.array, this.size);
        }

        #endregion

    }



    /// <summary>
    /// Enumerator over a prefix of an array (System.Array.GetEnumerator returns
    /// an enumerator over ALL the elements of the array).
    /// </summary>
    public class ArrayEnumerator : IEnumerator
    {
        /// <summary>
        /// Constructs an enumerator  over the first <c>size</c> elements of <c>array</c>.
        /// NOTE: I couldn't find any way of detecting comodification errors ...
        /// </summary>
        public ArrayEnumerator(object[]! array, int size)
        {
            this.array = array;
            this.size  = size;
            this.index = -1;
        }

        // underlying array
        private readonly object[]! array;
        // length of the prefix of array that we enumerate over
        private readonly int      size;
        // current enumerator position
        private int index;


        public virtual object Current
        {
            get 
            {
                if ((index >= 0) && (index < size)) return array[index];
                else
                    throw new InvalidOperationException();
            }
        }


        public virtual bool MoveNext()
        {
            if (index == size)
                return false;
            index++;
            // check whether we've passed the limit or not
            return index != size;
        }


        public virtual void Reset()
        {
            index = -1;
        }
    }
}


namespace DataStructs 
{
    using System;
    using System.Collections;


    /// <summary>
    /// Union enumerator over two <c>IEnumerable</c> objects. Each key is visited only once
    /// </summary>
    public class UnionEnumerable: IEnumerable 
    {

        public UnionEnumerable(IEnumerable! ieable1, IEnumerable! ieable2) 
            : this(new IEnumerable[]{ieable1, ieable2})
        {
        }

        public UnionEnumerable(IEnumerable!/*<IEnumerable>*/ ienums) 
        {
            this.ienums = ienums;
        }

        private IEnumerable!/*<IEnumerable>*/ ienums;

        public virtual IEnumerator GetEnumerator() 
        {
            return new UnionEnumerator(ienums);
        }
    }

    /// <summary>
    /// Union composition of two enumerators.  Enumerating with a
    /// multi-enumerator is equivalent to enumerating over the union of the elements in
    /// the first and second enumerator.
    /// </summary>
    public class UnionEnumerator: IEnumerator 
    {
        /// <summary>
        /// Creates a <c>UnionEnumerator</c> over both given enumerators.
        /// </summary>
        public UnionEnumerator(IEnumerable!/*<IEnumerable>*/ ienums) 
        {
            this.ies = ienums;

            // Duplicate from Reset 
            IEnumerator ienum = this.ienumate = ienums.GetEnumerator();
            // go to first enumerator.
            MoveEnumerator(ienum);
        }

        public void Reset() 
        {
            seen.Clear();

            IEnumerator ienum = this.ienumate = ies.GetEnumerator();
            // go to first enumerator.
            MoveEnumerator(ienum);
        }

        [Delayed]
        private void MoveEnumerator(IEnumerator! ienum) 
        {
            if (ienum.MoveNext()) {
                this.current_ie = ((IEnumerable)ienum.Current).GetEnumerator();
            }
            else {
                this.current_ie = null;
            }
        }


        public UnionEnumerator(IEnumerable ie1, IEnumerable ie2) : this(new IEnumerable[]{ie1,ie2})
        {
        }

        private HashSet! seen = new HashSet();
        private IEnumerable!/*<IEnumerable>*/ ies;
        private IEnumerator!/*<IEnumerable>*/ ienumate;
        private IEnumerator/*<'a>*/ current_ie;

        public virtual object Current 
        {
            get 
            {
                if (current_ie == null)
                    throw new InvalidOperationException("exhausted enumerator");
                return
                    current_ie.Current;
            }
        }

        public virtual bool MoveNext() 
        {
            while (current_ie != null) {
                if (current_ie.MoveNext()) {
                    if (this.seen.Add(current_ie.Current)) {
                        return true;
                    }
                    // already seen
                    continue;
                }
                // move to next ienumerable
                MoveEnumerator(this.ienumate);
            }
            return false;
        }

    }
}

namespace DataStructs 
{
    using System;
    using System.Collections;


    /// <summary>
    /// Returns null if object should not be returned, otherwise, returns object.
    /// Can thus change objects.
    /// </summary>
    public delegate object EnumeratorFilter(object elem, object context);

    /// <summary>
    /// "Glues" together two <c>IEnumerable</c> objects in a single view.
    /// </summary>
    public class CompoundEnumerable: IEnumerable 
    {

        /// <summary>
        /// Construct an enumerable that enumerators over ieable1, then ieable2. Each element
        /// is passed to the filter which can decide if the element should be returned by
        /// the enumerator or not. The filter can also change the element (map).
        /// </summary>
        /// <param name="filter">can be null</param>
        /// <param name="context">passed to filter</param>
        public CompoundEnumerable (
            IEnumerable! ieable1,
            IEnumerable! ieable2,
            EnumeratorFilter filter, 
            object context) 
        {
            this.ieable1 = ieable1;
            this.ieable2 = ieable2;
            this.filter = filter;
            this.context = context;
        }

        public CompoundEnumerable(IEnumerable! ieable1, IEnumerable! ieable2) : this(ieable1, ieable2, null, null)
        {
        }

        private IEnumerable! ieable1;
        private IEnumerable! ieable2;
        private EnumeratorFilter filter;
        private object context;

        public virtual IEnumerator GetEnumerator() 
        {
            return 
                new MultiEnumerator(ieable1.GetEnumerator(), ieable2.GetEnumerator(), filter, context);
        }
    }

    /// <summary>
    /// Serial composition of two enumerators.  Enumerating with a
    /// multi-enumerator is equivalent to enumerating with the first enumerator,
    /// and next with the second one.  Implements the full <c>IEnumerable</c>
    /// interface.  Aliases to the enumerators are sequentially composed are
    /// internally stored and used by the encapsulating multi-enumerator.
    /// </summary>
    public class MultiEnumerator: IEnumerator 
    {
        /// <summary>
        /// Creates a <c>MultiEnumerator</c> that serially chains the two
        /// enumerators passed as arguments.
        /// </summary>
        [NotDelayed]
        public MultiEnumerator(IEnumerator! ie1, IEnumerator! ie2,  EnumeratorFilter filter, object context) 
        {
            this.filter = filter;
            this.context = context;
            ies = new IEnumerator[]{ie1, ie2};
            base();
            ((IEnumerator!)ies[0]).Reset();
            ((IEnumerator!)ies[1]).Reset();
        }

        
        private EnumeratorFilter filter;
        private IEnumerator[]! ies;
        private int current_ie;
        private object context;

        private object currentValue;

        public virtual object Current 
        {
            get 
            {
                if (current_ie >= ies.Length)
                    throw new InvalidOperationException("exhausted enumerator");
                return
                    this.currentValue;
            }
        }

        public virtual bool MoveNext() 
        {
            if (current_ie >= ies.Length)
                return false;
            while (current_ie < ies.Length) {
                if (((IEnumerator!)ies[current_ie]).MoveNext()) {
                    object value = ((IEnumerator!)ies[current_ie]).Current;
                    if (this.filter != null) {
                        value = filter(value, this.context);
                        if (value == null) // skip this one
                        {
                            continue;
                        }
                    }
                    this.currentValue = value;
                    return true;
                }
                ((IEnumerator!)ies[current_ie]).Reset();
                current_ie++;                
            }
            return false;
        }

        public virtual void Reset() 
        {
            if (current_ie < ies.Length)
                ((IEnumerator!)ies[current_ie]).Reset();
            current_ie = 0;
        }
    }
}
