Skip to content

Commit

Permalink
Merge pull request #37 from moul/dev/moul/undefined-deps
Browse files Browse the repository at this point in the history
feat: detect PERT undefined dependencies
  • Loading branch information
moul authored Aug 29, 2019
2 parents 49e30a0 + b714440 commit e967fd7
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 11 deletions.
6 changes: 6 additions & 0 deletions attr.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ func (a Attrs) getOrCreatePert() *PertAttrs {
return a["pert"].(*PertAttrs)
}

func (a Attrs) SetPertUndefinedDependency() Attrs {
pert := a.getOrCreatePert()
pert.IsUndefinedDependency = true
return a
}

func (a Attrs) SetPertEstimates(opt, real, pess float64) Attrs {
pert := a.getOrCreatePert()
pert.Optimistic = opt
Expand Down
1 change: 1 addition & 0 deletions pert.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type PertAttrs struct {
IsAction, IsState bool
IsNonStandardGraph bool
IsStart, IsFinish bool
IsUndefinedDependency bool
}

func (pa PertAttrs) WeightedEstimate() float64 {
Expand Down
29 changes: 18 additions & 11 deletions pert_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func FromPertConfig(config PertConfig) *Graph {
dependency := action.DependsOn[0]

graph.AddEdge(
graph.pertGetDependencyEnd(dependency),
graph.pertGetDependencyEnd(dependency, config),
pertPreID(action.ID),
attrs,
)
Expand All @@ -116,7 +116,7 @@ func FromPertConfig(config PertConfig) *Graph {
)
for _, dependency := range action.DependsOn {
graph.AddEdge(
graph.pertGetDependencyEnd(dependency),
graph.pertGetDependencyEnd(dependency, config),
pertPreID(action.ID),
Attrs{}.SetPertZeroTimeActivity(),
)
Expand All @@ -128,7 +128,7 @@ func FromPertConfig(config PertConfig) *Graph {
for _, state := range config.States {
for _, dependency := range state.DependsOn {
graph.AddEdge(
graph.pertGetDependencyEnd(dependency),
graph.pertGetDependencyEnd(dependency, config),
state.ID,
Attrs{}.SetPertZeroTimeActivity(),
)
Expand All @@ -149,24 +149,27 @@ func FromPertConfig(config PertConfig) *Graph {

if !config.Opts.NoSimplify { // simplify the graph
for {
pertRemoveDummySteps(graph)
pertMergeDummyActionGroups(graph)
pertRemoveDummySteps(graph, config)
pertMergeDummyActionGroups(graph, config)
if removed := graph.gc(); removed == 0 {
break
}
}
}

for _, edge := range graph.Vertices() {
for _, vertex := range graph.Vertices() {
if pert := vertex.GetPert(); pert == nil {
vertex.Attrs.SetPertUndefinedDependency()
}
if !config.Opts.StandardPert {
edge.SetPertNonStandardGraph()
vertex.SetPertNonStandardGraph()
}
}

return graph
}

func pertRemoveDummySteps(graph *Graph) {
func pertRemoveDummySteps(graph *Graph, config PertConfig) {
// remove dummy states with only one dummy successor
for _, vertex := range graph.Vertices() {
if vertex.deleted || !pertIsUntitled(vertex) || vertex.OutDegree() != 1 || vertex.InDegree() == 0 || pertHasEstimates(vertex) {
Expand All @@ -183,7 +186,7 @@ func pertRemoveDummySteps(graph *Graph) {
}
}

func pertMergeDummyActionGroups(graph *Graph) {
func pertMergeDummyActionGroups(graph *Graph, config PertConfig) {
// merge dummy action groups
for _, vertex := range graph.Vertices() {
if vertex.deleted || vertex.OutDegree() < 2 {
Expand Down Expand Up @@ -241,7 +244,7 @@ func pertMergeDummyActionGroups(graph *Graph) {
}
metaVertex := graph.AddVertex(metaID, attrs)
for _, predecessor := range predecessors {
depID := graph.pertGetDependencyEnd(predecessor.id)
depID := graph.pertGetDependencyEnd(predecessor.id, config)
graph.AddEdge(depID, metaID, Attrs{}.SetPertZeroTimeActivity())
}
for _, successor := range successors {
Expand All @@ -261,7 +264,11 @@ func pertMergeDummyActionGroups(graph *Graph) {
func pertPreID(id string) string { return fmt.Sprintf("pre_%s", id) }
func pertPostID(id string) string { return fmt.Sprintf("post_%s", id) }

func (g *Graph) pertGetDependencyEnd(dependency string) string {
func (g *Graph) pertGetDependencyEnd(dependency string, config PertConfig) string {
if !config.Opts.StandardPert {
return dependency
}

// if dependency is a vertex, the end is the vertex itself
if vertex := g.GetVertex(dependency); vertex != nil {
return vertex.id
Expand Down
3 changes: 3 additions & 0 deletions viz/graphviz.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ func attrsFromVertex(vertex *graphman.Vertex, opts *Opts) map[string]string {
attrs[string(graphviz.Label)] = " "
attrs[string(graphviz.Shape)] = "circle"
// attrs[string(graphviz.Style)] = "dashed"
case pert.IsUndefinedDependency:
attrs[string(graphviz.Label)] = fmt.Sprintf("undefined dependency: %q", vertex.ID())
attrs[string(graphviz.Shape)] = "octagon"
default:
log.Printf("cannot determine pert style: %v", pert)
attrs[string(graphviz.Label)] = fmt.Sprintf("error: %q", vertex.ID())
Expand Down

0 comments on commit e967fd7

Please sign in to comment.