commit 71053249f78f3d2a4f5336cf6f44a15125e40288
parent 4afaa53aba8b86556ab2d600da926a3069f4cb46
Author: Cody Lewis <codymlewis@protonmail.com>
Date: Sat, 30 Mar 2019 15:23:42 +1100
Split the program into a few separate files and add command line flags
Diffstat:
8 files changed, 228 insertions(+), 191 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -391,3 +391,4 @@ TSWLatexianTemp*
tags
tags.lock
Session.vim
+reports.csv
diff --git a/BadMouther/__init__.py b/BadMouther/__init__.py
@@ -0,0 +1,9 @@
+import Node
+
+
+class BadMouther(Node.Node):
+ '''
+ A bad mouthing malicious node.
+ '''
+ def take_note(self, proxy, service_target, capability_target):
+ return -1
diff --git a/Functions.py b/Functions.py
@@ -0,0 +1,43 @@
+import numpy as np
+
+
+def print_progress(current_epoch, total_epochs, progress_len=20):
+ '''
+ Print a progress bar about how far a process has went through it's epochs.
+ '''
+ progress = int(100 * current_epoch / total_epochs)
+
+ if (100 * current_epoch / total_epochs) == progress:
+ progress_bar_progress = int(progress_len * progress * 0.01)
+ if progress_bar_progress != 0:
+ unprogressed = progress_len - progress_bar_progress
+ else:
+ unprogressed = progress_len - 1
+ progress_bar = "["
+ progress_bar += "".join(
+ ["#" for _ in range(progress_bar_progress - 1)]
+ )
+ progress_bar += "".join(["." for _ in range(unprogressed)])
+ progress_bar += "]"
+ print(f"{progress_bar} {progress}%")
+
+
+def wrong_note(note):
+ '''
+ Get the wrong note randomly
+ '''
+ wrong_notes = {-1, 0, 1} - {note}
+ return list(wrong_notes)[int(np.round(np.random.rand()))]
+
+
+def get_conditioned_ids(no_of_nodes, condition_factor):
+ '''
+ Give an id list of random nodes that fit a given condition.
+ '''
+ conditioned_list = []
+ ids = [i for i in range(no_of_nodes)]
+
+ for _ in range(int(no_of_nodes * condition_factor)):
+ conditioned_list.append(ids.pop(np.random.randint(len(ids))))
+
+ return conditioned_list
diff --git a/Node/__init__.py b/Node/__init__.py
@@ -0,0 +1,36 @@
+import numpy as np
+
+import Functions
+import Report
+
+
+class Node:
+ '''
+ A node in the trust managed network.
+ '''
+ def __init__(self, service=100, capability=100, note_acc=1.0):
+ self.service = service
+ self.capability = capability
+ self.note_taking_acc = note_acc # This is unknown to the trust manager
+
+ def send_report(self, proxy, service_target, capability_target, time):
+ '''
+ Create a report on a given proxy.
+ '''
+ note = self.take_note(proxy, service_target, capability_target)
+
+ return Report.Report(service_target, capability_target, note, time)
+
+ def take_note(self, proxy, service_target, capability_target):
+ if proxy.service >= service_target and \
+ proxy.capability >= capability_target:
+ note = 1
+ elif proxy.service >= service_target or \
+ proxy.capability >= capability_target:
+ note = 0
+ else:
+ note = -1
+
+ if np.random.rand() < self.note_taking_acc:
+ return note
+ return Functions.wrong_note(note)
diff --git a/Report/__init__.py b/Report/__init__.py
@@ -0,0 +1,15 @@
+class Report:
+ '''
+ Report that states the context and how well the node performed at that.
+ '''
+ def __init__(self, service=0, capability=0, note=0, time=0):
+ self.service = service
+ self.capability = capability
+ self.note = note
+ self.time = time
+
+ def csv_output(self):
+ '''
+ Output contained data in a format suitable for a csv
+ '''
+ return f"{self.service},{self.capability},{self.note},{self.time}"
diff --git a/Test.py b/Test.py
@@ -2,7 +2,11 @@
import unittest
import numpy as np
-import TrustModel
+import Functions
+import Report
+import Node
+import BadMouther
+import TrustManager
'''
Perform unit tests on the program.
@@ -27,7 +31,7 @@ class TestTrustModel(unittest.TestCase):
'''
Test the creation of reports.
'''
- report = TrustModel.Report(service, capability, note, time)
+ report = Report.Report(service, capability, note, time)
self.assertEqual(report.service, service)
self.assertEqual(report.capability, capability)
self.assertEqual(report.note, note)
@@ -41,18 +45,18 @@ class TestTrustModel(unittest.TestCase):
Test that the wrong note is assigned for each possible note.
'''
for note in [-1, 0, 1]:
- self.assertNotEqual(TrustModel.wrong_note(note), note)
+ self.assertNotEqual(Functions.wrong_note(note), note)
def test_note_take(self):
'''
Test that note taking returns the expected values.
'''
- node = TrustModel.Node()
- proxy = TrustModel.Node()
+ node = Node.Node()
+ proxy = Node.Node()
self.assertEqual(node.take_note(proxy, 50, 50), 1)
- proxy = TrustModel.Node(100, 1)
+ proxy = Node.Node(100, 1)
self.assertEqual(node.take_note(proxy, 50, 50), 0)
- proxy = TrustModel.Node(1, 1)
+ proxy = Node.Node(1, 1)
self.assertEqual(node.take_note(proxy, 50, 50), -1)
def test_network_creation(self):
@@ -63,7 +67,7 @@ class TestTrustModel(unittest.TestCase):
constrained_nodes = 0.5
poor_witnesses = 0.2
malicious_nodes = 0.1
- trust_manager = TrustModel.TrustManager(
+ trust_manager = TrustManager.TrustManager(
no_of_nodes, constrained_nodes, poor_witnesses, malicious_nodes
)
self.assertEqual(len(trust_manager.network), no_of_nodes)
@@ -76,7 +80,7 @@ class TestTrustModel(unittest.TestCase):
num_constrained += 1
if node.note_taking_acc < 1.0:
num_poor_witnesses += 1
- if isinstance(node, TrustModel.BadMouther):
+ if isinstance(node, BadMouther.BadMouther):
num_malicious += 1
self.assertEqual(no_of_nodes * constrained_nodes, num_constrained)
@@ -87,14 +91,14 @@ class TestTrustModel(unittest.TestCase):
'''
Test the report creation of the bad mouther.
'''
- proxy = TrustModel.Node(100, 100)
- bad_mouther = TrustModel.BadMouther()
+ proxy = Node.Node(100, 100)
+ bad_mouther = BadMouther.BadMouther()
self.make_report(bad_mouther, proxy, note=-1)
- proxy = TrustModel.Node(1, 100)
+ proxy = Node.Node(1, 100)
self.make_report(bad_mouther, proxy, note=-1)
- proxy = TrustModel.Node(100, 1)
+ proxy = Node.Node(100, 1)
self.make_report(bad_mouther, proxy, note=-1)
- proxy = TrustModel.Node(1, 1)
+ proxy = Node.Node(1, 1)
self.make_report(bad_mouther, proxy, note=-1)
def make_report(self, client, proxy, service=50,
@@ -109,7 +113,7 @@ class TestTrustModel(unittest.TestCase):
self.assertEqual(report.time, time)
def test_bootstrap(self):
- trust_manager = TrustModel.TrustManager()
+ trust_manager = TrustManager.TrustManager()
no_of_transactions = 5
trust_manager.bootstrap(no_of_transactions)
diff --git a/TrustManager/__init__.py b/TrustManager/__init__.py
@@ -0,0 +1,85 @@
+import numpy as np
+
+import Functions
+import Node
+import BadMouther
+
+
+class TrustManager:
+ '''
+ Create and control the network.
+ '''
+ def __init__(self, no_of_nodes=200, constrained_nodes=0.5,
+ poor_witnesses=0.2, malicious_nodes=0.1):
+ self.network = []
+ constrained_list = Functions.get_conditioned_ids(
+ no_of_nodes, constrained_nodes
+ )
+ poor_witness_list = Functions.get_conditioned_ids(
+ no_of_nodes, poor_witnesses
+ )
+ malicious_list = Functions.get_conditioned_ids(
+ no_of_nodes, malicious_nodes
+ )
+
+ for i in range(no_of_nodes):
+ if i in constrained_list:
+ service = np.round(np.random.rand())
+ capability = np.round(np.random.rand())
+ else:
+ service = 100
+ capability = 100
+ note_acc = np.random.rand() if i in poor_witness_list else 1.0
+ if i in malicious_list:
+ self.network.append(
+ BadMouther.BadMouther(service, capability, note_acc)
+ )
+ else:
+ self.network.append(Node.Node(service, capability, note_acc))
+
+ self.reports = [
+ [[] for _ in range(no_of_nodes)] for _ in range(no_of_nodes)
+ ]
+
+ def bootstrap(self, epochs=100):
+ '''
+ Go through the network and perform artificial transactions to develop
+ reports.
+ '''
+ print(f"\nBootstrapping network for {epochs} epochs:")
+ Functions.print_progress(0, epochs)
+ for i in range(1, epochs + 1):
+ self._artificial_transactions(i)
+ Functions.print_progress(i, epochs)
+ print("Done.")
+
+ def _artificial_transactions(self, current_epoch):
+ '''
+ Perform some transactions through the entire network with random
+ targets.
+ '''
+ for i_node_i in enumerate(self.network):
+ for j_node_j in enumerate(self.network):
+ if i_node_i[0] != j_node_j[0]:
+ service_target = np.round(np.random.rand() * 100)
+ capability_target = np.round(np.random.rand() * 100)
+ self.reports[i_node_i[0]][j_node_j[0]].append(
+ i_node_i[1].send_report(
+ j_node_j[1],
+ service_target,
+ capability_target,
+ current_epoch
+ )
+ )
+
+ def save_reports_csv(self, filename="reports.csv"):
+ '''
+ Save a csv on the report data
+ '''
+ with open(filename, "w") as report_csv:
+ for reports_from_node_i in enumerate(self.reports):
+ for reports_on_node_j in enumerate(reports_from_node_i[1]):
+ for report in reports_on_node_j[1]:
+ report_csv.write(
+ f"{reports_from_node_i[0]},{reports_on_node_j[0]},{report.csv_output()}\n"
+ )
diff --git a/TrustModel.py b/TrustModel.py
@@ -1,6 +1,9 @@
#!/usr/bin/env python3
-import numpy as np
+import sys
+import argparse
+
+import TrustManager
'''
A trust model simulation which uses machine learning techniques to find trust.
@@ -10,179 +13,20 @@ Date: 2019-03-12
'''
-class Report:
- '''
- Report that states the context and how well the node performed at that.
- '''
- def __init__(self, service=0, capability=0, note=0, time=0):
- self.service = service
- self.capability = capability
- self.note = note
- self.time = time
-
- def csv_output(self):
- '''
- Output contained data in a format suitable for a csv
- '''
- return f"{self.service},{self.capability},{self.note},{self.time}"
-
-
-class Node:
- '''
- A node in the trust managed network.
- '''
- def __init__(self, service=100, capability=100, note_acc=1.0):
- self.service = service
- self.capability = capability
- self.note_taking_acc = note_acc # This is unknown to the trust manager
-
- def send_report(self, proxy, service_target, capability_target, time):
- '''
- Create a report on a given proxy.
- '''
- note = self.take_note(proxy, service_target, capability_target)
-
- return Report(service_target, capability_target, note, time)
-
- def take_note(self, proxy, service_target, capability_target):
- if proxy.service >= service_target and \
- proxy.capability >= capability_target:
- note = 1
- elif proxy.service >= service_target or \
- proxy.capability >= capability_target:
- note = 0
- else:
- note = -1
-
- if np.random.rand() < self.note_taking_acc:
- return note
- return wrong_note(note)
-
-
-class BadMouther(Node):
- '''
- A bad mouthing malicious node.
- '''
- def take_note(self, proxy, service_target, capability_target):
- return -1
-
-
-class TrustManager:
- '''
- Create and control the network.
- '''
- def __init__(self, no_of_nodes=200, constrained_nodes=0.5,
- poor_witnesses=0.2, malicious_nodes=0.1):
- self.network = []
- constrained_list = get_conditioned_ids(no_of_nodes, constrained_nodes)
- poor_witness_list = get_conditioned_ids(no_of_nodes, poor_witnesses)
- malicious_list = get_conditioned_ids(no_of_nodes, malicious_nodes)
-
- for i in range(no_of_nodes):
- if i in constrained_list:
- service = np.round(np.random.rand())
- capability = np.round(np.random.rand())
- else:
- service = 100
- capability = 100
- note_acc = np.random.rand() if i in poor_witness_list else 1.0
- if i in malicious_list:
- self.network.append(BadMouther(service, capability, note_acc))
- else:
- self.network.append(Node(service, capability, note_acc))
-
- self.reports = [
- [[] for _ in range(no_of_nodes)] for _ in range(no_of_nodes)
- ]
-
- def bootstrap(self, epochs=100):
- '''
- Go through the network and perform artificial transactions to develop
- reports.
- '''
- print(f"\nBootstrapping network for {epochs} epochs:")
- print_progress(0, epochs)
- for i in range(1, epochs + 1):
- self._artificial_transactions(i)
- print_progress(i, epochs)
- print("Done.")
-
- def _artificial_transactions(self, current_epoch):
- '''
- Perform some transactions through the entire network with random
- targets.
- '''
- for i_node_i in enumerate(self.network):
- for j_node_j in enumerate(self.network):
- if i_node_i[0] != j_node_j[0]:
- service_target = np.round(np.random.rand() * 100)
- capability_target = np.round(np.random.rand() * 100)
- self.reports[i_node_i[0]][j_node_j[0]].append(
- i_node_i[1].send_report(
- j_node_j[1],
- service_target,
- capability_target,
- current_epoch
- )
- )
-
- def save_reports_csv(self):
- '''
- Save a csv on the report data
- '''
- with open("reports.csv", "w") as report_csv:
- for reports_from_node_i in enumerate(self.reports):
- for reports_on_node_j in enumerate(reports_from_node_i[1]):
- for report in reports_on_node_j[1]:
- report_csv.write(
- f"{reports_from_node_i[0]},{reports_on_node_j[0]},{report.csv_output()}\n"
- )
-
-
-def get_conditioned_ids(no_of_nodes, condition_factor):
- '''
- Give an id list of random nodes that fit a given condition.
- '''
- conditioned_list = []
- ids = [i for i in range(no_of_nodes)]
-
- for _ in range(int(no_of_nodes * condition_factor)):
- conditioned_list.append(ids.pop(np.random.randint(len(ids))))
-
- return conditioned_list
-
-
-def print_progress(current_epoch, total_epochs, progress_len=20):
- '''
- Print a progress bar about how far a process has went through it's epochs.
- '''
- progress = int(100 * current_epoch / total_epochs)
-
- if (100 * current_epoch / total_epochs) == progress:
- progress_bar_progress = int(progress_len * progress * 0.01)
- if progress_bar_progress != 0:
- unprogressed = progress_len - progress_bar_progress
- else:
- unprogressed = progress_len - 1
- progress_bar = "["
- progress_bar += "".join(
- ["#" for _ in range(progress_bar_progress - 1)]
- )
- progress_bar += "".join(["." for _ in range(unprogressed)])
- progress_bar += "]"
- print(f"{progress_bar} {progress}%")
-
-
-def wrong_note(note):
- '''
- Get the wrong note randomly
- '''
- wrong_notes = {-1, 0, 1} - {note}
- return list(wrong_notes)[int(np.round(np.random.rand()))]
-
-
if __name__ == '__main__':
- TRUST_MANAGER = TrustManager()
- TRUST_MANAGER.bootstrap(1000)
- TRUST_MANAGER.save_reports_csv()
- print(f"Shape of the reports: {np.shape(TRUST_MANAGER.reports)}")
+ PARSER = argparse.ArgumentParser(description="Simulate a trust model")
+ PARSER.add_argument("--create-data", dest="is_creating",
+ action="store_const", const=True, default=False,
+ help="Create data and place it in the csv file.")
+ PARSER.add_argument("-f", "--file", dest="filename",
+ action="store", default="reports.csv",
+ help="Specify the file to read from or write to.")
+ ARGS = PARSER.parse_args()
+
+ if len(sys.argv) == 1:
+ PARSER.print_help()
+
+ if ARGS.is_creating:
+ TRUST_MANAGER = TrustManager.TrustManager()
+ TRUST_MANAGER.bootstrap(500)
+ TRUST_MANAGER.save_reports_csv(ARGS.filename)