graph¶
A module containing a model Markov graph.
>>> from blur.markov.node import Node
>>> node_1 = Node('One')
>>> node_2 = Node('Two')
>>> node_1.add_link(node_1, 5)
>>> node_1.add_link(node_2, 2)
>>> node_2.add_link(node_1, 1)
>>> graph = Graph([node_1, node_2])
>>> [graph.pick().get_value() for i in range(10)]
['One', 'One', 'One', 'One', 'One', 'One', 'Two', 'One', 'One', 'One']
-
class
blur.markov.graph.
Graph
(node_list=None)¶ A Markov graph with a number of handy utilities.
The graph consists of a list of
Node
‘s and keeps track of which node was picked last.Several utilities offer conveniences for managing the network.
Parameters: node_list (list) – An optional list of nodes to populate the network with. To populate the network after initialization, use the Graph.add_nodes()
method.Warning
Nodes are not copied when placed into the graph: the passed nodes are used in the object. Side effects may occur if node-altering methods are called, such as
Graph.apply_noise()
orGraph.feather_links()
. Handle with care if using the sameNode
in multiple contexts.-
merge_nodes
(keep_node, kill_node)¶ Merge two nodes in the graph.
Takes two nodes and merges them together, merging their links by combining the two link lists and summing the weights of links which point to the same node.
All links in the graph pointing to
kill_node
will be merged intokeep_node
.Links belonging to
kill_node
which point to targets not inself.node_list
will not be merged intokeep_node
Parameters: Returns: None
Example
>>> from blur.markov.node import Node >>> node_1 = Node('One') >>> node_2 = Node('Two') >>> node_3 = Node('Three') >>> node_1.add_link(node_3, 7) >>> node_2.add_link(node_1, 1) >>> node_2.add_link(node_2, 3) >>> node_3.add_link(node_2, 5) >>> graph = Graph([node_1, node_2, node_3]) >>> print([node.value for node in graph.node_list]) ['One', 'Two', 'Three'] >>> graph.merge_nodes(node_2, node_3) >>> print([node.value for node in graph.node_list]) ['One', 'Two'] >>> for link in graph.node_list[1].link_list: ... print('{} {}'.format(link.target.value, link.weight)) One 1 Two 8
-
add_nodes
(nodes)¶ Add a given node or list of nodes to self.node_list.
Parameters: node (Node or list[Node]) – the node or list of nodes to add to the graph Returns: None
Examples:
Adding one node:
>>> from blur.markov.node import Node >>> graph = Graph() >>> node_1 = Node('One') >>> graph.add_nodes(node_1) >>> print([node.value for node in graph.node_list]) ['One']
Adding multiple nodes at a time in a list:
>>> from blur.markov.node import Node >>> graph = Graph() >>> node_1 = Node('One') >>> node_2 = Node('Two') >>> graph.add_nodes([node_1, node_2]) >>> print([node.value for node in graph.node_list]) ['One', 'Two']
-
feather_links
(factor=0.01, include_self=False)¶ Feather the links of connected nodes.
Go through every node in the network and make it inherit the links of the other nodes it is connected to. Because the link weight sum for any given node can be very different within a graph, the weights of inherited links are made proportional to the sum weight of the parent nodes.
Parameters: - factor (float) – multiplier of neighbor links
- include_self (bool) – whether nodes can inherit links pointing to themselves
Returns: None
Example
>>> from blur.markov.node import Node >>> node_1 = Node('One') >>> node_2 = Node('Two') >>> node_1.add_link(node_2, 1) >>> node_2.add_link(node_1, 1) >>> graph = Graph([node_1, node_2]) >>> for link in graph.node_list[0].link_list: ... print('{} {}'.format(link.target.value, link.weight)) Two 1 >>> graph.feather_links(include_self=True) >>> for link in graph.node_list[0].link_list: ... print('{} {}'.format(link.target.value, link.weight)) Two 1 One 0.01
-
apply_noise
(noise_weights=None, uniform_amount=0.1)¶ Add noise to every link in the network.
Can use either a
uniform_amount
or anoise_weight
weight profile. Ifnoise_weight
is set,uniform_amount
will be ignored.Parameters: - noise_weights (list) – a list of weight tuples
of form
(float, float)
corresponding to(amount, weight)
describing the noise to be added to each link in the graph - uniform_amount (float) – the maximum amount of uniform noise
to be applied if
noise_weights
is not set
Returns: None
Example
>>> from blur.markov.node import Node >>> node_1 = Node('One') >>> node_2 = Node('Two') >>> node_1.add_link(node_1, 3) >>> node_1.add_link(node_2, 5) >>> node_2.add_link(node_1, 1) >>> graph = Graph([node_1, node_2]) >>> for link in graph.node_list[0].link_list: ... print('{} {}'.format(link.target.value, link.weight)) One 3 Two 5 >>> graph.apply_noise() >>> for link in graph.node_list[0].link_list: ... print('{} {}'.format( ... link.target.value, link.weight)) One 3.154 Two 5.321
- noise_weights (list) – a list of weight tuples
of form
-
find_node_by_value
(value)¶ Find and return a node in self.node_list with the value
value
.If multiple nodes exist with the value
value
, return the first one found.If no such node exists, this returns
None
.Parameters: value (Any) – The value of the node to find Returns: Node – A node with value value
if it was foundNone: If no node exists with value
value
Example
>>> from blur.markov.node import Node >>> node_1 = Node('One') >>> graph = Graph([node_1]) >>> found_node = graph.find_node_by_value('One') >>> found_node == node_1 True
-
remove_node
(node)¶ Remove a node from
self.node_list
and links pointing to it.If
node
is not in the graph, do nothing.Parameters: node (Node) – The node to be removed Returns: None
Example
>>> from blur.markov.node import Node >>> node_1 = Node('One') >>> graph = Graph([node_1]) >>> graph.remove_node(node_1) >>> len(graph.node_list) 0
-
remove_node_by_value
(value)¶ Delete all nodes in
self.node_list
with the valuevalue
.Parameters: value (Any) – The value to find and delete owners of. Returns: None
Example
>>> from blur.markov.node import Node >>> node_1 = Node('One') >>> graph = Graph([node_1]) >>> graph.remove_node_by_value('One') >>> len(graph.node_list) 0
-
has_node_with_value
(value)¶ Whether any node in
self.node_list
has the valuevalue
.Parameters: value (Any) – The value to find in self.node_list
Returns: bool
Example
>>> from blur.markov.node import Node >>> node_1 = Node('One') >>> graph = Graph([node_1]) >>> graph.has_node_with_value('One') True >>> graph.has_node_with_value('Foo') False
-
pick
(starting_node=None)¶ Pick a node on the graph based on the links in a starting node.
Additionally, set
self.current_node
to the newly picked node.- if
starting_node
is specified, start from there - if
starting_node
isNone
, start fromself.current_node
- if
starting_node
isNone
andself.current_node
isNone
, pick a uniformally random node inself.node_list
Parameters: starting_node (Node) – Node
to pick from.Returns: Node
Example
>>> from blur.markov.node import Node >>> node_1 = Node('One') >>> node_2 = Node('Two') >>> node_1.add_link(node_1, 5) >>> node_1.add_link(node_2, 2) >>> node_2.add_link(node_1, 1) >>> graph = Graph([node_1, node_2]) >>> [graph.pick().get_value() for i in range(5)] ['One', 'One', 'Two', 'One', 'One']
- if
-
classmethod
from_string
(source, distance_weights=None, merge_same_words=False, group_marker_opening='<<', group_marker_closing='>>')¶ Read a string and derive of
Graph
from it.Words and punctuation marks are made into nodes.
Punctuation marks are split into separate nodes unless they fall between other non-punctuation marks.
'hello, world'
is split into'hello'
,','
, and'world'
, while'who's there?'
is split into"who's"
,'there'
, and'?'
.To group arbitrary characters together into a single node (e.g. to make
'hello, world!'
), surround the text in question withgroup_marker_opening
andgroup_marker_closing
. With the default value, this would look like'<<hello, world!>>'
. It is recommended that the group markers not appear anywhere in the source text where they aren’t meant to act as such to prevent unexpected behavior.The exact regex for extracting nodes is defined by:
expression = r'{0}(.+){1}|([^\w\s]+)\B|([\S]+)'.format( ''.join('\' + c for c in group_marker_opening), ''.join('\' + c for c in group_marker_closing) )
Parameters: - source (str) – the string to derive the graph from
- distance_weights (dict) –
dict of relative indices corresponding with word weights. For example, if a dict entry is
1: 1000
this means that every word is linked to the word which follows it with a weight of 1000.-4: 350
would mean that every word is linked to the 4th word behind it with a weight of 350. A key of0
refers to the weight words get pointing to themselves. Keys pointing beyond the edge of the word list will wrap around the list.The default value for
distance_weights
is{1: 1}
. This means that each word gets equal weight to whatever word follows it. Consequently, if this default value is used andmerge_same_words
isFalse
, the resulting graph behavior will simply move linearly through the source, wrapping at the end to the beginning. - merge_same_words (bool) – if nodes which have the same value should be merged or not.
- group_marker_opening (str) – The string used to mark the beginning of word groups.
- group_marker_closing (str) – The string used to mark the end
of word groups. It is strongly recommended that this be
different than
group_marker_opening
to prevent unexpected behavior with the regex pattern.
Returns: Graph
Example
>>> graph = Graph.from_string('i have nothing to say and ' ... 'i am saying it and that is poetry.') >>> ' '.join(graph.pick().value for i in range(8)) 'using chance algorithmic in algorithmic art easier blur'
-
classmethod
from_file
(source, distance_weights=None, merge_same_words=False, group_marker_opening='<<', group_marker_closing='>>')¶ Read a string from a file and derive a
Graph
from it.This is a convenience function for opening a file and passing its contents to
Graph.from_string()
(see that for more detail)Parameters: - source (str) – the file to read and derive the graph from
- distance_weights (dict) – dict of relative indices corresponding
with word weights. See
Graph.from_string
for more detail. - merge_same_words (bool) – whether nodes which have the same value should be merged or not.
- group_marker_opening (str) – The string used to mark the beginning of word groups.
- group_marker_closing (str) – The string used to mark the end of word groups.
Returns: Graph
Example
>>> graph = Graph.from_file('cage.txt') >>> ' '.join(graph.pick().value for i in range(8)) 'poetry i have nothing to say and i'
-