Skip to the content.

SemaWal Semantic network resolver

SemaWal logo

SemaWal is a semantic network resolver in python

Developper: Ali AOUF

Features value
Authors Authors.md
Release 0.2 (20.10)
License GPL
Tracker 40uf411/arrand/Issues
Source Github
Feedbacks Comments
Accounts @Twitter

Description

SemaWal Is a semantic network resolver developed as a python library. It allows the creation of networks through manual coding or a JSON file. It supports a variety of connection types between nodes. SemaWal provides useful network defining functions and knowledge extraction functions, these functions allows for network browsing, path finding, pattern checking and more.

Features:


Usage

install

pip install semawal

[requirement]

SemaWal 0.2 requires no lib šŸ˜‰ļøšŸ˜Šļø

import

>>> from semawal.node import Node
>>> from semawal.net import Net
>>> from semawal.csv_parser import parser

SemaWal Node object

A node is the essential building block of a semantic network. A SemaWal node has a name, a type, and it can have a list of properties. A SemaWal node can extend another node, which will give it a copy of the parent node links. When linking two nodes, SamaWal saves the link on the node that is considered the start of the link. In order to accelerate operations on the links, SemaWal stores the links in a local hidden node attribute, and it generates a list of links that includes all the local links as well as the parent node links. This process will reduce the number of links calculation and thus accelerate operations like searching and tracking. To use the Node you have to import the Node class as the following:

from semawal.node import Node

Create a node

Node(name, props={}, type="regular")

Creating a Node is as simple as calling the default constructor. It takes as input the name of the node, its parameters and, its type. There are three types of nodes:

Examples:

>>> nodeA = Node(name="Node A", props={"p1": "v1", "p2": "v2"}, type="root")
[!] Created node A
>>> nodeB = Node(name="B")
[!] Created node B
>>> nodeC = Node("C")
[!] Created node C

Basic node methods

Resetting a node

Resetting a node will wipe itā€™s list of links, properties and, parent.

>>>nodeA.reset()
Renaming a node
>>>nodeA.rename("newName")
Get a nodeā€™s name
>>>nodeName = nodeA.name()
Get a nodeā€™s type
>>>nodeType = nodeA.type()
Get a nodeā€™s parent
>>>parentNode = nodeA.parent()
Get a nodeā€™s root (parent of the parent ofā€¦of the node)
>>>nodeRoot = nodeA.root()
Get a nodeā€™s properties
>>>nodeProps = nodeA.getProperties()
Get a nodeā€™s specific property
>>>nodeProps = nodeA.getProp(key="prop1")
Add a property to node
>>>nodeProps = nodeA.addProp(key="prop1", value="value1")
Drop a property from node
>>>nodeProps = nodeA.dropProp(key="prop1")
Check if a node is valid by its props
>>>valid = nodeA.validateProps(pattern={
	{
    	"prop1": [["<", 10], [">", 9]]
	}
})

Note the allowed operations are: ==, !=, <=, >=, <, >, and each list of elements is considered as a set of conjunction of conditions (condition1 AND condition2).

Linking two nodes

link(attribute, node, mode=1, power=1, generate=True)

Root and regular nodes can create links leading to other nodes. Each link has an attribute that defines the meaning of the link, a mode 0 or 1 being negative or positive meaning respectively, the mode is mainly used used to define the negative of the attribute, and the power(strength) of the link being an integer between 0 and 10.

Note: In order to avoid building the graph at each operation, SemaWal builds a static graph that is used for the search operations. Operation that define the graph like the ā€œlinkā€ function execute a rebuild of the static graph after which can slow the execution of the code, and to prevent that is is highly recommended to set the generate parameter to false when defining a network with relatively big size.

Node: In case of defining a bidirectional link, it is more convenient to use the mutualLink method.

Examples:

## One-way relation: Ex: A has B
# mode (int): 0=negative, 1=positive
>>> nodeA.link(attribute="has", node=NodeB, mode=1, power=7, generate=False)
## Mutual Link: Ex: A is B and B is A
>>> nodeA.mutualLink(attribute="is", node=NodeB, mode=1, power=5)

Tip: Letā€™s say you want to create a link between a link a node A and a list of nodes, calling the link method every time with the same parameters is annoying. As a solution to that SemaWal provides the andWith() method to create a chain of links.

andWith(self, node, attribute="", mode="", power="", generate=False)

Of course, you can change the parameters at any point. Just be aware that the changed parameters will affect the rest of the links after the change. And donā€™t forget to set generate to True at the last call. Examples:

>>>nodeA.link(attribute="has", node=NodeB, mode=1, power=7, generate=False).andWith(nodeB).andWith(nodeC, generate=True)
Generating the static graph

We mentioned earlier how to prevent the generation of the static graph. Now, generating it is simply calling the generateStaticLinks method, or simply commit.

>>>nodeA.generateStaticLinks()
#or
>>>nodeA.commit()

Extending a node

When working with big networks, having nodes that share similar properties and links is very normal, and normally the developer has to define the nodes and rewrite the same properties and link for each node. In SemaWal, it is possible to define one node and then extend other nodes with it. The nodes that extend this node get a copy of the parent node properties and links, and while the links of the child not are updated after each update of the parent links, the properties are not updated.

Important rules

When a node extends another, the child gets the properties of the parent node, and if they both share the same property with different values, the child node will keep its own value. inheriting links works is simple, the child node gets the parent nodes. the inherited links are updated after each change to the parent links. If both the parent and the child have a link with the same node on the same attribute, the childā€™s link is only updated if the power of the parent link higher than the childā€™s link power. Example:

>>> ## Inheritance (A inherits B relations): Ex: A extends B
>>> nodeA.extends(node=NodeC)

WARNING! as of version 0.2 Semawal does does not detect the circles. A circle happens when two nodes extend each other directly or indirectly. A circle can cause an infinite loop.

dropLink(attribute, node, generate=True)

A link can be dropped only if it is not inherited. Local links can be dropped by calling the drop method.

>>>nodeA.dropLink("is", nodeB)
>>>nodeA.getLinks(generate=True)
>>>nodeA.showLinks(generate=True)

Output

nodeA       |  relation:  test0     |   nd_0         | mode:  1  power:  1
nodeA       |  relation:  test1     |   nd_1         | mode:  0  power:  7
>>>nodeA.getLinksAttributes()
["test0", "test1"]
>>>nodeA.getRelationsWith(nodeB)
["test0", "test1"]
Search for for connections with filters
getConnections(attributes=[], props = [], mode = -1, minPower=0, maxPower=10)

Examples

>>>nodeA.checkPattern([
    {
        "num":2,
        "attributes": ["test1"],
        "props": {},
        "mode": -1,
        "minPower": 2,
        "maxPower":4
    },
	{
        "num":1,
        "attributes": ["test0"],
        "props": {},
        "mode": -1,
        "minPower": 5,
        "maxPower":6
    },
])

SemaWal Network object

In SemaWal a network is a special node. A node that can contain other nodes. This definition allows SemaWal to have a more complex representations of sub-networks. Since a network is basically a node, it has access to all the node methods, plus a set of network methods allowing for more advanced search operations. To use the Network you have to import the Net class as the following:

from semawal.net import Net

Create a network

Net(name="Network", description="", props={}, type="regular")

Example

>>>netA = Net()
>>>netB = Net("NetB")
>>>netC = Net(name="NetC", description="This network is to illustrate SemaWal Net")

All the basic methods like renaming, getting the name, Ext are exactly the same as the Nodeā€™s methods.

Get a Network description
>>>d = netA.desc()
Set a Network description
>>>netA.setDesc("New description")
Append nodes & networks
append(node)
# or for a list of items
appendAll(nodes)

Example

>>>netA.append(nodeA)
>>>netA.append(netB)
# or for a list of items
>>>netA.appendAll([nodeC, nodeD, NetC])
Drop a node or a network
drop(node)

Example

>>>netA.drop(nodeA)
Get a list of all the nodes
>>>netA.getNodes()
Get a node by its name
>>>nodeA = net.getNode("nodeA")
Get nodes of type ā€œrootā€
>>>rootNodes = net.roots()
Get sub-networks
>>>retNodes = net.nets()
>>>net.showLinks(node=None)
Find path between two nodes
findPath(nodeA, nodeB, depth=-1, allowedAttributes=[], props={}, mode=-1, minPower=0, maxPower=10, ignoreNodes=[])

SemaWal JSON parser

SemaWal 0.2 comes with a JSON parser that can import and export both nodes and network. This mechanism allows for a more friendly use and ease the processing of sharing work. To use the JSON parser you have to import the parser class as the following:

from semawal.json_parser import Parser

Exporting a node or a network

Exporting a node or a network is as simple as calling the export function

export(object, filename)

Example

>>>Parser.export(net, "net.json")
>>>Parser.export(node, "node.json")

Importing a node or a network

In order to import a node or a network, it must be well formed and organized. An example of a node JSON file:

{
    "type": "node",//important
    "node": {
        "name": "Node1",//important
        "type": "leaf",
        "props": {
            "size": "13ko",
            "year": 1999 
        }
    }
}

An example of a network JSON file:

{
    "name": "Network", 
    "desc": "This net is just an example of how you can use SemaWal", 
    "type": "net",
    "__comment__": "Comments like this one will not be included in the parsing process", 
    "nodes": [
        "node.json",//This will read the file node.js and create a node/network from it
        "test_node",//This will create a node with the name being "test_node"
        {"name": "1", "type": "root", "props": {"p": 1, "p2": 2}, "parent": null},//Direct node definition
        {"name": "2", "type": "regular", "props": {"s":4}, "parent": null}, 
        {"name": "3", "type": "regular", "props": {}, "parent": null}, 
        {"name": "4", "type": "regular", "props": {}, "parent": "1"}//Here node "4" will extend node "1"
    ], 
    "links": [
        {"from": "1", "to": "2", "attribute": "test", "mode": 1, "power": 1}, 
        {"from": "2", "to": "3", "attribute": "test", "mode": 1, "power": 3, "mutual": true}, 
        {"from": "3", "to": "4", "attribute": "test", "mode": 1, "power": 1}
    ]
}

Importing a node/network

>>>net = Parser.read("net.json")
# or
>>>node = Parser.read("node.json")