Skip to content

Commit

Permalink
Merge branch 'release/0.21.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
moaxcp committed Oct 28, 2017
2 parents 01c78a5 + 8787550 commit 12f27d6
Show file tree
Hide file tree
Showing 74 changed files with 1,132 additions and 1,758 deletions.
136 changes: 63 additions & 73 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,42 +60,6 @@ may be changed which will break the graph. These rules will address those issues
4. Changing one or two in Edge moves the edge to different vertices. The vertices will be created if they do not exist.
5. delegates in Vertex and Edge are read-only

## extending the graph

Developers can use the dsl to create new algorithms based on graphs like this workflow between step1 and step2.

```groovy
def workQueue = new LinkedList()
apply EdgeWeightPlugin, VertexMapPlugin
edge (step1, step2) {
weight { queue.size() }
}
vertex step1 {
action = {
println "processing"
workQueue << "work"
}
}
vertex step2 {
action = {
println "done processing ${workQueue.poll()}"
}
}
```

In this script the edge method first creates step1 and step2. Then it creates and edge between the two vertices. It then
configures the edge with the Mapping and Weight traits. Mapping allows the edge to have extra properties like a queue.
Weight affects the behavior of traversals.

Next, the script finds step1 and configures it with the Mapping trait and an action closure which adds "work" to the
workQueue.

Finally, step2 is configured with an action which processes "work".

## directed graphs

The Default behavior of a graph is undirected. These graphs have a set of edges where only one edge
Expand All @@ -108,15 +72,6 @@ type 'directed-graph'
//lots of code
```

## traits

Traits can be added to all edges and vertices using `edgeTraits` and `vertexTraits`.

```groovy
edgeTraits Mapping, Weight
vertexTraits Mapping
```

## Traversing a graph

Once a graph is created there is a dsl for depthFirstTraversal and breadthFirstTraversal.
Expand Down Expand Up @@ -201,7 +156,33 @@ Calling `classifyEdges` on an undirected graph will result in two classification
is what the edge would be in a directed graph. The second classification is always back-edge. This is because edges in
an undirected graph are considered bi-directional in `classifyEdges`.

#Types
# Edge and Vertex Properties

Properties can be added to Edge and Vertex dynamically simply by assigning them.

```groovy
edge(A, B) {
key = 'value'
}
vertex step1, {
label = 'first step in process'
}
```

# Types

A graph's type determines specific behavior. A type can change a normal graph to an directed-graph. It can add wieght
to the graph. It can change the graph to a DAG. Developers can make their own type and apply it to a graph. Types can:

1. replace all edges and vertices
2. add methods to the edge and vertex dsl
3. change the data structures used by the graph
4. add constraints to the structure of the graph

The type of a graph may be changed at any time. An undirected-graph may be changed to a directed-graph which can be
changed back to an undirected-graph.


## DirectedGraphType

Expand All @@ -215,46 +196,44 @@ opposite directions.

Traversal methods will only follow out edges from a vertex.

# Plugins

Plugins provide graphs with extra functionality. They can:

1. Modify all edges and vertices by adding traits or replacing them
2. modify the factories so they create different edges and vertices
3. perform meta-programming on the graph to change or add methods

## WeightedGraphType

## EdgeWeightPlugin

This plugin applies Weight to all edges and changes all traversal methods to follow edges in order of their weight.
```groovy
type 'weighted-graph'
```

## EdgeMapPlugin
WeightedGraphType is an undirected graph where edges can have weight. Traversal methods follow edges with the least
weight.

All edges and all future edges will have the Mapping triat.
### Adding weight

Note: will probably be deleted in the future.
Edges can be assigned weight within the dsl.

## VertexMapPlugin
```groovy
type 'weighted-graph'
All vertices and all future vertices will have the Mapping trait.
edge A, B, [weight:10]
Note: will probably be deleted in the future.
edge (A, B) { weight = 10 }
```

# Traits
Weight can be a lazy property by assigning a closure.

Traits are standard groovy traits that developers or plugins can apply to Vertex or Edge
delegates. The Vertex and Edge objects call their delegate when a method or property is
missing. This allows properties and methods to be added to a Vertex or Edge at runtime.
```groovy
type 'weighted-graph'
## Mapping
edge(A, B) {
weight = { queue.size() }
}
Allows a vertex or edge to act like a Map. When a property is missing in the delegate this
trait will return or set the value in its map.
## WeightedDirectedGraphType
## Weight
```groovy
type 'weighted-directed-graph'
```

Adds a weight property to a vertex or map. The weight is set with the `weight` method passing
in a closure. This makes the weight lazy so it can change dynamically.
WeightedDirectedGraphType is a directed graph where edges can have weight. Traversal methods follow edges with the least
weight.

# Getting Started With Development/Contributing

Expand Down Expand Up @@ -316,6 +295,17 @@ If there are any issues contact me moaxcp@gmail.com.

# Releases

## 0.21.0

This release represents a major change in how graphs are typed. Additional functionality is no only added through a
Type. Type is the delegate of a Graph. A graph's type provides additional methods and can change any aspect of how a
graph works. Types provide a graph with edges and vertices. They define the EdgeSpec and VertexSpec which means a type
may add new methods to the dsl for building edges and vertices.

* upgraded to gradle 4.2
* replaced plugins with type
* edges and vertices can now add properties dynamically. This removes the need for traits.

## 0.20.0

* [#98](https://github.com/moaxcp/graph-dsl/issues/98)
Expand Down
13 changes: 9 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ description = 'A groovy dsl for creating and traversing graphs.'

sourceCompatibility = 1.8
targetCompatibility = 1.8
ext.groovyVersion = '2.5.0-beta-1'
ext.groovyVersion = '2.4.12'

versioneye {
includePlugins = true
Expand All @@ -45,7 +45,7 @@ jacocoTestCoverageVerification {
}
limit {
counter = 'BRANCH'
minimum = 0.89
minimum = 0.88
}
}

Expand All @@ -63,7 +63,7 @@ jacocoTestCoverageVerification {

rule {
element = 'CLASS'
includes = ['graph.type.EdgeSpec']
includes = ['graph.type.undirected.GraphEdgeSpec']
limit {
minimum = 0.93
}
Expand All @@ -75,7 +75,7 @@ jacocoTestCoverageVerification {

rule {
element = 'CLASS'
includes = ['graph.type.VertexSpec']
includes = ['graph.type.undirected.GraphVertexSpec']
limit {
minimum = 0.95
}
Expand Down Expand Up @@ -204,6 +204,11 @@ nexusStaging {

dependencies {
compile "org.codehaus.groovy:groovy:$groovyVersion"
testCompile( 'com.athaydes:spock-reports:1.3.2' ) {
transitive = false
}
testCompile 'org.slf4j:slf4j-api:1.7.13'
testCompile 'org.slf4j:slf4j-simple:1.7.13'
testCompile ('org.spockframework:spock-core:1.1-groovy-2.4') {
exclude group: 'org.codehaus.groovy', module:'groovy-all'
}
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#Mon Jun 26 21:11:23 EDT 2017
#Sun Oct 15 20:00:03 EDT 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.2-all.zip
6 changes: 3 additions & 3 deletions gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
warn () {
echo "$*"
}

die ( ) {
die () {
echo
echo "$*"
echo
Expand Down Expand Up @@ -155,7 +155,7 @@ if $cygwin ; then
fi

# Escape application args
save ( ) {
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
Expand Down
33 changes: 29 additions & 4 deletions src/main/groovy/graph/DslScript.groovy
Original file line number Diff line number Diff line change
@@ -1,19 +1,44 @@
package graph

/**
* Base script for using graph-dsl. This class may be used in scripts to make the dsl part of the script.
*
* <pre><code>
* #!/usr/bin/env groovy
*
* @Grapes(
* @Grab(group='com.github.moaxcp', module='graph-dsl', version='0.20.0')
* )
*
* import graph.*
*
* @groovy.transform.BaseScript DslScript graph
* edge A, B
*
* assert graph.edges.size() == 1
* assert graph.edges.first().one == 'A'
* assert graph.edges.first().two == 'B'
* assert graph.vertices.size() == 2
* assert graph.vertices.A.name == 'A'
* assert graph.vertices.B.name == 'B'
* </code></pre>
*/
@SuppressWarnings('AbstractClassWithoutAbstractMethod')
@SuppressWarnings('NoWildcardImports')
abstract class DslScript extends Script {
Graph graph
DslScript() {
graph = new Graph()
}
Graph graph = new Graph()

@SuppressWarnings('NoDef')
def propertyMissing(String name) {
graph."$name"
}

@SuppressWarnings('NoDef')
def propertyMissing(String name, value) {
graph."$name" = value
}

@SuppressWarnings('NoDef')
def methodMissing(String name, args) {
graph.invokeMethod name, args
}
Expand Down
Loading

0 comments on commit 12f27d6

Please sign in to comment.