///
/// @license
/// Copyright 2020 Roberto Luiz Souza Monteiro,
/// Renata Souza Barreto,
/// Hernane Borges de Barros Pereira.
///
/// Licensed under the Apache License, Version 2.0 (the 'License');
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at;
///
/// http://www.apache.org/licenses/LICENSE-2.0;
///
/// Unless required by applicable law or agreed to in writing, software;
/// distributed under the License is distributed on an 'AS IS' BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, eitherMath.express or implied.
/// See the License for the specific language governing permissions and;
/// limitations under the License.
///
///
/// Library for building semantic networks.
/// @namespace snet
///
namespace snet {
///
/// Create a JSON graph from a file in DLF format.
/// @method createFromDlf
/// @memberof snet
/// @param {string} fileContents - DLF file contents.
/// @param {object} properties - Network properties (n, m and directed).
/// @param {string} topology - Network topology. It can be:
/// chain, circle or clique.
/// @param {boolean} weighted - The created network must be weighted based
/// on the number of occurrences of the connections
/// between the vertices.
/// @param {boolean} allowLoops - Allows the existence of loops.
/// @param {object} network - Network previously created to insert new data.
/// @return {object} A JSON containing the network.
///
function createFromDlf(fileContents, properties, topology, weighted, allowLoops, network) {
if (core.type(properties) == "undefined") {
properties = {
"n": 0,
"m": 0,
"directed": true
}
} else {
properties.n = 0
properties.m = 0
}
if (core.type(topology) == "undefined") {
topology = "chain"
}
if (core.type(weighted) == "undefined") {
weighted = true
}
if (core.type(network) == "undefined") {
network = {
"nodes": [],
"edges": [],
"numberOfSentences": 0,
"vocabulary": 0,
"density": []
}
}
if (core.type(allowLoops) == "undefined") {
allowLoops = false
}
if (properties.directed == true) {
edgeType = "arrow"
} else {
edgeType = "line"
}
function findNode(list, label) {
foreach (list; index; value) {
if (value.label == label) {
return(value)
}
}
return("undefined")
}
function findEdge(list, source, target, directed) {
if (core.type(directed) == "undefined") {
directed = false
}
foreach (list; index; value) {
if (directed) {
if ((value.source == source) && (value.target == target)) {
return(value)
}
} else {
if (((value.source == source) && (value.target == target)) || ((value.source == target) && (value.target == source))) {
return(value)
}
}
}
return("undefined")
}
nodes = []
endOfRecord = false
t1 = core.date()
fileLines = core.split(core.replace(fileContents, "\r\n", "\n"), "\n")
system.println("Processing " + fileLines.length + " lines ...")
for (l = 0; l < fileLines.length; l = l + 1) {
if ((l != 0) || (l % 100 == 0)) {
system.println("Processed " + l.toString() + " lines of " + fileLines.length.toString() + ".")
}
line = fileLines[l]
line = core.replace(line, "\t", " ")
record = core.splitCSV(line.trim(), " ", true)
if (record[0] == "{S}") {
network.numberOfSentences = network.numberOfSentences + 1
endOfRecord = true
} else {
if (l == fileLines.length - 1) {
network.numberOfSentences = network.numberOfSentences + 1
endOfRecord = true
}
}
if (core.length(record) >= 1) {
if (!endOfRecord) {
label = core.toString(record[0])
x = ""
y = ""
size = ""
if (x == "") {
x = math.random()
}
if (y == "") {
y = math.random()
}
if (size == "") {
size = 1
}
node = {
"id": label,
"label": label,
"x": x,
"y": y,
"size": size
}
nodes.push(node)
} else {
foreach (nodes; index; node) {
nodeFound = findNode(network.nodes, node.label)
if (nodeFound == "undefined") {
network.nodes.push(node)
network.vocabulary = network.vocabulary + 1
} else {
nodeFound.size = nodeFound.size + 1
}
}
if (topology == "chain") {
for (i = 0; i < nodes.length - 1; i = i + 1) {
node1 = nodes[i]
node2 = nodes[i + 1]
if (!allowLoops) {
if (node1.id == node2.id) {
continue
}
}
edgeFound = findEdge(network.edges, node1.id, node2.id, properties.directed)
if (edgeFound == "undefined") {
edge = {
"id": "e" + network.edges.length,
"label": "1",
"source": node1.id,
"target": node2.id,
"size": 1,
"type": edgeType
}
network.edges.push(edge)
} else {
if (weighted) {
edgeFound.size = edgeFound.size + 1
edgeFound.label = core.toString(edgeFound.size)
}
}
}
} elseif (topology == "clique") {
foreach (nodes; index1; node1) {
foreach (nodes; index2; node2) {
if (!allowLoops) {
if (node1.id == node2.id) {
continue
}
}
if (index1 > index2) {
continue
}
edgeFound = findEdge(network.edges, node1.id, node2.id, properties.directed)
if (edgeFound == "undefined") {
edge = {
"id": "e" + network.edges.length,
"label": "1",
"source": node1.id,
"target": node2.id,
"size": 1,
"type": edgeType
}
network.edges.push(edge)
} else {
if (weighted) {
edgeFound.size = edgeFound.size + 1
edgeFound.label = core.toString(edgeFound.size)
}
}
}
}
} elseif (topology == "circle") {
for (i = 0; i < nodes.length - 1; i = i + 1) {
node1 = nodes[i]
node2 = nodes[i + 1]
if (!allowLoops) {
if (node1.id == node2.id) {
continue
}
}
edgeFound = findEdge(network.edges, node1.id, node2.id, properties.directed)
if (edgeFound == "undefined") {
edge = {
"id": "e" + network.edges.length,
"label": "1",
"source": node1.id,
"target": node2.id,
"size": 1,
"type": edgeType
}
network.edges.push(edge)
} else {
if (weighted) {
edgeFound.size = edgeFound.size + 1
edgeFound.label = core.toString(edgeFound.size)
}
}
if (i + 1 == nodes.length - 1) {
node1 = nodes[i + 1]
node2 = nodes[0]
edgeFound = findEdge(network.edges, node1.id, node2.id, properties.directed)
if (edgeFound == "undefined") {
edge = {
"id": "e" + network.edges.length,
"label": "1",
"source": node1.id,
"target": node2.id,
"size": 1,
"type": edgeType
}
network.edges.push(edge)
} else {
if (weighted) {
edgeFound.size = edgeFound.size + 1
edgeFound.label = core.toString(edgeFound.size)
}
}
}
}
}
properties.n = network.nodes.length
properties.m = network.edges.length
if (properties.directed) {
density = (properties.m / (properties.n * (properties.n - 1)))
} else {
density = (2 * properties.m / (properties.n * (properties.n - 1)))
}
network.density.push(density)
nodes = []
endOfRecord = false
}
}
}
properties.n = network.nodes.length
properties.m = network.edges.length
t2 = core.date()
t = t2 - t1
system.println("Processed " + l.toString() + " lines of " + fileLines.length.toString() + ".")
system.println("Elapsed time: " + t + " ms.")
return (network)
}
///
/// Create a JSON graph from a file in JSON data.
/// @method createFromJson
/// @memberof snet
/// @param {object} jsonData - JSON data.
/// @param {object} properties - Network properties (n, m and directed).
/// @param {string} topology - Network topology. It can be:
/// chain, circle or clique.
/// @param {boolean} weighted - The created network must be weighted based
/// on the number of occurrences of the connections
/// between the vertices.
/// @param {boolean} allowLoops - Allows the existence of loops.
/// @param {object} network - Network previously created to insert new data.
/// @return {object} A JSON containing the network.
///
function createFromJson(jsonData, properties, topology, weighted, allowLoops, network) {
if (core.type(properties) == "undefined") {
properties = {
"n": 0,
"m": 0,
"directed": true
}
} else {
properties.n = 0
properties.m = 0
}
if (core.type(topology) == "undefined") {
topology = "chain"
}
if (core.type(weighted) == "undefined") {
weighted = true
}
if (core.type(network) == "undefined") {
network = {
"nodes": [],
"edges": [],
"numberOfSentences": 0,
"vocabulary": 0,
"density": []
}
}
if (core.type(allowLoops) == "undefined") {
allowLoops = false
}
if (properties.directed == true) {
edgeType = "arrow"
} else {
edgeType = "line"
}
function findNode(list, label) {
foreach (list; index; value) {
if (value.label == label) {
return(value)
}
}
return("undefined")
}
function findEdge(list, source, target, directed) {
if (core.type(directed) == "undefined") {
directed = false
}
foreach (list; index; value) {
if (directed) {
if ((value.source == source) && (value.target == target)) {
return(value)
}
} else {
if (((value.source == source) && (value.target == target)) || ((value.source == target) && (value.target == source))) {
return(value)
}
}
}
return("undefined")
}
nodes = []
t1 = core.date()
system.println("Processing " + jsonData.length + " records ...")
network.numberOfSentences = jsonData.length
for (r = 0; r < jsonData.length; r = r + 1) {
if ((r != 0) || (r % 100 == 0)) {
system.println("Processed " + r.toString() + " records of " + jsonData.length.toString() + ".")
}
record = jsonData[r]
if (record.length == 0) {
continue
}
for (w = 0; w < record.length; w = w + 1) {
word = record[w]
label = word.object
x = math.random()
y = math.random()
size = 1
node = {
"id": label,
"label": label,
"x": x,
"y": y,
"size": size,
"class": word.class,
"subClass": word.subClass,
"subSubClass": word.subSubClass
}
nodes.push(node)
}
foreach (nodes; index; node) {
nodeFound = findNode(network.nodes, node.label)
if (nodeFound == "undefined") {
network.nodes.push(node)
network.vocabulary = network.vocabulary + 1
} else {
nodeFound.size = nodeFound.size + 1
}
}
if (topology == "chain") {
for (i = 0; i < nodes.length - 1; i = i + 1) {
node1 = nodes[i]
node2 = nodes[i + 1]
if (!allowLoops) {
if (node1.id == node2.id) {
continue
}
}
edgeFound = findEdge(network.edges, node1.id, node2.id, properties.directed)
if (edgeFound == "undefined") {
edge = {
"id": "e" + network.edges.length,
"label": "1",
"source": node1.id,
"target": node2.id,
"size": 1,
"type": edgeType
}
network.edges.push(edge)
} else {
if (weighted) {
edgeFound.size = edgeFound.size + 1
edgeFound.label = core.toString(edgeFound.size)
}
}
}
} elseif (topology == "clique") {
foreach (nodes; index1; node1) {
foreach (nodes; index2; node2) {
if (!allowLoops) {
if (node1.id == node2.id) {
continue
}
}
if (index1 > index2) {
continue
}
edgeFound = findEdge(network.edges, node1.id, node2.id, properties.directed)
if (edgeFound == "undefined") {
edge = {
"id": "e" + network.edges.length,
"label": "1",
"source": node1.id,
"target": node2.id,
"size": 1,
"type": edgeType
}
network.edges.push(edge)
} else {
if (weighted) {
edgeFound.size = edgeFound.size + 1
edgeFound.label = core.toString(edgeFound.size)
}
}
}
}
} elseif (topology == "circle") {
for (i = 0; i < nodes.length - 1; i = i + 1) {
node1 = nodes[i]
node2 = nodes[i + 1]
if (!allowLoops) {
if (node1.id == node2.id) {
continue
}
}
edgeFound = findEdge(network.edges, node1.id, node2.id, properties.directed)
if (edgeFound == "undefined") {
edge = {
"id": "e" + network.edges.length,
"label": "1",
"source": node1.id,
"target": node2.id,
"size": 1,
"type": edgeType
}
network.edges.push(edge)
} else {
if (weighted) {
edgeFound.size = edgeFound.size + 1
edgeFound.label = core.toString(edgeFound.size)
}
}
if (i + 1 == nodes.length - 1) {
node1 = nodes[i + 1]
node2 = nodes[0]
edgeFound = findEdge(network.edges, node1.id, node2.id, properties.directed)
if (edgeFound == "undefined") {
edge = {
"id": "e" + network.edges.length,
"label": "1",
"source": node1.id,
"target": node2.id,
"size": 1,
"type": edgeType
}
network.edges.push(edge)
} else {
if (weighted) {
edgeFound.size = edgeFound.size + 1
edgeFound.label = core.toString(edgeFound.size)
}
}
}
}
}
properties.n = network.nodes.length
properties.m = network.edges.length
if (properties.directed) {
density = (properties.m / (properties.n * (properties.n - 1)))
} else {
density = (2 * properties.m / (properties.n * (properties.n - 1)))
}
network.density.push(density)
nodes = []
}
properties.n = network.nodes.length
properties.m = network.edges.length
t2 = core.date()
t = t2 - t1
system.println("Processed " + r.toString() + " records of " + jsonData.length.toString() + ".")
system.println("Elapsed time: " + t + " ms.")
return (network)
}
///
/// Calculate de incidence fidelity index from JSON network data.
/// @method calculateIncidenceFidelity
/// @memberof snet
/// @param {object} jsonData - JSON network data.
/// @param {object} updateWeights - Update weights on the network.
/// @return {object} Incidence fidelity table.
///
function calculateIncidenceFidelity(jsonData, updateWeights) {
if (core.type(jsonData) == "undefined") {
return("undefined")
}
if (core.type(updateWeights) == "undefined") {
updateWeights = false
}
nodes = jsonData.nodes
edges = jsonData.edges
numberOfSentences = jsonData.numberOfSentences
vocabulary = jsonData.vocabulary
ifData = {
"numberOfSentences": numberOfSentences,
"vocabulary": vocabulary,
"vocabularyByNumberOfSentences": vocabulary / numberOfSentences
}
function findNode(list, id) {
foreach (list; index; value) {
if (value.id == id) {
return(value)
}
}
return("undefined")
}
rows = []
foreach (edges; index; value) {
source = findNode(nodes, value.source)
target = findNode(nodes, value.target)
row = []
row.push(value.id)
row.push(source.label + "-" + target.label)
row.push(source.size)
row.push(target.size)
row.push(value.size)
incidence = value.size / numberOfSentences
fidelity = value.size / (source.size + target.size - value.size)
incidenceFidelity = incidence * fidelity
row.push(incidence)
row.push(fidelity)
row.push(incidenceFidelity)
rows.push(row)
if (updateWeights) {
value.size = incidenceFidelity
}
}
ifData.rows = rows
return(ifData)
}
}