Atastor / dagraph

Directed Acyclic Graph gem

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Directed Acyclic Graph

Dagraph provides DAG functionality to ActiveRecord models

Code Climate Test Coverage Issue Count

Example

DAG description RU

Installation

  1. Gemfile
gem 'dagraph', github: 'nmix/dagraph'
  1. Install gem
bundle install
  1. Generate migration and run migrate
bin/rails generate dagraph:migration
bin/rake db:migrate
  1. Add acs_as_dagraph to model
class Unit < ActiveRecord::Base
	acts_as_dagraph
end

Usage

Example

Creation

# create units
unit7 = Unit.create(code: "7")
unit5 = Unit.create(code: "5")
unit3 = ...
# create graph with weights
unit7.add_child(unit11, 4)
unit7.add_child(unit8, 1)
unit5.add_child(unit11, 6)
unit3.add_child(unit8, 5)
unit3.add_child(unit10, 7)

unit2.add_parent(unit11, 9)
unit9.add_parent(unit11, 2)
unit9.add_parent(unit8, 1)
unit10.add_parent(unit11, 1)

Children and parents

Get all children (direct descendants)

unit7.children
# => [#<Unit id: 4, code: "11">, #<Unit id: 5, code: "8">]

Get all parents (direct ancestors)

unit8.parents
# => [#<Unit id: 1, code: "7">, #<Unit id: 3, code: "3">]

Routing

Get all of the routes passing through the node ({route_id => [nodes], ...)

unit11.routing
# => {1=>[#<Unit id: 1, code: "7">, #<Unit id: 4, code: "11">, #<Unit id: 7, code: "9">], 3=>[#<Unit id: 1, code: "7">, #<Unit id: 4, code: "11">, #<Unit id: 8, code: "10">], 4=>[#<Unit id: 2, code: "5">, #<Unit id: 4, code: "11">, #<Unit id: 7, code: "9">], 5=>[#<Unit id: 2, code: "5">, #<Unit id: 4, code: "11">, #<Unit id: 8, code: "10">], 6=>[#<Unit id: 1, code: "7">, #<Unit id: 4, code: "11">, #<Unit id: 6, code: "2">], 7=>[#<Unit id: 2, code: "5">, #<Unit id: 4, code: "11">, #<Unit id: 6, code: "2">]}

unit10.routing
# => {3=>[#<Unit id: 1, code: "7">, #<Unit id: 4, code: "11">, #<Unit id: 8, code: "10">], 5=>[#<Unit id: 2, code: "5">, #<Unit id: 4, code: "11">, #<Unit id: 8, code: "10">], 9=>[#<Unit id: 3, code: "3">, #<Unit id: 8, code: "10">]}

Descendants and ancestors

Get all descendants (split to routes)

unit5.descendats
# => [[#<Unit id: 4, code: "11">, #<Unit id: 7, code: "9">], [#<Unit id: 4, code: "11">, #<Unit id: 8, code: "10">], [#<Unit id: 4, code: "11">, #<Unit id: 6, code: "2">]]

Get all uniq descendants (without routes)

unit5.descendats.flatten.uniq
# => [#<Unit id: 4, code: "11">, #<Unit id: 7, code: "9">, #<Unit id: 8, code: "10">, #<Unit id: 6, code: "2">]

Get all ancestors (split to routes)

unit10.ancestors
# => [[#<Unit id: 1, code: "7">, #<Unit id: 4, code: "11">], [#<Unit id: 2, code: "5">, #<Unit id: 4, code: "11">], [#<Unit id: 3, code: "3">]]

Get all uniq ancestors (without routes)

unit10.ancestors.flatten.uniq
# => [#<Unit id: 1, code: "7">, #<Unit id: 4, code: "11">, #<Unit id: 2, code: "5">, #<Unit id: 3, code: "3">]

Weights

Get children with weights

unit3.children_weights
# => [[#<Unit id: 5, code: "8">, 5], [#<Unit id: 8, code: "10">, 7]]

Parents with weights

unit10.parents_weights
# [[#<Unit id: 4, code: "11">, 1], [#<Unit id: 3, code: "3">, 7]]

Get all ancestors with weights (split by routes)

unit9.ancestors_weights (split by routes)
=> [[[#<Unit id: 1, code: "7">, 4], [#<Unit id: 4, code: "11">, 2]], [[#<Unit id: 1, code: "7">, 1], [#<Unit id: 5, code: "8">, 1]], [[#<Unit id: 2, code: "5">, 6], [#<Unit id: 4, code: "11">, 2]], [[#<Unit id: 3, code: "3">, 5], [#<Unit id: 5, code: "8">, 1]]]

Get all descendants with weights (split by routes)

uniq5.descendats_weights
# => [[[#<Unit id: 4, code: "11">, 6], [#<Unit id: 7, code: "9">, 2]], [[#<Unit id: 4, code: "11">, 6], [#<Unit id: 8, code: "10">, 1]], [[#<Unit id: 4, code: "11">, 6], [#<Unit id: 6, code: "2">, 9]]]

Get all descendants with comprised weights (assembly-like-weight-calculation)

unit7.descendants_assembled
# => [[#<Unit id: 4, code: "11">, 4], [#<Unit id: 7, code: "9">, 9], [#<Unit id: 5, code: "8">, 1], [#<Unit id: 8, code: "10">, 4], [#<Unit id: 6, code: "2">, 36]]

Errors

Trying to add node to itself

unit3.add_child(unit3)
# => SelfCyclicError: SelfCyclicError

Trying to create a loop

unit2.add_child(unit7)
# => CyclicError: CyclicError
unit3.add_parent(unit9)
# => CyclicError: CyclicError

Trying to duplicate edge

unit7.add_child(unit11)
DuplicationError: DuplicationError
unit10.add_parent(unit3)
DuplicationError: DuplicationError

Destroying

Remove a child

unit11.children
# => [#<Unit id: 7, code: "9">, #<Unit id: 8, code: "10">, #<Unit id: 6, code: "2">]
unit11.remove_child(unit9)
# => [#<Unit id: 8, code: "10">, #<Unit id: 6, code: "2">]

Remove all children

unit11.children
# => [#<Unit id: 8, code: "10">, #<Unit id: 6, code: "2">]
unit11.remove_children
# => []
unit11.children
# => []

Remove a parent

unit8.parents
# => [#<Unit id: 1, code: "7">, #<Unit id: 3, code: "3">]
unit8.remove_parent(unit7)
# => [#<Unit id: 3, code: "3">]

Remove all parents

unit8.remove_parents
=> []

Methods

method description
unit.add_child(another_unit) Add another_unit as a child node to the unit
unit.add_parent(another_unit) Set another_unit as a parent node for the unit
unit.parents Get all parents of the unit
unit.parents_weights Get all parents with weights
unit.children Get all children of the unit
unit.children_weights Get all children with weights
unit.routing Get hash of all routes passing the unit
unit.ancestors Get array of ancestors of the unit (split by routes)
unit.self_and_ancetors Get array of ancestors including self node (split by routes)
unit.ancestors_weights Get array of ancestors with weights (split by routes)
unit.descendants Get array of descendants of the unit (split by routes)
unit.self_and_descendants Get array of descendants including self node (split by routes)
unit.descendants_weights Get array of descendants with weights (split by routes)
unit.descendants_assembled Get array of descendants with comprised weights (assembly-like-weight-calculation)
unit.roots Get array of root units from ancestors
unit.leafs Get array of leaf units from descendants
unit.root? true if unit has no parents
unit.leaf? true if unit has no children
unit.isolated? true if node has no children no parents
Unit.roots Get array of units without children
Unit.leafs Get array of units without parents

License

This project rocks and uses MIT-LICENSE.

About

Directed Acyclic Graph gem

License:MIT License


Languages

Language:Ruby 89.8%Language:HTML 8.1%Language:CSS 1.1%Language:JavaScript 1.0%