Franck Pommereau

improved Go backend performance

......@@ -7,3 +7,4 @@ __pycache__
.*.swp
.#*
#*
/libs/go/**/pkg/
......
......@@ -6,16 +6,52 @@ package dicts
import (
"bytes"
"fmt"
"hash/fnv"
"reflect"
)
type Hashable interface {
Hash () uint64
Eq (other interface{}) bool
//
// hash any value
//
const _FREE int64 = -1
const _DUMMY int64 = -2
func Hash (value interface{}) uint64 {
h, err := doHash(value, nil)
if err != nil {
panic(err)
}
i := int64(h)
if i < 0 {
return uint64(-i)
} else {
return uint64(i)
}
}
//
// compare any values
//
type equatable interface {
Eq (interface{}) bool
}
func Eq (a, b interface{}) bool {
i, ok := a.(equatable)
if ok {
return i.Eq(b)
}
return reflect.DeepEqual(a, b)
}
//
// dict type
//
type Item struct {
Key *Hashable
Key *interface{}
Value *interface{}
hash uint64
}
......@@ -25,25 +61,50 @@ type Dict struct {
itemlist []Item
used uint64
filled uint64
keyhash uint64
}
func hash (key Hashable) uint64 {
h := int64(key.Hash())
if h < 0 {
return uint64(-h)
} else {
return uint64(h)
}
func (self *Dict) Clear () {
self.indices = make(map[uint64]int64)
self.itemlist = make([]Item, 0)
self.used = 0
self.filled = 0
self.keyhash = 0
}
func StringHash (s string) uint64 {
hash := fnv.New64()
hash.Write([]byte(s))
return hash.Sum64()
}
type copyfunc func(interface{})interface{}
const _FREE int64 = -1
const _DUMMY int64 = -2
func (self Dict) Copy (copiers ...copyfunc) Dict {
d := Dict{}
d.indices = make(map[uint64]int64)
for k, v := range self.indices {
d.indices[k] = v
}
d.itemlist = make([]Item, len(self.itemlist))
if len(copiers) == 0 {
copy(d.itemlist, self.itemlist)
} else if len(copiers) == 1 {
cpk := copiers[0]
for index, item := range self.itemlist {
k := cpk(*(item.Key))
d.itemlist[index] = Item{&k, item.Value, item.hash}
}
} else if len(copiers) == 2 {
cpk := copiers[0]
cpv := copiers[1]
for index, item := range self.itemlist {
k := cpk(*(item.Key))
v := cpv(*(item.Value))
d.itemlist[index] = Item{&k, &v, item.hash}
}
} else {
panic("at most two copiers are allowed")
}
d.used = self.used
d.filled = self.filled
d.keyhash = self.keyhash
return d
}
func MakeDict (items ...Item) Dict {
d := Dict{}
......@@ -54,13 +115,6 @@ func MakeDict (items ...Item) Dict {
return d
}
func (self *Dict) Clear () {
self.indices = make(map[uint64]int64)
self.itemlist = make([]Item, 0)
self.used = 0
self.filled = 0
}
func (self Dict) Len () uint64 {
return self.used
}
......@@ -83,42 +137,52 @@ func (self *probe) next () uint64 {
return self.i
}
func (self Dict) lookup (key Hashable, hashvalue uint64) (int64, uint64) {
var freeslot *uint64 = nil
func (self Dict) lookup (key interface{}, hashvalue uint64) (int64, uint64) {
var freeslot uint64
var fsempty bool = true
for i, p := first_probe(hashvalue); true; i = p.next() {
index, found := self.indices[i]
if ! found {
if freeslot == nil {
if fsempty {
return _FREE, i
} else {
return _DUMMY, *freeslot
return _DUMMY, freeslot
}
} else if index == _DUMMY {
if freeslot == nil {
freeslot = new(uint64)
*freeslot = i
if fsempty {
fsempty = false
freeslot = i
}
} else {
item := self.itemlist[index]
if item.Key == &key || item.hash == hashvalue && (*item.Key).Eq(key) {
if item.Key == &key || item.hash == hashvalue && Eq(*(item.Key), key) {
return index, i
}
}
}
// never reached
panic("unreachable code has been reached")
return 0, 0
}
func (self Dict) Get (key Hashable) *interface{} {
index, _ := self.lookup(key, hash(key))
func (self Dict) Get (key interface{}) *interface{} {
index, _ := self.lookup(key, Hash(key))
if index < 0 {
return nil
}
return self.itemlist[index].Value
}
func (self Dict) Fetch (key Hashable, fallback interface{}) *interface{} {
index, _ := self.lookup(key, hash(key))
func (self Dict) GetItem (key interface{}) *Item {
index, _ := self.lookup(key, Hash(key))
if index < 0 {
return nil
}
return &self.itemlist[index]
}
func (self Dict) Fetch (key interface{}, fallback interface{}) *interface{} {
index, _ := self.lookup(key, Hash(key))
if index < 0 {
return &fallback
} else {
......@@ -126,8 +190,8 @@ func (self Dict) Fetch (key Hashable, fallback interface{}) *interface{} {
}
}
func (self *Dict) Set (key Hashable, value interface{}) {
hashvalue := hash(key)
func (self *Dict) Set (key interface{}, value interface{}) {
hashvalue := Hash(key)
index, i := self.lookup(key, hashvalue)
if index < 0 {
self.indices[i] = int64(self.used)
......@@ -135,14 +199,16 @@ func (self *Dict) Set (key Hashable, value interface{}) {
self.used++
if index == _FREE {
self.filled++
}
}
self.keyhash += hashvalue
} else {
self.itemlist[index] = Item{&key, &value, hashvalue}
}
}
func (self *Dict) Del (key Hashable) {
index, i := self.lookup(key, hash(key))
func (self *Dict) Del (key interface{}) {
hashvalue := Hash(key)
index, i := self.lookup(key, hashvalue)
if index < 0 {
return
}
......@@ -158,6 +224,7 @@ func (self *Dict) Del (key Hashable) {
self.itemlist[index] = lastitem
}
self.itemlist = self.itemlist[:self.used]
self.keyhash -= hashvalue
}
type DictIterator struct {
......@@ -171,7 +238,7 @@ func (self *DictIterator) Next () *Item {
return nil
} else {
return &(self.d.itemlist[self.i])
}
}
}
func (self Dict) Iter () (DictIterator, *Item) {
......@@ -183,8 +250,8 @@ func (self Dict) Iter () (DictIterator, *Item) {
}
}
func (self Dict) Has (key Hashable) bool {
index, _ := self.lookup(key, hash(key))
func (self Dict) Has (key interface{}) bool {
index, _ := self.lookup(key, Hash(key))
return index >= 0
}
......@@ -194,18 +261,53 @@ func (self *Dict) Pop () Item {
}
item := self.itemlist[self.used-1]
self.Del(*(item.Key))
self.keyhash -= item.hash
return item
}
func (self Dict) Hash () uint64 {
var h uint64 = 1959494633841095838 + self.keyhash
for i := uint64(0); i < self.used; i++ {
h += 5 * Hash(*(self.itemlist[i].Value)) + 1
}
return h
}
func (self Dict) Eq (other interface{}) bool {
d, ok := other.(Dict)
if ok {
if self.Len() != d.Len() {
return false
} else if self.keyhash != d.keyhash {
return false
}
for i := uint64(0); i < self.used; i++ {
value := d.Get(*(self.itemlist[i].Key))
if value == nil {
return false
} else if ! Eq(*(self.itemlist[i].Value), *(value)) {
return false
}
}
return true
} else {
return false
}
}
//
//
//
func (self Dict) String () string {
buf := bytes.NewBufferString("{")
for i := uint64(0); i < self.used; i++ {
if i > 0 {
buf.WriteString(", ")
}
buf.WriteString(fmt.Sprint(*(self.itemlist[i].Key)))
buf.WriteString(fmt.Sprintf("%#v", *(self.itemlist[i].Key)))
buf.WriteString(": ")
buf.WriteString(fmt.Sprint(*(self.itemlist[i].Value)))
buf.WriteString(fmt.Sprintf("%#v", *(self.itemlist[i].Value)))
}
buf.WriteString("}")
return buf.String()
......@@ -213,7 +315,7 @@ func (self Dict) String () string {
func (self Item) String () string {
return fmt.Sprintf("Item{%s}",
fmt.Sprintf("%s, %s, %d",
fmt.Sprintf("%#v, %#v, %#v",
fmt.Sprint(*(self.Key)),
fmt.Sprint(*(self.Value)),
self.hash))
......
package hashstructure
// Adapted from https://github.com/mitchellh/hashstructure
// to call Hash() method when found.
// The MIT License (MIT)
//
// Copyright (c) 2016 Mitchell Hashimoto
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package dicts
import (
"encoding/binary"
......@@ -8,6 +33,20 @@ import (
"reflect"
)
// Includable is an interface that can optionally be implemented by
// a struct. It will be called for each field in the struct to check whether
// it should be included in the hash.
type Includable interface {
HashInclude(field string, v interface{}) (bool, error)
}
// IncludableMap is an interface that can optionally be implemented by
// a struct. It will be called when a map-type field is found to ask the
// struct if the map item should be included in the hash.
type IncludableMap interface {
HashIncludeMap(field string, k, v interface{}) (bool, error)
}
// ErrNotStringer is returned when there's an error with hash:"string"
type ErrNotStringer struct {
Field string
......@@ -65,7 +104,7 @@ type HashOptions struct {
// * "string" - The field will be hashed as a string, only works when the
// field implements fmt.Stringer
//
func Hash(v interface{}, opts *HashOptions) (uint64, error) {
func doHash(v interface{}, opts *HashOptions) (uint64, error) {
// Create default options
if opts == nil {
opts = &HashOptions{}
......@@ -104,7 +143,18 @@ type visitOpts struct {
StructField string
}
type hashable interface {
Hash () uint64
}
func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
// Call method Hash() is any
i, ok := v.Interface().(hashable)
if ok {
return i.Hash(), nil
}
t := reflect.TypeOf(0)
// Loop since these can be wrapped in multiple layers of pointers
......
The MIT License (MIT)
Copyright (c) 2016 Mitchell Hashimoto
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# hashstructure [![GoDoc](https://godoc.org/github.com/mitchellh/hashstructure?status.svg)](https://godoc.org/github.com/mitchellh/hashstructure)
hashstructure is a Go library for creating a unique hash value
for arbitrary values in Go.
This can be used to key values in a hash (for use in a map, set, etc.)
that are complex. The most common use case is comparing two values without
sending data across the network, caching values locally (de-dup), and so on.
## Features
* Hash any arbitrary Go value, including complex types.
* Tag a struct field to ignore it and not affect the hash value.
* Tag a slice type struct field to treat it as a set where ordering
doesn't affect the hash code but the field itself is still taken into
account to create the hash value.
* Optionally specify a custom hash function to optimize for speed, collision
avoidance for your data set, etc.
* Optionally hash the output of `.String()` on structs that implement fmt.Stringer,
allowing effective hashing of time.Time
## Installation
Standard `go get`:
```
$ go get github.com/mitchellh/hashstructure
```
## Usage & Example
For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/hashstructure).
A quick code example is shown below:
```go
type ComplexStruct struct {
Name string
Age uint
Metadata map[string]interface{}
}
v := ComplexStruct{
Name: "mitchellh",
Age: 64,
Metadata: map[string]interface{}{
"car": true,
"location": "California",
"siblings": []string{"Bob", "John"},
},
}
hash, err := hashstructure.Hash(v, nil)
if err != nil {
panic(err)
}
fmt.Printf("%d", hash)
// Output:
// 2307517237273902113
```
package hashstructure
import (
"fmt"
)
func ExampleHash() {
type ComplexStruct struct {
Name string
Age uint
Metadata map[string]interface{}
}
v := ComplexStruct{
Name: "mitchellh",
Age: 64,
Metadata: map[string]interface{}{
"car": true,
"location": "California",
"siblings": []string{"Bob", "John"},
},
}
hash, err := Hash(v, nil)
if err != nil {
panic(err)
}
fmt.Printf("%d", hash)
// Output:
// 6691276962590150517
}
This diff is collapsed. Click to expand it.
package hashstructure
// Includable is an interface that can optionally be implemented by
// a struct. It will be called for each field in the struct to check whether
// it should be included in the hash.
type Includable interface {
HashInclude(field string, v interface{}) (bool, error)
}
// IncludableMap is an interface that can optionally be implemented by
// a struct. It will be called when a map-type field is found to ask the
// struct if the map item should be included in the hash.
type IncludableMap interface {
HashIncludeMap(field string, k, v interface{}) (bool, error)
}
......@@ -8,23 +8,23 @@ func StateSpace (init func()Marking, addsucc func(Marking, Set),
var succ Set
count := 1
i := init()
todo := MakeQueue(&i)
seen := MakeSet(&i)
todo := MakeQueue(i)
seen := MakeSet(i)
for ! todo.Empty() {
state := todo.Get()
if print_states {
fmt.Println(state)
}
succ = MakeSet()
addsucc(*state, succ)
for _, s := range succ.data {
if found, p := seen.Get(s); found {
s = p
addsucc(state, succ)
for it, s := succ.Iter(); s != nil; s = it.Next(){
if found, p := seen.Get(*s); found {
s = &p
} else {
count += 1
s.SetId(count)
seen.AddPtr(s)
todo.Put(s)
seen.Add(*s)
todo.Put(*s)
}
if print_succs {
fmt.Println(" >", s)
......@@ -38,25 +38,26 @@ func DeadLocks (init func()Marking, addsucc func(Marking, Set), print bool) int
var succ Set
count := 1
i := init()
todo := MakeQueue(&i)
seen := MakeSet(&i)
todo := MakeQueue(i)
seen := MakeSet(i)
for ! todo.Empty() {
state := todo.Get()
succ = MakeSet()
addsucc(*state, succ)
addsucc(state, succ)
if succ.Empty() {
if print {
fmt.Println(state)
}
count++
} else {
for _, s := range succ.data {
if found, p := seen.Get(s); found {
s = p
for it, s := succ.Iter(); s != nil; s = it.Next(){
if found, p := seen.Get(*s); found {
s = &p
} else {
s.SetId(seen.Len())
seen.AddPtr(s)
todo.Put(s)
count += 1
s.SetId(count)
seen.Add(*s)
todo.Put(*s)
}
}
}
......@@ -66,12 +67,12 @@ func DeadLocks (init func()Marking, addsucc func(Marking, Set), print bool) int
func LabelledTransitionsSystem (init func()Marking, itersucc SuccIterFunc) {
i := init()
todo := MakeQueue(&i)
seen := MakeSet(&i)
todo := MakeQueue(i)
seen := MakeSet(i)
for ! todo.Empty() {
state := todo.Get()
fmt.Println(state)
for i, p := Iter(itersucc, *state); p != nil; p = i.Next() {
for i, p := Iter(itersucc, state); p != nil; p = i.Next() {
// print trans & mode
fmt.Print("@ ", p.Name, " = {")
first := true
......@@ -89,12 +90,12 @@ func LabelledTransitionsSystem (init func()Marking, itersucc SuccIterFunc) {
fmt.Println(" - ", p.Sub)
fmt.Println(" + ", p.Add)
s := state.Copy().Sub(p.Sub).Add(p.Add)
if found, old := seen.Get(&s); found {
if found, old := seen.Get(s); found {
fmt.Println(" > ", old)
} else {
s.SetId(seen.Len())
s.SetId(int(seen.Len()))
seen.Add(s)
todo.Put(&s)
todo.Put(s)
fmt.Println(" > ", s)
}
}
......
......@@ -2,7 +2,6 @@ package zn
import "fmt"
import "bytes"
import "hash/fnv"
import "dicts"
type Marking struct {
......@@ -14,6 +13,10 @@ func (self *Marking) SetId (id int) {
self.i = id
}
func (self Marking) GetId () int {
return self.i
}
func MakeMarking (id ...int) Marking {
d := dicts.MakeDict()
if len(id) == 0 {
......@@ -26,36 +29,20 @@ func MakeMarking (id ...int) Marking {
}
func (self Marking) Hash () uint64 {
var h uint64 = 2471033218594493899
hash := fnv.New64()
for iter, item := self.d.Iter(); item != nil; item = iter.Next() {
hash.Reset()
hash.Write([]byte(fmt.Sprintf("[%s]{%x}",
fmt.Sprint(*(item.Key)),
(*item.Value).(Mset).Hash())))
h ^= hash.Sum64()
}
return h
}
type place struct {
s string
}
func (self place) Hash () uint64 {
return dicts.StringHash(self.s)
return self.d.Hash()
}
func (self place) Eq (other interface{}) bool {
if val, isplace := other.(place); isplace {
return val.s == self.s
func (self Marking) Eq (other interface{}) bool {
m, ok := other.(Marking)
if ok {
return self.d.Eq(*(m.d))
} else {
return false
}
}
func (self Marking) Has (p string) bool {
return self.d.Has(place{p})
return self.d.Has(p)
}
//### a := zn.MakeMarking()
......@@ -91,28 +78,14 @@ func (self Marking) Has (p string) bool {
//... a.Hash() == b.Hash()
//=== true
func (self Marking) Eq (other Marking) bool {
if self.d.Len() != other.d.Len() {
return false
}
for iter, p, m := self.Iter(); p != nil; p, m = iter.Next() {
if ! other.d.Has(place{*p}) {
return false
} else if ! m.Eq(other.Get(*p)) {
return false
}
}
return true
}
//+++ zn.MakeMarking().Eq(zn.MakeMarking())
func (self Marking) Set (p string, tokens ...interface{}) {
if len(tokens) == 0 {
self.d.Del(place{p})
self.d.Del(p)
} else {
m := MakeMset(tokens...)
self.d.Set(place{p}, m)
self.d.Set(p, m)
}
}
......@@ -136,7 +109,7 @@ func (self Marking) Update (p string, tokens Mset) {
m := self.Get(p)
m.Add(tokens)
} else {
self.d.Set(place{p}, tokens.Copy())
self.d.Set(p, tokens.Copy())
}
}
......@@ -150,12 +123,17 @@ func (self Marking) Update (p string, tokens Mset) {
//... a.Eq(b)
//=== true
func copykey (k interface{}) interface{} {
return k
}
func copyval (v interface{}) interface{} {
return v.(Mset).Copy()
}
func (self Marking) Copy () Marking {
copy := MakeMarking()
for iter, p, m := self.Iter(); p != nil; p, m = iter.Next() {
copy.Update(*p, *m)
}
return copy
dict := self.d.Copy(copykey, copyval)
return Marking{&dict, self.i}
}
//### a := zn.MakeMarking()
......@@ -204,7 +182,7 @@ func (self Marking) Copy () Marking {
//=== false
func (self Marking) Get (p string) Mset {
return (*(self.d.Fetch(place{p}, MakeMset()))).(Mset)
return (*(self.d.Fetch(p, MakeMset()))).(Mset)
}
//### a := zn.MakeMarking()
......@@ -283,7 +261,7 @@ func (self Marking) Sub (other Marking) Marking {
for iter, p, m := other.Iter(); p != nil; p, m = iter.Next() {
mine := self.Get(*p)
if m.Geq(mine) {
self.d.Del(place{*p})
self.d.Del(*p)
} else {
mine.Sub(*m)
}
......@@ -367,9 +345,9 @@ func (self MarkingIterator) Next () (*string, *Mset) {
if next == nil {
return nil, nil
} else {
p := (*next.Key).(place)
p := (*next.Key).(string)
m := (*next.Value).(Mset)
return &(p.s), &m
return &p, &m
}
}
......@@ -379,9 +357,9 @@ func (self Marking) Iter () (MarkingIterator, *string, *Mset) {
if item == nil {
return myiter, nil, nil
} else {
p := (*item.Key).(place)
p := (*item.Key).(string)
m := (*item.Value).(Mset)
return myiter, &(p.s), &m
return myiter, &p, &m
}
}
......
......@@ -2,8 +2,6 @@ package zn
import "fmt"
import "bytes"
import "hash/fnv"
import "hashstructure"
import "dicts"
type Mset struct {
......@@ -11,44 +9,18 @@ type Mset struct {
}
func (self Mset) Hash () uint64 {
var h uint64 = 13124430844775843711
hash := fnv.New64()
for iter, item := self.d.Iter(); item != nil; item = iter.Next() {
hv, err := hashstructure.Hash(*(item.Key), nil)
if err != nil {
panic(err)
}
hash.Reset()
hash.Write([]byte(fmt.Sprintf("[%x]{%x}", hv, *(item.Value))))
h ^= hash.Sum64()
}
return h
}
type AsString struct {
val *interface{}
}
func (self AsString) Hash () uint64 {
return dicts.StringHash(fmt.Sprint(*(self.val)))
return self.d.Hash()
}
func (self AsString) Eq (other interface{}) bool {
if v, ok := other.(AsString); ok {
return fmt.Sprint(*(self.val)) == fmt.Sprint(*(v.val))
func (self Mset) Eq (other interface{}) bool {
m, ok := other.(Mset)
if ok {
return self.d.Eq(*(m.d))
} else {
return fmt.Sprint(*(self.val)) == fmt.Sprint(other)
return false
}
}
func i2h (v interface{}) dicts.Hashable {
return AsString{&v}
}
func h2i (v *dicts.Hashable) *interface{} {
return (*v).(AsString).val
}
//+++ zn.MakeMset(1, 2, 2, 3, 3, 3).Hash() == zn.MakeMset(3, 3, 3, 2, 2, 1).Hash()
//+++ zn.MakeMset(1, 2, 2, 3, 3, 3).Hash() == zn.MakeMset(3, 2, 1, 3, 2, 3).Hash()
......@@ -56,27 +28,12 @@ func MakeMset (values ...interface{}) Mset {
dict := dicts.MakeDict()
mset := Mset{&dict}
for _, elt := range values {
h := i2h(elt)
count := (*mset.d.Fetch(h, uint64(0))).(uint64)
mset.d.Set(h, count + 1)
count := (*mset.d.Fetch(elt, uint64(0))).(uint64)
mset.d.Set(elt, count + 1)
}
return mset
}
func (self Mset) Eq (other Mset) bool {
if self.d.Len() != other.d.Len() {
return false
}
for iter, item := self.d.Iter(); item != nil; item = iter.Next() {
if ! other.d.Has(*(item.Key)) {
return false
} else if (*item.Value).(uint64) != (*other.d.Get(*(item.Key))).(uint64) {
return false
}
}
return true
}
//+++ zn.MakeMset().Eq(zn.MakeMset())
//--- zn.MakeMset().Eq(zn.MakeMset(1, 2, 3))
//--- zn.MakeMset().Eq(zn.MakeMset(1, 1, 1))
......@@ -85,11 +42,8 @@ func (self Mset) Eq (other Mset) bool {
//--- zn.MakeMset(1, 1, 1).Eq(zn.MakeMset(2, 2, 2))
func (self Mset) Copy () Mset {
copy := MakeMset()
for iter, item := self.d.Iter(); item != nil; item = iter.Next() {
copy.d.Set(*(item.Key), *(item.Value))
}
return copy
dict := self.d.Copy()
return Mset{&dict}
}
//+++ zn.MakeMset(1, 2, 2, 3, 3, 3).Copy().Eq(zn.MakeMset(1, 2, 2, 3, 3, 3))
......@@ -172,7 +126,7 @@ func (self Mset) Empty () bool {
//--- zn.MakeMset(1, 2).Empty()
func (self Mset) Count (value interface{}) uint64 {
return (*(self.d.Fetch(i2h(value), uint64(0)))).(uint64)
return (*(self.d.Fetch(value, uint64(0)))).(uint64)
}
//### zn.MakeMset(1, 2, 2, 3, 3, 3).Count(1)
......@@ -204,7 +158,7 @@ func (self *MsetIterator) Next () *interface{} {
} else if self.dup {
self.count--
}
return h2i(self.current.Key)
return self.current.Key
}
func (self Mset) Iter () (MsetIterator, *interface{}) {
......@@ -213,14 +167,14 @@ func (self Mset) Iter () (MsetIterator, *interface{}) {
if item == nil {
return myiter, nil
} else {
return myiter, h2i(item.Key)
return myiter, item.Key
}
}
func (self Mset) IterDup () (MsetIterator, *interface{}) {
iter, item := self.d.Iter()
myiter := MsetIterator{iter, true, (*(item.Value)).(uint64) - 1, item}
return myiter, h2i(item.Key)
return myiter, item.Key
}
//### a := zn.MakeMset(1, 2, 2, 3, 3, 3)
......@@ -263,10 +217,10 @@ type mapfunc func (interface{}, uint64) (interface{}, uint64)
func (self Mset) Map (f mapfunc) Mset {
copy := MakeMset()
for iter, item := self.d.Iter(); item != nil; item = iter.Next() {
k := *h2i(item.Key)
k := *(item.Key)
v := (*(item.Value)).(uint64)
k, v = f(k, v)
copy.d.Set(i2h(k), v)
copy.d.Set(k, v)
}
return copy
}
......
......@@ -6,7 +6,7 @@ type Queue struct {
data map[uint64]*Marking
}
func MakeQueue (markings ...*Marking) Queue {
func MakeQueue (markings ...Marking) Queue {
q := Queue{0, 0, make(map[uint64]*Marking)}
for _, m := range markings {
q.Put(m)
......@@ -22,20 +22,20 @@ func (self Queue) Full () bool {
return self.head == self.tail+1
}
func (self *Queue) Put (m *Marking) {
func (self *Queue) Put (m Marking) {
if self.Full() {
panic("queue is full")
}
self.data[self.tail] = m
self.data[self.tail] = &m
self.tail++
}
func (self *Queue) Get () *Marking {
func (self *Queue) Get () Marking {
if self.Empty() {
panic("queue is empty")
}
m := self.data[self.head]
delete(self.data, self.head)
self.head++
return m
return *m
}
......
package zn
import "dicts"
type Set struct {
data map[uint64]*Marking
d *dicts.Dict
}
type _z struct {
}
func (self _z) Hash () uint64 {
return 8806599771745799646
}
func (self _z) Eq (other interface{}) bool {
_, ok := other.(_z)
if ok {
return true
} else {
return false
}
}
//*** a := zn.MakeMarking()
......@@ -11,84 +29,102 @@ type Set struct {
//*** c := b.Copy()
//*** c.Set("p3", 3)
func MakeSet (markings ...*Marking) Set {
set := Set{make(map[uint64]*Marking)}
func MakeSet (markings ...Marking) Set {
dict := dicts.MakeDict()
for _, m := range markings {
set.AddPtr(m)
dict.Set(m, _z{})
}
return set
return Set{&dict}
}
func (self Set) Empty () bool {
return len(self.data) == 0
return self.d.Len() == 0
}
func (self Set) NotEmpty () bool {
return len(self.data) > 0
return self.d.Len() > 0
}
//+++ zn.MakeSet().Empty()
//--- zn.MakeSet(&a).Empty()
//--- zn.MakeSet(a).Empty()
//--- zn.MakeSet().NotEmpty()
//+++ zn.MakeSet(&a).NotEmpty()
//+++ zn.MakeSet(a).NotEmpty()
func (self Set) Len () int {
return len(self.data)
func (self Set) Len () uint64 {
return self.d.Len()
}
//+++ zn.MakeSet().Len() == 0
//+++ zn.MakeSet(&a).Len() == 1
//+++ zn.MakeSet(&a, &a).Len() == 1
func (self Set) lookup (m *Marking) (uint64, bool) {
slot := m.Hash()
perturb := slot
for true {
if value, found := self.data[slot]; !found {
return slot, false
} else if value.Eq(*m) {
return slot, true
} else {
slot = (5 * slot) + 1 + perturb
perturb >>= 5
}
}
return 0, false
}
//+++ zn.MakeSet(a).Len() == 1
//+++ zn.MakeSet(a, a).Len() == 1
func (self *Set) Add (m Marking) {
self.AddPtr(&m)
}
func (self *Set) AddPtr (m *Marking) {
if slot, found := self.lookup(m); !found {
self.data[slot] = m
}
self.d.Set(m, _z{})
}
//### s := zn.MakeSet(&a, &b)
//### s := zn.MakeSet(a, b)
//... s.Len()
//=== 2
//### s := zn.MakeSet(&a, &b)
//### s := zn.MakeSet(a, b)
//... s.Add(c)
//... s.Add(c)
//... s.Len()
//=== 3
func (self Set) Get (m *Marking) (bool, *Marking) {
if slot, found := self.lookup(m); found {
return true, self.data[slot]
func (self Set) Get (m Marking) (bool, Marking) {
i := self.d.GetItem(m)
if i == nil {
return false, Marking{nil, -1}
} else {
return false, nil
return true, (*(i.Key)).(Marking)
}
}
func (self Set) Has (m *Marking) bool {
found, _ := self.Get(m)
return found
//### x := a.Copy()
//... x.SetId(42)
//... s := zn.MakeSet(x, b)
//... s.Get(a)
//=== true [42] {"p1": [1]}
func (self Set) Has (m Marking) bool {
return self.d.Has(m)
}
//+++ zn.MakeSet(a, b).Has(a)
//+++ zn.MakeSet(a, b).Has(b)
//--- zn.MakeSet(a, b).Has(c)
type SetIterator struct {
i dicts.DictIterator
}
func (self *SetIterator) Next () *Marking {
n := self.i.Next()
if n == nil {
return nil
} else {
m := (*(n.Key)).(Marking)
return &m
}
}
func (self Set) Iter () (SetIterator, *Marking) {
i, f := self.d.Iter()
if f == nil {
return SetIterator{i}, nil
} else {
m := (*(f.Key)).(Marking)
return SetIterator{i}, &m
}
}
//+++ zn.MakeSet(&a, &b).Has(&a)
//+++ zn.MakeSet(&a, &b).Has(&b)
//--- zn.MakeSet(&a, &b).Has(&c)
//### a.SetId(1)
//... b.SetId(2)
//... c.SetId(3)
//... s := zn.MakeSet(a, b, c)
//... for i, m := s.Iter(); m != nil; m = i.Next() { fmt.Println(*m) }
//... nil
//=== [1] {"p1": [1]}
//=== [2] {"p1": [1], "p2": [2]}
//=== [3] {"p1": [1], "p2": [2], "p3": [3]}
......
# Referendum (https://mcc.lip6.fr/pdf/Referendum-form.pdf)
# parameters :
# - lang = coffee : annotation language
# - count = 8 : number of voters
lang coffee
net "Referendum" :
place v number = 0, 1, 2, 3, 4, 5, 6, 7
place y number
place n number
trans yes :
< v var = i
> y var = i
trans no :
< v var = i
> n var = i
# Referendum (https://mcc.lip6.fr/pdf/Referendum-form.pdf)
# parameters :
# - lang = go : annotation language
# - count = 8 : number of voters
lang go
net "Referendum" :
place v int = 0, 1, 2, 3, 4, 5, 6, 7
place y int
place n int
trans yes :
< v var = i
> y var = i
trans no :
< v var = i
> n var = i
# Referendum (https://mcc.lip6.fr/pdf/Referendum-form.pdf)
# parameters :
# - lang = python : annotation language
# - count = 8 : number of voters
lang python
net "Referendum" :
place v int = 0, 1, 2, 3, 4, 5, 6, 7
place y int
place n int
trans yes :
< v var = i
> y var = i
trans no :
< v var = i
> n var = i