/// <summary>
        /// Reduction rules for a BDD.
        /// </summary>
        /// <param name="node">The node to reduce.</param>
        /// <param name="result">The modified node.</param>
        /// <returns>If there was a reduction.</returns>
        public virtual bool Reduce(CBDDNode node, out DDIndex result)
        {
            result = DDIndex.False;
            if (node.Low.Equals(node.High))
            {
                result = node.Low;
                return(true);
            }

            if (node.Low.IsConstant())
            {
                return(false);
            }

            var lo = this.Manager.LookupNodeByIndex(node.Low);

            if (lo.Variable == node.NextVariable && lo.High.Equals(node.High))
            {
                var reduced = new CBDDNode(node.Variable, lo.NextVariable, lo.Low, node.High);
                result = this.Manager.Allocate(reduced);
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// Remove all elements matching a predicate.
        /// </summary>
        /// <param name="forwardingAddresses">The forwarding addresses.</param>
        /// <returns>A new handle table after garbage collection.</returns>
        public HandleTable <T> Rebuild(int[] forwardingAddresses)
        {
            var table = new HandleTable <T>(this.manager, this.Count);

            for (int bucket = 0; bucket < this.buckets.Length; bucket++)
            {
                int i = this.buckets[bucket];
                while (i >= 0)
                {
                    var entry       = this.entries[i];
                    var index       = entry.Key;
                    var wref        = entry.Value;
                    var position    = index.GetPosition();
                    var newPosition = forwardingAddresses[position];
                    if (newPosition != 0 || index.IsConstant())
                    {
                        var newIndex = new DDIndex(newPosition, index.IsComplemented());
                        if (wref.TryGetTarget(out DD target))
                        {
                            target.Index = newIndex;
                        }

                        table.AddUnique(newIndex, wref);
                    }

                    i = entry.Next;
                }
            }

            return(table);
        }
        /// <summary>
        /// Rebuild the unique table.
        /// </summary>
        /// <param name="newSize">The new number of nodes in use after a GC.</param>
        /// <param name="forwardingAddresses">The index forwarding addresses.</param>
        /// <returns>A new table with valid indicies.</returns>
        public UniqueTable <T> Rebuild(int newSize, int[] forwardingAddresses)
        {
            var values = new DDIndex[newSize];
            var table  = new UniqueTable <T>(this.manager, this.Count);

            for (int bucket = 0; bucket < this.buckets.Length; bucket++)
            {
                int i = this.buckets[bucket];
                while (i >= 0)
                {
                    var entry       = this.entries[i];
                    var ddindex     = entry.Value;
                    var newPosition = forwardingAddresses[ddindex.GetPosition()];
                    if (newPosition != 0 || ddindex.IsConstant())
                    {
                        values[newPosition] = new DDIndex(newPosition, ddindex.IsComplemented());
                    }

                    i = entry.Next;
                }
            }

            for (int i = 0; i < values.Length; i++)
            {
                table.AddUnchecked(this.manager.MemoryPool[i], values[i]);
            }

            return(table);
        }
Пример #4
0
        /// <summary>
        /// Returns a new formula that repairs the order after a substitution.
        /// </summary>
        /// <param name="level">Variable level of the new node.</param>
        /// <param name="lo">The node's lo branch.</param>
        /// <param name="hi">The node's hi branch.</param>
        /// <returns></returns>
        private DDIndex RepairOrder(int level, DDIndex lo, DDIndex hi)
        {
            var loNode = this.Manager.MemoryPool[lo.GetPosition()];
            var hiNode = this.Manager.MemoryPool[hi.GetPosition()];

            loNode = lo.IsComplemented() ? Flip(loNode) : loNode;
            hiNode = hi.IsComplemented() ? Flip(hiNode) : hiNode;

            var loLevel = Level(lo, loNode);
            var hiLevel = Level(hi, hiNode);

            if (level < loLevel && level < hiLevel)
            {
                return(this.Manager.Allocate(new BDDNode(level, lo, hi)));
            }
            else if (loLevel < hiLevel)
            {
                var l = RepairOrder(level, loNode.Low, hi);
                var h = RepairOrder(level, loNode.High, hi);
                return(this.Manager.Allocate(new BDDNode(loNode.Variable, l, h)));
            }
            else if (loLevel > hiLevel)
            {
                var l = RepairOrder(level, lo, hiNode.Low);
                var h = RepairOrder(level, lo, hiNode.High);
                return(this.Manager.Allocate(new BDDNode(hiNode.Variable, l, h)));
            }
            else
            {
                var l = RepairOrder(level, loNode.Low, hiNode.Low);
                var h = RepairOrder(level, loNode.High, hiNode.High);
                return(this.Manager.Allocate(new BDDNode(loNode.Variable, l, h)));
            }
        }
 /// <summary>
 /// The logical conjunction of two BDDs as the
 /// standard BDD "apply" operation.
 /// </summary>
 /// <param name="xid">The left operand index.</param>
 /// <param name="x">The left operand node.</param>
 /// <param name="yid">The right operand index.</param>
 /// <param name="y">The right operand node.</param>
 /// <returns>A new node representing the "And".</returns>
 public DDIndex And(DDIndex xid, CBDDNode x, DDIndex yid, CBDDNode y)
 {
     if (x.Variable < y.Variable)
     {
         if (x.NextVariable <= y.Variable)
         {
             var xlow  = this.Manager.And(x.Low, yid);
             var xhigh = this.Manager.And(x.High, yid);
             return(this.Manager.Allocate(new CBDDNode(x.Variable, x.NextVariable, xlow, xhigh)));
         }
         else
         {
             var child = this.Manager.Allocate(new CBDDNode(y.Variable, x.NextVariable, x.Low, x.High));
             var xlow  = this.Manager.And(child, yid);
             var xhigh = this.Manager.And(x.High, yid);
             return(this.Manager.Allocate(new CBDDNode(x.Variable, y.Variable, xlow, xhigh)));
         }
     }
     else if (y.Variable < x.Variable)
     {
         if (y.NextVariable <= x.Variable)
         {
             var ylow  = this.Manager.And(y.Low, xid);
             var yhigh = this.Manager.And(y.High, xid);
             return(this.Manager.Allocate(new CBDDNode(y.Variable, y.NextVariable, ylow, yhigh)));
         }
         else
         {
             var child = this.Manager.Allocate(new CBDDNode(x.Variable, y.NextVariable, y.Low, y.High));
             var ylow  = this.Manager.And(child, xid);
             var yhigh = this.Manager.And(y.High, xid);
             return(this.Manager.Allocate(new CBDDNode(y.Variable, x.Variable, ylow, yhigh)));
         }
     }
     else
     {
         if (x.NextVariable == y.NextVariable)
         {
             var lo = this.Manager.And(x.Low, y.Low);
             var hi = this.Manager.And(x.High, y.High);
             return(this.Manager.Allocate(new CBDDNode(x.Variable, x.NextVariable, lo, hi)));
         }
         else if (x.NextVariable < y.NextVariable)
         {
             var ychild = this.Manager.Allocate(new CBDDNode(x.NextVariable, y.NextVariable, y.Low, y.High));
             var lo     = this.Manager.And(x.Low, ychild);
             var hi     = this.Manager.And(x.High, y.High);
             return(this.Manager.Allocate(new CBDDNode(x.Variable, x.NextVariable, lo, hi)));
         }
         else
         {
             var xchild = this.Manager.Allocate(new CBDDNode(y.NextVariable, x.NextVariable, x.Low, x.High));
             var lo     = this.Manager.And(y.Low, xchild);
             var hi     = this.Manager.And(y.High, x.High);
             return(this.Manager.Allocate(new CBDDNode(y.Variable, y.NextVariable, lo, hi)));
         }
     }
 }
Пример #6
0
        /// <summary>
        /// Reduction rules for a BDD.
        /// </summary>
        /// <param name="node">The node to reduce.</param>
        /// <param name="result">The modified node.</param>
        /// <returns>If there was a reduction.</returns>
        public virtual bool Reduce(BDDNode node, out DDIndex result)
        {
            result = DDIndex.False;
            if (node.Low.Equals(node.High))
            {
                result = node.Low;
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// Either get the existing value or create a
        /// new one in a single operation.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        private void AddUnique(DDIndex key, WeakReference <DD> value)
        {
            int hashCode     = key.GetHashCode() & 0x7FFFFFFF;
            int targetBucket = hashCode & this.mask;
            int index        = this.Count;

            this.Count++;
            this.entries[index] = new Entry {
                Next = this.buckets[targetBucket], Key = key, Value = value
            };
            this.buckets[targetBucket] = index;
        }
        /// <summary>
        /// Either get the existing value or create a
        /// new one in a single operation.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="value">The value.</param>
        public void AddUnchecked(T key, DDIndex value)
        {
            int hashCode     = key.GetHashCode() & 0x7FFFFFFF;
            int targetBucket = hashCode & this.mask;
            int index        = this.count;

            this.count++;
            this.entries[index] = new Entry {
                Next = this.buckets[targetBucket], Value = value
            };
            this.buckets[targetBucket] = index;
        }
        /// <summary>
        /// Implement the logical "exists" operation,
        /// recursively calling the manager if necessary.
        /// </summary>
        /// <param name="xid">The left index.</param>
        /// <param name="x">The left node.</param>
        /// <param name="variables">The variable set.</param>
        /// <returns>The resulting function.</returns>
        public DDIndex Exists(DDIndex xid, BDDNode x, VariableSet <BDDNode> variables)
        {
            var lo = this.Manager.Exists(x.Low, variables);
            var hi = this.Manager.Exists(x.High, variables);

            if (variables.Contains(x.Variable))
            {
                return(this.Manager.Or(lo, hi));
            }

            return(this.Manager.Allocate(new BDDNode(x.Variable, lo, hi)));
        }
Пример #10
0
        /// <summary>
        /// Implement a replacement operation that substitutes
        /// variables for other variables.
        /// </summary>
        /// <param name="xid">The left index.</param>
        /// <param name="x">The left node.</param>
        /// <param name="variableMap">The variable set.</param>
        /// <returns>A new formula with the susbtitution.</returns>
        public DDIndex Replace(DDIndex xid, BDDNode x, VariableMap <BDDNode> variableMap)
        {
            if (x.Variable > variableMap.MaxIndex)
            {
                return(xid);
            }

            var lo = this.Manager.Replace(x.Low, variableMap);
            var hi = this.Manager.Replace(x.High, variableMap);

            var level = variableMap.Get(x.Variable);

            level = level < 0 ? x.Variable : level;
            return(RepairOrder(level, lo, hi));
        }
Пример #11
0
 /// <summary>
 /// The logical conjunction of two BDDs as the
 /// standard BDD "apply" operation.
 /// </summary>
 /// <param name="xid">The left operand index.</param>
 /// <param name="x">The left operand node.</param>
 /// <param name="yid">The right operand index.</param>
 /// <param name="y">The right operand node.</param>
 /// <returns>A new node representing the "And".</returns>
 public DDIndex And(DDIndex xid, BDDNode x, DDIndex yid, BDDNode y)
 {
     if (x.Variable < y.Variable)
     {
         var xlow  = this.Manager.And(x.Low, yid);
         var xhigh = this.Manager.And(x.High, yid);
         return(this.Manager.Allocate(new BDDNode(x.Variable, xlow, xhigh)));
     }
     else if (y.Variable < x.Variable)
     {
         var ylow  = this.Manager.And(y.Low, xid);
         var yhigh = this.Manager.And(y.High, xid);
         return(this.Manager.Allocate(new BDDNode(y.Variable, ylow, yhigh)));
     }
     else
     {
         var low  = this.Manager.And(x.Low, y.Low);
         var high = this.Manager.And(x.High, y.High);
         return(this.Manager.Allocate(new BDDNode(x.Variable, low, high)));
     }
 }
Пример #12
0
        /// <summary>
        /// Either get the existing value or create a
        /// new one in a single operation.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns>The value, possibly freshly created.</returns>
        public DD GetOrAdd(DDIndex key)
        {
            int hashCode     = key.GetHashCode() & 0x7FFFFFFF;
            int targetBucket = hashCode & this.mask;

            for (int i = this.buckets[targetBucket]; i >= 0; i = this.entries[i].Next)
            {
                if (this.entries[i].Key.Equals(key))
                {
                    var wref = this.entries[i].Value;
                    if (!wref.TryGetTarget(out DD target))
                    {
                        target = new DD(this.manager.Uid, key);
                        wref.SetTarget(target);
                    }

                    return(target);
                }
            }

            int index;

            if (this.Count == this.entries.Length)
            {
                this.Resize();
                targetBucket = hashCode & this.mask;
            }

            index = this.Count;
            this.Count++;
            var dd    = new DD(this.manager.Uid, key);
            var value = new WeakReference <DD>(dd);

            this.entries[index] = new Entry {
                Next = this.buckets[targetBucket], Key = key, Value = value
            };
            this.buckets[targetBucket] = index;
            return(dd);
        }
Пример #13
0
        /// <summary>
        /// Return a function capturing a variable being greater
        /// than or equal to a particular value. The value is
        /// represented as a byte array and should be have MSBs first.
        /// For example, the 32-bit value 300 would be represented as
        /// the byte array [0, 0, 1, 44].
        /// </summary>
        /// <param name="value">The value.</param>
        /// <returns>The function representing the inequality.</returns>
        public DD GreaterOrEqual(byte[] value)
        {
            var len     = this.Indices.Length;
            var eq      = new DDIndex[len];
            var greater = new DDIndex[len];

            for (int v = len - 1; v >= 0; v--)
            {
                var variable   = this.Indices[v];
                var i          = this.GetBitPositionForVariableIndex(variable);
                var whichByte  = i / 8;
                var whichIndex = i % 8;
                var set        = GetBit(value[whichByte], whichIndex, 8);
                if (set)
                {
                    var node = this.Manager.IdIdx(variable);
                    eq[i]      = node;
                    greater[i] = DDIndex.False;
                }
                else
                {
                    var node = this.Manager.IdIdx(variable);
                    eq[i]      = this.Manager.Not(node);
                    greater[i] = node;
                }
            }

            var acc = DDIndex.True;

            for (int i = len - 1; i >= 0; i--)
            {
                acc = this.Manager.Or(greater[i], this.Manager.And(acc, eq[i]));
            }

            return(this.Manager.FromIndex(acc));
        }
Пример #14
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DD"/> class.
 /// </summary>
 /// <param name="managerId">Id of the manager that created this node.</param>
 /// <param name="index">Index of the underlying IDDNode.</param>
 internal DD(ushort managerId, DDIndex index)
 {
     this.ManagerId = managerId;
     this.Index     = index;
 }
 /// <summary>
 /// Implement the logical "exists" operation,
 /// recursively calling the manager if necessary.
 /// </summary>
 /// <param name="xid">The left index.</param>
 /// <param name="x">The left node.</param>
 /// <param name="variables">The variable set.</param>
 /// <returns>The resulting function.</returns>
 public DDIndex Exists(DDIndex xid, CBDDNode x, VariableSet <CBDDNode> variables)
 {
     throw new System.NotImplementedException();
 }
Пример #16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CBDDNode"/> struct.
 /// </summary>
 /// <param name="variable">The variable index.</param>
 /// <param name="nextVariable">The next index.</param>
 /// <param name="lo">The low (false) child.</param>
 /// <param name="hi">The high (true) child.</param>
 public CBDDNode(int variable, int nextVariable, DDIndex lo, DDIndex hi)
 {
     this.data = new NodeData32Packed(variable, false, nextVariable);
     this.Low  = lo;
     this.High = hi;
 }
Пример #17
0
 public DDIndex Ite(DDIndex fid, CBDDNode f, DDIndex gid, CBDDNode g, DDIndex hid, CBDDNode h)
 {
     throw new System.NotSupportedException();
 }
Пример #18
0
 /// <summary>
 /// Gets the "level" for the node, where the maximum
 /// value is used for constants.
 /// </summary>
 /// <param name="idx">The node index.</param>
 /// <param name="node">The node.</param>
 /// <returns></returns>
 private int Level(DDIndex idx, BDDNode node)
 {
     return(idx.IsConstant() ? int.MaxValue : node.Variable);
 }
Пример #19
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BDDNode"/> struct.
 /// </summary>
 /// <param name="variable">The variable index.</param>
 /// <param name="lo">The low (false) child.</param>
 /// <param name="hi">The high (true) child.</param>
 public BDDNode(int variable, DDIndex lo, DDIndex hi)
 {
     this.data = new NodeData32(variable, false);
     this.Low  = lo;
     this.High = hi;
 }
Пример #20
0
        /// <summary>
        /// Implement the logical "ite" operation,
        /// recursively calling the manager if necessary.
        /// </summary>
        /// <param name="fid">The f index.</param>
        /// <param name="f">The f node.</param>
        /// <param name="gid">The g index.</param>
        /// <param name="g">The g node.</param>
        /// <param name="hid">The h index.</param>
        /// <param name="h">The h node.</param>
        /// <returns>The ite of the three nodes.</returns>
        public DDIndex Ite(DDIndex fid, BDDNode f, DDIndex gid, BDDNode g, DDIndex hid, BDDNode h)
        {
            var flevel = Level(fid, f);
            var glevel = Level(gid, g);
            var hlevel = Level(hid, h);

            if (flevel == glevel)
            {
                if (flevel == hlevel)
                {
                    var x = this.Manager.IteRecursive(f.Low, g.Low, h.Low);
                    var y = this.Manager.IteRecursive(f.High, g.High, h.High);
                    return(this.Manager.Allocate(new BDDNode(f.Variable, x, y)));
                }
                else if (flevel < hlevel)
                {
                    var x = this.Manager.IteRecursive(f.Low, g.Low, hid);
                    var y = this.Manager.IteRecursive(f.High, g.High, hid);
                    return(this.Manager.Allocate(new BDDNode(f.Variable, x, y)));
                }
                else
                {
                    var x = this.Manager.IteRecursive(fid, gid, h.Low);
                    var y = this.Manager.IteRecursive(fid, gid, h.High);
                    return(this.Manager.Allocate(new BDDNode(h.Variable, x, y)));
                }
            }
            else if (flevel < glevel)
            {
                if (flevel == hlevel)
                {
                    var x = this.Manager.IteRecursive(f.Low, gid, h.Low);
                    var y = this.Manager.IteRecursive(f.High, gid, h.High);
                    return(this.Manager.Allocate(new BDDNode(f.Variable, x, y)));
                }
                else if (flevel < hlevel)
                {
                    var x = this.Manager.IteRecursive(f.Low, gid, hid);
                    var y = this.Manager.IteRecursive(f.High, gid, hid);
                    return(this.Manager.Allocate(new BDDNode(f.Variable, x, y)));
                }
                else
                {
                    var x = this.Manager.IteRecursive(fid, gid, h.Low);
                    var y = this.Manager.IteRecursive(fid, gid, h.High);
                    return(this.Manager.Allocate(new BDDNode(h.Variable, x, y)));
                }
            }
            else
            {
                if (glevel == hlevel)
                {
                    var x = this.Manager.IteRecursive(fid, g.Low, h.Low);
                    var y = this.Manager.IteRecursive(fid, g.High, h.High);
                    return(this.Manager.Allocate(new BDDNode(g.Variable, x, y)));
                }
                else
                if (glevel < hlevel)
                {
                    var x = this.Manager.IteRecursive(fid, g.Low, hid);
                    var y = this.Manager.IteRecursive(fid, g.High, hid);
                    return(this.Manager.Allocate(new BDDNode(g.Variable, x, y)));
                }
                else
                {
                    var x = this.Manager.IteRecursive(fid, gid, h.Low);
                    var y = this.Manager.IteRecursive(fid, gid, h.High);
                    return(this.Manager.Allocate(new BDDNode(h.Variable, x, y)));
                }
            }
        }
Пример #21
0
 /// <summary>
 /// Implement a replacement operation that substitutes
 /// variables for other variables.
 /// </summary>
 /// <param name="xid">The left index.</param>
 /// <param name="x">The left node.</param>
 /// <param name="variableMap">The variable set.</param>
 /// <returns>A new formula with the susbtitution.</returns>
 public DDIndex Replace(DDIndex xid, CBDDNode x, VariableMap <CBDDNode> variableMap)
 {
     throw new System.NotSupportedException();
 }