Skip to content

Commit

Permalink
Preparing for new persistent bst types
Browse files Browse the repository at this point in the history
  • Loading branch information
200sc committed Apr 28, 2017
1 parent 5500238 commit 9683fcc
Show file tree
Hide file tree
Showing 6 changed files with 205 additions and 108 deletions.
2 changes: 1 addition & 1 deletion search/persistent.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type DynamicPersistent interface {
Dynamic
AtInstant(float64) Dynamic
ThisInstant() Dynamic
ToStaticPersitent() StaticPersistent
ToStaticPersistent() StaticPersistent
}

// Persistable types are dynamic types, convertible to PersistentDynamic.
Expand Down
2 changes: 1 addition & 1 deletion search/tree/bst.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (bst *BST) isValid() bool {

// ToPersistent converts this BST into a Persistent BST.
func (bst *BST) ToPersistent() search.DynamicPersistent {
pbst := new(PersistentBST)
pbst := new(FullPersistentBST)
pbst.instant = math.MaxFloat64 * -1
pbst.instants = []BSTInstant{{BST: bst, instant: pbst.instant}}
return pbst
Expand Down
102 changes: 0 additions & 102 deletions search/tree/persistent.go

This file was deleted.

137 changes: 137 additions & 0 deletions search/tree/persistentFullCopy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package tree

import (
"github.com/200sc/go-compgeo/printutil"
"github.com/200sc/go-compgeo/search"
)

// FullPersistentBST is an implementation of a persistent
// binary search tree using full copies, with each
// instant represented by a separate BST.
type FullPersistentBST struct {
instant float64
index int
// Implicitly sorted
instants []BSTInstant
}

// BSTInstant is a single BST within a Persistent BST.
type BSTInstant struct {
*BST
instant float64
}

// ThisInstant returns the subtree at the most recent
// instant set
func (pbst *FullPersistentBST) ThisInstant() search.Dynamic {
return pbst.instants[pbst.index]
}

// AtInstant returns the subtree of pbst at the given instant
func (pbst *FullPersistentBST) AtInstant(ins float64) search.Dynamic {
// binary search
bot := 0
top := len(pbst.instants) - 1
var mid int
for {
if top <= bot {
// round down
if pbst.instants[bot].instant > ins {
bot--
}
return pbst.instants[bot]
}
mid = (bot + top) / 2
v := pbst.instants[mid].instant
if v == ins {
return pbst.instants[mid]
} else if v < ins {
bot = mid + 1
} else {
top = mid - 1
}
}
}

// ToStaticPersistent returns a static peristent version
// of the pbst
func (pbst *FullPersistentBST) ToStaticPersistent() search.StaticPersistent {
// Todo
return nil
}

// MinInstant returns the minimum instant ever set on pbst.
func (pbst *FullPersistentBST) MinInstant() float64 {
return pbst.instants[0].instant
}

// MaxInstant returns the maximum instant ever set on pbst.
func (pbst *FullPersistentBST) MaxInstant() float64 {
return pbst.instants[len(pbst.instants)-1].instant
}

// SetInstant increments the pbst to the given instant.
func (pbst *FullPersistentBST) SetInstant(ins float64) {
if ins < pbst.instant {
panic("Decreasing instants is not yet supported")
} else if ins == pbst.instant {
return
}
bsti := BSTInstant{}
bsti.BST = pbst.instants[len(pbst.instants)-1].copy()
bsti.instant = ins
pbst.instants = append(pbst.instants, bsti)
pbst.instant = ins
pbst.index++
}

// Insert peforms Insert on the current set instant's search tree.
func (pbst *FullPersistentBST) Insert(n search.Node) error {
return pbst.AtInstant(pbst.instant).Insert(n)
}

// Delete performs Delete on the current set instant's search tree.
func (pbst *FullPersistentBST) Delete(n search.Node) error {
return pbst.AtInstant(pbst.instant).Delete(n)
}

// ToStatic performs ToStatic on the current set instant's search tree.
func (pbst *FullPersistentBST) ToStatic() search.Static {
return pbst.AtInstant(pbst.instant).ToStatic()
}

// Size performs Size on the current set instant's search tree.
func (pbst *FullPersistentBST) Size() int {
return pbst.AtInstant(pbst.instant).Size()
}

// InOrderTraverse performs InOrderTraverse on the current
// set instant's search tree.
func (pbst *FullPersistentBST) InOrderTraverse() []search.Node {
return pbst.AtInstant(pbst.instant).InOrderTraverse()
}

// Search performs Search on the current set instant's search tree.
func (pbst *FullPersistentBST) Search(f interface{}) (bool, interface{}) {
return pbst.AtInstant(pbst.instant).Search(f)
}

// SearchDown performs SearchDown on the current set instant's search tree.
func (pbst *FullPersistentBST) SearchDown(f interface{}, d int) (search.Comparable, interface{}) {
return pbst.AtInstant(pbst.instant).SearchDown(f, d)
}

// SearchUp performs SearchUp on the current set instant's search tree.
func (pbst *FullPersistentBST) SearchUp(f interface{}, u int) (search.Comparable, interface{}) {
return pbst.AtInstant(pbst.instant).SearchUp(f, u)
}

// String returns a string representation of pbst.
func (pbst *FullPersistentBST) String() string {
s := ""
for _, ins := range pbst.instants {
s += printutil.Stringf64(ins.instant) + ":\n"
s += ins.BST.String()
}
return s
}
62 changes: 62 additions & 0 deletions search/tree/persistent_test.go
Original file line number Diff line number Diff line change
@@ -1,2 +1,64 @@
package tree

import (
"testing"

"github.com/stretchr/testify/assert"
)

var (
instantInputs1 = [][]testNode{
{{1, 1}},
{{2, 1}},
{{3, 1}},
{{4, 1}},
{{5, 1}},
{{6, 1}},
{{7, 1}},
{{8, 1}},
{{9, 1}},
{{10, 1}},
}
)

func TestPBSTDefinedInput1(t *testing.T) {
tree := New(RedBlack).ToPersistent()
for i, ls := range instantInputs1 {
tree.SetInstant(float64(i))
for _, v := range ls {
err := tree.Insert(v)
assert.Nil(t, err)
}
}
for i := range instantInputs1 {
t2 := tree.AtInstant(float64(i))
for j, ls2 := range instantInputs1 {
if j > i {
break
}
for _, v := range ls2 {
found, _ := t2.Search(v.key)
assert.True(t, found)
}
}
}
for i, ls := range instantInputs1 {
tree.SetInstant(float64(len(instantInputs1) + i))
for _, v := range ls {
err := tree.Delete(v)
assert.Nil(t, err)
}
}
for i := range instantInputs1 {
t2 := tree.AtInstant(float64(len(instantInputs1) + i))
for j, ls2 := range instantInputs1 {
if j > i {
break
}
for _, v := range ls2 {
found, _ := t2.Search(v.key)
assert.False(t, found)
}
}
}
}
8 changes: 4 additions & 4 deletions search/tree/rb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,16 +191,16 @@ func TestPredSucc(t *testing.T) {
tree.Insert(v)
}

_, v := tree.SearchUp(9.5)
_, v := tree.SearchUp(9.5, 0)
assert.Equal(t, v, compFloat(1))
_, v = tree.SearchDown(9.5)
_, v = tree.SearchDown(9.5, 0)
assert.Equal(t, v, compFloat(2))

t2 := tree.ToStatic()

_, v = t2.SearchUp(9.5)
_, v = t2.SearchUp(9.5, 0)
assert.Equal(t, v, compFloat(1))
_, v = t2.SearchDown(9.5)
_, v = t2.SearchDown(9.5, 0)
assert.Equal(t, v, compFloat(2))

}
Expand Down

0 comments on commit 9683fcc

Please sign in to comment.