Idiomatic way of implementing nested matrices in golang - data-structures

I am trying to represent a hypergraph in memory. Are there any better data structures for this task beside nested matrices? A nested matrix is a matrix which can have elements of both the "native" type (let's say int for the sake of simplicity) and matrices.
This is the beginning of such a matrix. Are there any rough edges in the code, to make it look more idiomatic? How to make it look more idiomatic?
The code:
package main
import "fmt"
type Matricial interface {
Put(interface{}, ...int)
Get(...int) interface{}
}
type Matrix struct {
Matricial
values map[int]interface{}
}
func NewMatrix() *Matrix {
m := &Matrix{}
m.values = make(map[int]interface{})
return m
}
func (m *Matrix) Set(atom interface{}, pos ...int) {
firstdim := pos[0]
if val, ok := m.values[firstdim]; ok {
fmt.Println("map key exists", val)
switch converted := val.(type) {
case int:
m.values[firstdim] = converted
default:
fmt.Println("ERR: unknown type: %T", val)
}
} else {
if len(pos[1:]) > 0 {
newm := NewMatrix()
m.values[firstdim] = newm
newm.Set(atom, pos[1:]...)
} else {
m.values[firstdim] = atom
}
}
}
func (m *Matrix) Get(pos ...int) interface{} {
if len(pos) == 1 {
return m.values[pos[0]]
} else {
switch accessor := m.values[pos[0]].(type) {
case Matricial:
return accessor.Get(pos[1:]...)
default:
return nil
}
}
return nil
}
func main() {
m := NewMatrix()
m.Set(42, 2, 3, 4)
m.Set(43, 0)
fmt.Println(m.Get(2, 3))
fmt.Println(m.Get(2, 3, 4))
fmt.Println(m.Get(0))
}
The data structure must allow connecting hyperedges with other hyperedges (i.e. handling hyperedges as though they were nodes).

A nested matrix (adopting your definition of the term) seems a reasonable representation for hypergraph, not knowing anything more about your application anyway. An example Go implementation is the power set example at Rosetta code.
It is not idiomatic to embed an interface. For example, if you rename the Put method of Matricial to be Set, which is what I think you meant, then you can just delete the Matricial field of Matrix and your program produces the same output.

Related

Operate on a struct with lots of pointers (especially to numbers)

I have quite a few data structures that contain mostly numbers, I get the data, do a calculation and return the result.
The thing is that all of those numbers can be zero and hence, I had to switch to using pointers (*int64 or *float64) so that the default is nil and not 0.
Unfortunately, I don't know of a solution to this in Go except using pointers.
The problem comes now in the Calculate() function that is implemented for all data structures:
type X struct {
A, B, C, D, E, F *int
// and much more
Result *float64
}
func (x *X) Calculate() {
floatptr := func(f float64) *float64 { return &f }
x.Result = floatptr(float64(*x.A + *x.B + *x.C + *x.D + *x.E + *x.F))
}
This function will obviously panic if any of the data is nil. So, I wrote the functions differently that it checks for nil data before the calculation:
func (x *X) CalculateWithNilChecks() {
floatptr := func(f float64) *float64 { return &f }
if x.A == nil || x.B == nil || x.C == nil || x.D == nil || x.E == nil || x.F == nil {
return
}
x.Result = floatptr(float64(*x.A + *x.B + *x.C + *x.D + *x.E + *x.F))
}
The problem is that the data structures are quite long. Having a SUPER long if x != nil looks ugly. I was wondering if there is another (cleaner) way to doing this.
I thought of doing like in the encoding/json and just recover nil pointer dereference panics, not sure if this is cleaner TBH.
Another thought was to reflect the data structures and stop if any of the required data is nil, I don't think this should be necessary for such a simple task.
Here is a playground link for the above code
What am I missing here? Thanks!
As general solution you can unmarshal your JSON into a map of *int pointers or json.RawMessage and then use a reflection to cross check with your struct or just check it with expected number of fields.
func main() {
result := make(map[string]*int)
str := `{ "A": 1, "B": 2, "C": 3, "D": 4, "E": 5, "F": 6 }`
json.Unmarshal([]byte(str), &result)
for _, field := range result {
// Check if expect fields exists using reflection or manually
// ...
}
}
You can use reflect module and error when one of the required fields is missing.
Use this as template.
package main
import (
"fmt"
"reflect"
)
type X struct {
A, B, C, D, E, F *int
Result *float64
}
func (x *X) PrintFoo() {
fmt.Println(x.A)
}
func main() {
a := 3
x := X{A: &a}
val := reflect.ValueOf(x)
for i := 0; i < val.Type().NumField(); i++ {
field := val.Type().Field(i)
fieldType := fmt.Sprintf("%s", field.Type)
if fieldType == "*int" && val.FieldByName(field.Name).IsNil() {
fmt.Println("Missing value on field", field.Name)
}
}
}

Modifying receiver with a method on value?

package matrix
import (
"errors"
"strconv"
"strings"
)
// Matrix matrix inteface
type Matrix interface {
Rows() [][]int
Cols() [][]int
Set(r, c, val int) bool
}
// matrix implements the interface Matrix
type matrix struct {
data [][]int
rows int
cols int
}
// New returns a valid matrix created from the input
func New(input string) (Matrix, error) {
var m matrix
rows := strings.Split(input, "\n")
for r, row := range rows {
rowElements := strings.Fields(row)
switch {
case r == 0:
m.rows, m.cols = len(rows), len(rowElements)
matrix, err := allocateMemory(m.rows, m.cols)
if err != nil {
return invalidMatrix()
}
m.data = matrix
case len(rowElements) != m.cols:
return invalidMatrix()
}
for c, element := range rowElements {
element, err := strconv.Atoi(element)
if err != nil {
return invalidMatrix()
}
m.data[r][c] = element
}
}
return m, nil
}
// invalidMatrix returns the error indicating the
// provided matrix is invalid
func invalidMatrix() (Matrix, error) {
return nil, errors.New("invalid matrix")
}
// allocateMemory allocates a 2D slice of int having size RxC
func allocateMemory(R, C int) ([][]int, error) {
if R < 1 || C < 1 {
return nil, errors.New("invalid matrix")
}
matrix := make([][]int, R)
for r := range matrix {
matrix[r] = make([]int, C)
}
return matrix, nil
}
// Set sets the given value at (r,c) in the matrix,
// if (r,c) belongs to the matrix.
func (m matrix) Set(r, c, val int) bool {
switch {
case r < 0 || c < 0:
return false
case r >= m.rows || c >= m.cols:
return false
default:
m.data[r][c] = val
return true
}
}
// order defines the order the matrix to export
// two useful values are columnMajor and rowMajor
type order int
const (
columnMajor order = iota
rowMajor
)
// Cols returns columns of the matrix.
func (m matrix) Cols() [][]int {
return m.export(columnMajor)
}
// Rows returns rows of the matrix.
func (m matrix) Rows() [][]int {
return m.export(rowMajor)
}
// export return the matrix in the required order;
// either columnMajor or rowMajor.
func (m matrix) export(o order) [][]int {
var matrix [][]int
var err error
switch o {
case columnMajor:
matrix, err = allocateMemory(m.cols, m.rows)
if err != nil {
return nil
}
for r, row := range m.data {
for c, element := range row {
matrix[c][r] = element
}
}
case rowMajor:
matrix, err = allocateMemory(m.rows, m.cols)
if err != nil {
return nil
}
for r, row := range m.data {
copy(matrix[r], row)
}
}
return matrix
}
I am having a hard time understanding why the method Set() is able to modify the data of the struct. I had an understanding that methods defined on values cannot do that. I have tried to compare it with another problem where I cannot modify the content of receiver but in this case it just works. A test file for this code is available at test file. Any idea what I am missing?
The reason Set can modify the contents of the slice is that the slice is a reference value. Your other example (in the comment) attempts to assign the field holding the slice, and this won't work - because it's working on a copy. See this code sample:
package main
import (
"fmt"
)
type Holder struct {
s []int
v []int
}
func (h Holder) Set() {
// This will successfully modify the `s` slice's contents
h.s[0] = 99
// This will assign a new slice to a copy of the v field,
// so it won't affect the actual value on which this
// method is invoked.
h.v = []int{1, 2, 3}
}
func main() {
var h Holder
h.s = []int{10, 20, 30}
h.v = []int{40, 50, 60}
fmt.Println("before Set:", h)
h.Set()
fmt.Println("after Set:", h)
}
You can run it on the playground, and it prints:
before Set: {[10 20 30] [40 50 60]}
after Set: {[99 20 30] [40 50 60]}
What happens here is that even though Set gets a copy of h, and hence h.s is a copy too, but both copies point to the same underlying slice, so the contents can be modified. Read this post for all the details.
A slice value contains (ptr, len, cap) where ptr is a pointer to the slice's underlying array. The Set method modifies the slice's underlying array by dereferencing the pointer. The slice value, stored in the field, is not modified.
The Go Language blog post on slices describes the slice memory layout in more detail.

Building an interface

I wrote the below code that is working fine:
package main
import "fmt"
type hashMap interface {
}
type hashMap struct {
m map[hashable]hashable
k []hashable
}
type hashMap struct {
m map[T]T
k []T
}
// Methods required to enable sort: Len, Less, Swap > start
func (h *hashMap) Len() int {
return len(h.m)
}
func (h *hashMap) Less(i, j int) bool {
switch v := h.m[h.k[i]].(type) {
case int:
return v > h.m[h.k[j]].(int)
case float32:
return v > h.m[h.k[j]].(float32)
case float64:
return v > h.m[h.k[j]].(float64)
case string:
return v > h.m[h.k[j]].(string)
default:
return false
}
}
func (h *hashMap) Swap(i, j int) {
h.k[i], h.k[j] = h.k[j], h.k[i]
}
// Methods required to enable sort: Len, Less, Swap > end
// Build Ordered Map methods
func (h *hashMap) from(m map[T]T) hashMap {
h.m = m
h.k = make([]T, 0, len(m))
for key := range m {
h.k = append(h.k, key)
}
return *h
}
func main() {
inv := new(hashMap).from(map[T]T{"first:": 1, "second": 2})
fmt.Printf("%v", inv)
}
I would like to replace the empty interface type T interface {} using something like:
type T interface {
Len() int
Less() bool
Swap()
}
How can I do it?
You cannot do that in general.
Your hashMap contains a map[T]T. From https://golang.org/ref/spec#Map_types :
The comparison operators == and != must be fully defined for operands of the key type; thus the key type must not be a function, map, or slice. If the key type is an interface type, these comparison operators must be defined for the dynamic key values; failure will cause a run-time panic.
(emphasis added).
So this works only if your implementation of T has == and != defined. As these operators are not userdefinable only the builtin/predeclared types which define them can be used. So the only types you can use as Ts are the one you can use as normal map keys anyway. So you gain nothing.
(But honestly I have no idea what your interface T is good for, especially given that you cannot use that interface for sorting; or what your code is trying to do. This looks like a XY problem.)

A function that search for an interface{} over a slice of interface{} in Go

I'm trying to implement a function that takes an element of any type and a slice of the same type and search the first inside the second, giving it's position as result or -1 otherwise.
I'm not a Go expert, so my first thought was to pass the element to search as interface{} and the slice as []interface{}, but it didn't really work.
Here's what I tried:
package main
import (
"fmt"
)
func IsElementInListWithPos(element interface{}, list []interface{}) int {
for i := range list {
if list[i] == element {
return i
}
}
return -1
}
func main() {
list1 := []int{1, 2, 3, 4, 5, 6}
list2 := []string{"a", "b", "c", "d"}
pos1 := IsElementInListWithPos(3, list1)
pos2 := IsElementInListWithPos("a", list2)
fmt.Println(pos1, pos2)
}
It gives me the following errors:
cannot use list (type []int) as type []interface {} in argument to IsElementInListWithPos
cannot use list2 (type []string) as type []interface {} in argument to IsElementInListWithPos
Any idea how I could solve this issue without actually using two different functions?
Thanks in advance.
The sort package demonstrates how interfaces can be used to implement algorithms in a type-independent way.
Linear search requires two essential operations that depend on the haystack element type, Len and Equal. So we can write the following Haystack interface and a Search function that using it:
type Haystack interface {
Len() int
Equal(int, interface{}) bool
}
func Search(haystack Haystack, needle interface{}) int {
for i := 0; i < haystack.Len(); i++ {
if haystack.Equal(i, needle) {
return i
}
}
return -1
}
This makes writing implementations for Haystack simple, but not type-safe:
type Strings []string
func (s Strings) Len() int { return len(s) }
func (s Strings) Equal(i int, x interface{}) bool { return s[i] == x.(string) }
type Ints []int
func (s Ints) Len() int { return len(s) }
func (s Ints) Equal(i int, x interface{}) bool { return s[i] == x.(int) }
func main() {
strings := []string{"b", "a", "c", "d"}
fmt.Println(Search(Strings(strings), "c")) // 2
fmt.Println(Search(Strings(strings), "e")) // -1
ints := []int{2, 1, 3, 4}
fmt.Println(Search(Ints(ints), 3)) // 2
fmt.Println(Search(Ints(ints), 5)) // -1
}
Note the type assertions in the Equal methods. To make this type-safe we have to get rid of the interface{} argument to Equal:
type Haystack interface {
Len() int
Equal(int) bool
}
func Search(haystack Haystack) int {
for i := 0; i < haystack.Len(); i++ {
if haystack.Equal(i) {
return i
}
}
return -1
}
type Strings struct {
hs []string
needle string
}
func (s Strings) Len() int { return len(s.hs) }
func (s Strings) Equal(i int) bool { return s.hs[i] == s.needle }
type Ints struct {
hs []int
needle int
}
func (s Ints) Len() int { return len(s.hs) }
func (s Ints) Equal(i int) bool { return s.hs[i] == s.needle }
func main() {
strings := []string{"b", "a", "c", "d"}
fmt.Println(Search(Strings{strings, "c"})) // 2
fmt.Println(Search(Strings{strings, "e"})) // -1
ints := []int{2, 1, 3, 4}
fmt.Println(Search(Ints{ints, 3})) // 2
fmt.Println(Search(Ints{ints, 5})) // -1
}
This made both the interface implementations and using the Search function much more complicated.
The moral of the story is that using interfaces this way requires a sufficiently complicated algorithm to be worth the trouble. If writing the interface implementation for a particular type is more work than writing the concrete implementation for the algorithm, well, then just write the concrete functions you need:
func SearchStr(haystack []string, needle string) int {
for i, x := range haystack {
if x == needle {
return i
}
}
return -1
}
func SearchInt(haystack []int, needle int) int {
for i, x := range haystack {
if x == needle {
return i
}
}
return -1
}
func main() {
strings := []string{"b", "a", "c", "d"}
fmt.Println(SearchStr(strings, "c")) // 2
fmt.Println(SearchStr(strings, "e")) // -1
ints := []int{2, 1, 3, 4}
fmt.Println(SearchInt(ints, 3)) // 2
fmt.Println(SearchInt(ints, 5)) // -1
}
Currently, it is not possible to build a solution that respects all your criteria. It will be possible once generics are implemented. Or you could try building one using reflect, but that will yield a complex and potentially slow solution... so I generally advise against using reflect for something as simple as this (see second snippet below).
What you can do right now is to use something like:
func FindFirst(n int, f func(int) bool) int {
for i := 0; i < n; i++ {
if f(i) {
return i
}
}
return -1
}
// in your code (s is the slice, e the value you are searching for)
i := FindFirst(len(s), func(i int) bool {
return s[i] == e
})
if i != -1 {
// i is the index of the element with value e
}
This, as you can imagine, does not make much sense... as it's arguably simpler, faster, and more idiomatic to simply write out the loop explicitly:
// in your code (s is the slice, e the value you are searching for)
for i, v := range s {
if v == e {
_ = i // i is the index of the element with value e
break
}
}
Obviously, this whole approach (linear scan) is only reasonable if the number of elements in the slice is small. If your slice is big and changes rarely, it would arguably make more sense (from a time complexity perspective) to sort it (sort.Slice) first and then do binary searches (sort.Search) on the sorted slice. Or, alternatively, you could use a map instead: in which case (assuming keys are small) lookup would be O(1).

Problems understanding usage of `interface{}` in Go

I'm trying to port an algorithm from Python to Go. The central part of it is a tree built using dicts, which should stay this way since each node can have an arbitrary number of children. All leaves are at the same level, so up the the lowest level the dicts contain other dicts, while the lowest level ones contain floats. Like this:
tree = {}
insert(tree, ['a', 'b'], 1.0)
print tree['a']['b']
So while trying to port the code to Go while learning the language at the same time, this is what I started with to test the basic idea:
func main() {
tree := make(map[string]interface{})
tree["a"] = make(map[string]float32)
tree["a"].(map[string]float32)["b"] = 1.0
fmt.Println(tree["a"].(map[string]float32)["b"])
}
This works as expected, so the next step was to turn this into a routine that would take a "tree", a path, and a value. I chose the recursive approach and came up with this:
func insert(tree map[string]interface{}, path []string, value float32) {
node := path[0]
l := len(path)
switch {
case l > 1:
if _, ok := tree[node]; !ok {
if l > 2 {
tree[node] = make(map[string]interface{})
} else {
tree[node] = make(map[string]float32)
}
}
insert(tree[node], path[1:], value) //recursion
case l == 1:
leaf := tree
leaf[node] = value
}
}
This is how I imagine the routine should be structured, but I can't get the line marked with "recursion" to work. There is either a compiler error, or a runtime error if I try to perform a type assertion on tree[node]. What would be the correct way to do this?
Go is perhaps not the ideal solution for generic data structures like this. The type assertions make it possible, but manipulating data in it requires more work that you are used to from python and other scripting languages.
About your specific issue: You are missing a type assertion in the insert() call. The value of tree[node] is of type interface{} at that point. The function expects type map[string]interface{}. A type assertion will solve that.
Here's a working example:
package main
import "fmt"
type Tree map[string]interface{}
func main() {
t := make(Tree)
insert(t, []string{"a", "b"}, 1.0)
v := t["a"].(Tree)["b"]
fmt.Printf("%T %v\n", v, v)
// This prints: float32 1
}
func insert(tree Tree, path []string, value float32) {
node := path[0]
len := len(path)
switch {
case len == 1:
tree[node] = value
case len > 1:
if _, ok := tree[node]; !ok {
tree[node] = make(Tree)
}
insert(tree[node].(Tree), path[1:], value) //recursion
}
}
Note that I created a new type for the map. This makes the code a little easier to follow. I also use the same 'map[string]interface{}` for both tree nodes and leaves. If you want to get a float out of the resulting tree, another type assertion is needed:
leaf := t["a"].(Tree)["b"] // leaf is of type 'interface{}`.
val := leaf.(float32)
well... the problem is that you're trying to code Go using Python idioms, and you're making a tree with... hashtables? Huh? Then you have to maintain that the keys are unique and do a bunch of otherstuff, when if you just made the set of children a slice, you get that sort of thing for free.
I wouldn't make a Tree an explicit map[string]interface{}. A tree and a node on a tree are really the same thing, since it's a recursive datatype.
type Tree struct {
Children []*Tree
Value interface{}
}
func NewTree(v interface{}) *Tree {
return &Tree{
Children: []*Tree{},
Value: v,
}
}
so to add a child...
func (t *Tree) AddChild(child interface{}) {
switch c := child.(type) {
case *Tree:
t.Children = append(t.Children, c)
default:
t.Children = append(t.Children, NewTree(c))
}
}
and if you wanted to implement some recursive function...
func (t *Tree) String() string {
return fmt.Sprint(t.Value)
}
func (t *Tree) PrettyPrint(w io.Writer, prefix string) {
var inner func(int, *Tree)
inner = func(depth int, child *Tree) {
for i := 0; i < depth; i++ {
io.WriteString(w, prefix)
}
io.WriteString(w, child.String()+"\n") // you should really observe the return value here.
for _, grandchild := range child.Children {
inner(depth+1, grandchild)
}
}
inner(0, t)
}
something like that. Any node can be made the root of some tree, since a subtree is just a tree itself. See here for a working example: http://play.golang.org/p/rEx43vOnXN
There are some articles out there like "Python is not Java" (http://dirtsimple.org/2004/12/python-is-not-java.html), and to that effect, Go is not Python.

Resources