Skip to content

Commit

Permalink
Implement DAG
Browse files Browse the repository at this point in the history
  • Loading branch information
Ahmad Muzakkir committed Nov 8, 2018
0 parents commit 1389eec
Show file tree
Hide file tree
Showing 20 changed files with 1,204 additions and 0 deletions.
72 changes: 72 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
.env
.idea/
vendor/
public_slurp/
public/
update/

*.db

# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib

# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/

# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/dictionaries

# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml

# Gradle:
.idea/**/gradle.xml
.idea/**/libraries

# CMake
cmake-build-debug/

# Mongo Explorer plugin:
.idea/**/mongoSettings.xml

## File-based project format:
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Cursive Clojure plugin
.idea/replstate.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.exclude": {
"**/vendor": true
}
}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Directed Acyclic Graph
Demonstrate an implementation of directed acyclic graph (DAG) in GO
55 changes: 55 additions & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package cmd

import (
"os"
"path/filepath"

"github.com/ahmadmuzakkir/dag/store/badgerstore"
"github.com/ahmadmuzakkir/dag/store/boltstore"
"github.com/boltdb/bolt"
"github.com/dgraph-io/badger"
)

// File path to the bolt db
const BoltPath = "/tmp/bolt/graph_bolt.db"

// Folder path to the directory to store badger files
const BadgerDirPath = "/tmp/badger"

// 1 = Bolt, 2 = Badger
const DBType = 1

func GetBoltDataStore(path string) (*boltstore.BoltStore, func(), error) {
// Create directory if it does not exist
if _, err := os.Stat(path); os.IsNotExist(err) {
if err2 := os.MkdirAll(filepath.Dir(path), os.ModePerm); err2 != nil {
return nil, func() {}, err2
}
}

db, err := bolt.Open(path, 0600, nil)
if err != nil {
return nil, func() {}, err
}

var ds = boltstore.NewBoltStore(db)
if err != nil {
return nil, func() { db.Close() }, err
}

return ds, func() { db.Close() }, nil
}

func GetBadgerDataStore(dir string) (*badgerstore.BadgerStore, func(), error) {
opts := badger.DefaultOptions
opts.Dir = dir
opts.ValueDir = dir
db, err := badger.Open(opts)
if err != nil {
return nil, func() {}, err
}

var ds = badgerstore.NewBadgerStore(db)

return ds, func() { db.Close() }, nil
}
44 changes: 44 additions & 0 deletions cmd/dag/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"log"

"github.com/ahmadmuzakkir/dag/cmd"
"github.com/ahmadmuzakkir/dag/store"
)

func main() {
var ds store.DataStore
var teardown func()
var err error

if cmd.DBType == 1 {
ds, teardown, err = cmd.GetBoltDataStore(cmd.BoltPath)
} else {
ds, teardown, err = cmd.GetBadgerDataStore(cmd.BadgerDirPath)
}
if err != nil {
log.Fatal(err)
}

defer teardown()

graph, err := ds.Get()
if err != nil {
log.Fatal(err)
}

highestAncestorsCount := 0
for i := 0; i < 10; i++ {
v, _ := graph.GetVertexByIndex(i)
if err != nil {
log.Fatal(err)
}

a := graph.AncestorsBFS(v.ID, nil)
if len(a) > highestAncestorsCount {
highestAncestorsCount = len(a)
}
}
log.Printf("Highest ancestors count: %v", highestAncestorsCount)
}
92 changes: 92 additions & 0 deletions cmd/dag/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package main

import (
"testing"

"github.com/ahmadmuzakkir/dag/cmd"
"github.com/ahmadmuzakkir/dag/store"
)

func getGraph(t *testing.B) (*store.DAG, func()) {
// ds, teardown, err := cmd.GetBadgerDataStore(cmd.BadgerDirPath)
ds, teardown, err := cmd.GetBoltDataStore(cmd.BoltPath)
if err != nil {
t.Fatal(err)
}

// If you want regenerate the data for every run, uncomment below.
// Otherwise, it will use existing data.

graph := store.GenerateGraph(100000)
err = ds.Insert(graph)
if err != nil {
t.Fatal(err)
}

g, err := ds.Get()
if err != nil {
t.Fatal(err)
}

return g, teardown
}

func getVertex(graph *store.DAG, t *testing.B) *store.Vertex {
var index int = 0
// index := rand.Intn(graph.CountVertex())

v, err := graph.GetVertexByIndex(index)
if err != nil {
t.Fatal(err)
}

return v
}

func BenchmarkGet(t *testing.B) {
ds, teardown, err := cmd.GetBoltDataStore(cmd.BoltPath)
if err != nil {
t.Fatal(err)
}
defer teardown()

_, err = ds.Get()
if err != nil {
t.Fatal(err)
}
}

func BenchmarkReach(t *testing.B) {
graph, teardown := getGraph(t)
defer teardown()

v := getVertex(graph, t)
graph.Reach(v.ID)
}

func BenchmarkConditionalReach(t *testing.B) {
graph, teardown := getGraph(t)
defer teardown()

v := getVertex(graph, t)

graph.ConditionalReach(v.ID, false)
}

func BenchmarkList(t *testing.B) {
graph, teardown := getGraph(t)
defer teardown()

v := getVertex(graph, t)

graph.List(v.ID)
}

func BenchmarkConditionalList(t *testing.B) {
graph, teardown := getGraph(t)
defer teardown()

v := getVertex(graph, t)

graph.ConditionalList(v.ID, false)
}
40 changes: 40 additions & 0 deletions cmd/generate/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package main

// Used to generate the graph and insert them into the DB

import (
"log"
"math/rand"
"time"

"github.com/ahmadmuzakkir/dag/cmd"
"github.com/ahmadmuzakkir/dag/store"
)

func init() {
rand.Seed(time.Now().UnixNano())
}

func main() {
var ds store.DataStore
var teardown func()
var err error

if cmd.DBType == 1 {
ds, teardown, err = cmd.GetBoltDataStore(cmd.BoltPath)
} else {
ds, teardown, err = cmd.GetBadgerDataStore(cmd.BadgerDirPath)
}
if err != nil {
log.Fatal(err)
}

defer teardown()

graph := store.GenerateGraph(100000)

err = ds.Insert(graph)
if err != nil {
log.Fatal("insert error: ", err)
}
}
12 changes: 12 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/ahmadmuzakkir/dag

require (
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 // indirect
github.com/boltdb/bolt v1.3.1
github.com/dgraph-io/badger v1.5.4
github.com/dgryski/go-farm v0.0.0-20180109070241-2de33835d102 // indirect
github.com/golang/protobuf v1.2.0 // indirect
github.com/pkg/errors v0.8.0 // indirect
golang.org/x/net v0.0.0-20181106040132-ab400d30ebde // indirect
golang.org/x/sys v0.0.0-20181031143558-9b800f95dbbc // indirect
)
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi81xWQA2QIVxjWkFHptGgC547vchpUbtFo=
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/dgraph-io/badger v1.5.4 h1:gVTrpUTbbr/T24uvoCaqY2KSHfNLVGm0w+hbee2HMeg=
github.com/dgraph-io/badger v1.5.4/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
github.com/dgryski/go-farm v0.0.0-20180109070241-2de33835d102 h1:afESQBXJEnj3fu+34X//E8Wg3nEbMJxJkwSc0tPePK0=
github.com/dgryski/go-farm v0.0.0-20180109070241-2de33835d102/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/net v0.0.0-20181106040132-ab400d30ebde h1:d+Rwm0ydekeHqJr+mizM2MoeV4x+xc5WDjMtJpTmwHo=
golang.org/x/net v0.0.0-20181106040132-ab400d30ebde/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sys v0.0.0-20181031143558-9b800f95dbbc h1:SdCq5U4J+PpbSDIl9bM0V1e1Ug1jsnBkAFvTs1htn7U=
golang.org/x/sys v0.0.0-20181031143558-9b800f95dbbc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Loading

0 comments on commit 1389eec

Please sign in to comment.