diff --git a/config/Nodes.cfg b/config/Nodes.cfg index 02e7dc5b..731dab66 100644 --- a/config/Nodes.cfg +++ b/config/Nodes.cfg @@ -2,4 +2,4 @@ Alice Bob Charlie David -Eve +Eve \ No newline at end of file diff --git a/config/appNodes.cfg b/config/appNodes.cfg index 913470a1..9f88dc80 100755 --- a/config/appNodes.cfg +++ b/config/appNodes.cfg @@ -1,12 +1,5 @@ -# Network configuration file -# -# For each host its informal name, as well as its location in the network must -# be listed. -# -# [name], [hostname], [port number] -# Alice, localhost, 8811 Bob, localhost, 8812 Charlie, localhost, 8813 David, localhost, 8814 -Eve, localhost, 8815 +Eve, localhost, 8815 \ No newline at end of file diff --git a/config/classicalNet.cfg b/config/classicalNet.cfg index 015d1df7..496e5661 100755 --- a/config/classicalNet.cfg +++ b/config/classicalNet.cfg @@ -9,6 +9,4 @@ # Alice, localhost, 8811 Bob, localhost, 8812 Charlie, localhost, 8813 -David, localhost, 8814 - - +David, localhost, 8814 \ No newline at end of file diff --git a/config/cqcNodes.cfg b/config/cqcNodes.cfg index 8bd031e4..0f959917 100755 --- a/config/cqcNodes.cfg +++ b/config/cqcNodes.cfg @@ -1,12 +1,5 @@ -# Network configuration file -# -# For each host its informal name, as well as its location in the network must -# be listed. -# -# [name], [hostname], [port number] -# Alice, localhost, 8806 Bob, localhost, 8807 Charlie, localhost, 8808 David, localhost, 8809 -Eve, localhost, 8810 +Eve, localhost, 8810 \ No newline at end of file diff --git a/config/logging.cfg b/config/logging.cfg index 80b4722f..ebf34e5d 100755 --- a/config/logging.cfg +++ b/config/logging.cfg @@ -27,4 +27,3 @@ args=(sys.stdout,) [formatter_simpleFormatter] format=%(asctime)s - %(name)s - %(levelname)s - %(message)s datefmt= - diff --git a/config/topology.json b/config/topology.json index cd5f8500..6a715580 100644 --- a/config/topology.json +++ b/config/topology.json @@ -1 +1 @@ -{"Alice": ["Bob"], "Bob": ["Alice", "Charlie"], "Charlie": ["Bob"]} \ No newline at end of file +{"Alice": ["Bob","Charlie"], "Bob": ["Alice", "Charlie"], "Charlie": ["Bob"]} \ No newline at end of file diff --git a/config/topology.png b/config/topology.png new file mode 100644 index 00000000..358cddef Binary files /dev/null and b/config/topology.png differ diff --git a/config/virtualNodes.cfg b/config/virtualNodes.cfg index 1b78b8ae..7d604ca4 100755 --- a/config/virtualNodes.cfg +++ b/config/virtualNodes.cfg @@ -1,12 +1,5 @@ -# Network configuration file -# -# For each host its informal name, as well as its location in the network must -# be listed. -# -# [name], [hostname], [port number] -# Alice, localhost, 8801 Bob, localhost, 8802 Charlie, localhost, 8803 David, localhost, 8804 -Eve, localhost, 8805 +Eve, localhost, 8805 \ No newline at end of file diff --git a/cqc/backend/cqcProtocol.py b/cqc/backend/cqcProtocol.py index 96688956..5e88fc51 100755 --- a/cqc/backend/cqcProtocol.py +++ b/cqc/backend/cqcProtocol.py @@ -98,6 +98,11 @@ def lookup(self, ip, port): Lookup name of remote host used within SimulaQron given ip and portnumber. """ + # # Check if a topology is defined, otherwise use fully connected + # self._setup_topology(Settings.CONF_TOPOLOGY_FILE) + # # Check the nodes dict + # yield self.virtRoot.callRemote("update_hostDict", topology[self.name]) + for entry in self.cqcNet.hostDict: node = self.cqcNet.hostDict[entry] if (node.ip == ip) and (node.port == port): @@ -152,11 +157,19 @@ def is_adjacent(self, remote_host_name): :return: """ # Check if a topology is defined, otherwise use fully connected + self._setup_topology(Settings.CONF_TOPOLOGY_FILE) + # Check the nodes dict + yield self.virtRoot.callRemote("update_hostDict", topology[self.name]) + if self.topology is None: return True if self.name in self.topology: if remote_host_name in self.topology[self.name]: + + ## construct a link, if the nodes are not connected + self.virtRoot.callRemote("connect_to_node_by_name", remote_host_name) + return True else: return False diff --git a/examples/cqc/pythonLib/corrRNG/aliceTest.py b/examples/cqc/pythonLib/corrRNG/aliceTest.py index 215d0a8b..d7195153 100644 --- a/examples/cqc/pythonLib/corrRNG/aliceTest.py +++ b/examples/cqc/pythonLib/corrRNG/aliceTest.py @@ -52,6 +52,18 @@ def main(): print("| "+to_print+" |") print("|"+"-"*(len(to_print)+2)+"|") + fh = open(os.environ.get('NETSIM') + "/config/topology.json","w") + fh.write('{"Alice": ["Bob","Charlie"], "Bob": ["Alice", "Charlie"], "Charlie": ["Bob"]}') + + # Create an EPR pair + q = Alice.createEPR("Charlie") + + # Measure qubit + m=q.measure() + to_print="App {}: Measurement outcome is: {}".format(Alice.name,m) + print("|"+"-"*(len(to_print)+2)+"|") + print("| "+to_print+" |") + print("|"+"-"*(len(to_print)+2)+"|") ################################################################################################## main() diff --git a/examples/cqc/pythonLib/corrRNG/charlieTest.py b/examples/cqc/pythonLib/corrRNG/charlieTest.py new file mode 100644 index 00000000..5fee5c96 --- /dev/null +++ b/examples/cqc/pythonLib/corrRNG/charlieTest.py @@ -0,0 +1,58 @@ +# +# Copyright (c) 2017, Stephanie Wehner and Axel Dahlberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Stephanie Wehner, QuTech. +# 4. Neither the name of the QuTech organization nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from SimulaQron.general.hostConfig import * +from SimulaQron.cqc.backend.cqcHeader import * +from SimulaQron.cqc.pythonLib.cqc import * + + + +##################################################################################################### +# +# main +# +def main(): + + # Initialize the connection + with CQCConnection("Charlie") as Charlie: + + # Receive qubit + q=Charlie.recvEPR() + + # Measure qubit + m=q.measure() + to_print="App {}: Measurement outcome is: {}".format(Charlie.name,m) + print("|"+"-"*(len(to_print)+2)+"|") + print("| "+to_print+" |") + print("|"+"-"*(len(to_print)+2)+"|") + + +################################################################################################## +main() + diff --git a/examples/cqc/pythonLib/corrRNG/petrosTest.py b/examples/cqc/pythonLib/corrRNG/petrosTest.py new file mode 100644 index 00000000..89a06a13 --- /dev/null +++ b/examples/cqc/pythonLib/corrRNG/petrosTest.py @@ -0,0 +1,57 @@ +# +# Copyright (c) 2017, Stephanie Wehner and Axel Dahlberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by Stephanie Wehner, QuTech. +# 4. Neither the name of the QuTech organization nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ''AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from SimulaQron.general.hostConfig import * +from SimulaQron.cqc.backend.cqcHeader import * +from SimulaQron.cqc.pythonLib.cqc import * + + + +##################################################################################################### +# +# main +# +def main(): + + # Initialize the connection + with CQCConnection("Petros") as Petros: + + # Create an EPR pair + q = Petros.createEPR("Bob") + + # Measure qubit + m=q.measure() + to_print="App {}: Measurement outcome is: {}".format(Petros.name,m) + print("|"+"-"*(len(to_print)+2)+"|") + print("| "+to_print+" |") + print("|"+"-"*(len(to_print)+2)+"|") + +################################################################################################## +main() + diff --git a/examples/cqc/pythonLib/corrRNG/run.sh b/examples/cqc/pythonLib/corrRNG/run.sh index 23908b22..478ad6e4 100755 --- a/examples/cqc/pythonLib/corrRNG/run.sh +++ b/examples/cqc/pythonLib/corrRNG/run.sh @@ -1,4 +1,6 @@ #!/bin/sh - +python ../../../../run/addNode.py python aliceTest.py & -python bobTest.py & +# python bobTest.py & +# python charlieTest.py & +python petrosTest.py & \ No newline at end of file diff --git a/run/addNode.py b/run/addNode.py new file mode 100644 index 00000000..da52440d --- /dev/null +++ b/run/addNode.py @@ -0,0 +1,80 @@ +import subprocess +import os +import ast +from cabler import Command +import socket +import json + +config = os.path.normpath(os.path.join(os.path.dirname(__file__), '..', 'config')) +run = os.path.normpath(os.path.join(os.path.dirname(__file__), '..', 'run')) + +nodesFile = os.environ.get('NETSIM') + "/config/Nodes.cfg" +topologyFile = os.environ.get('NETSIM') + "/config/topology.json" + +startNode = os.environ.get('NETSIM') + "/run/startNode.py" +startCQC = os.environ.get('NETSIM') + "/run/startCQC.py" +# startCQC = os.path.join(run, 'startCQC.py') + +def get_input(): + port, host, node = None, None, None + node=input("Enter node: ") + + while(True): + try: + port=int(input("Enter port: ")) + if port >= 8000 and port <= 9000: + break + except: + print("Please provide a valid port number in the range 8000-9000.") + + while(True): + try: + host=input("Enter host: ") + socket.gethostbyname(host) + break + except socket.error: + print("Please provide a valid host name.") + + return port, host, node + +def add_cabler(port, host, node): + cabler = Command() + cabler.add_node(node, host, port) + +def read_config_Nodes(): + fh = open(nodesFile, "r") + nodes=[] + for n in fh.readlines(): + nodes.append(n.strip()) + print("The nodes are: ", nodes ) + return nodes + +def get_input_neigbors(node): + neigbors = input("Enter neigbors of "+ node ) + return neigbors + +## read the topology file and update it +def update_topology(node, neigbors): + with open(topologyFile, "r") as f: + # s = f.read() + topology = json.load(f) + topology[node] = [neigbors] + print("The new topology {}".format(topology)) + + with open(topologyFile, 'w') as fp: + fp.write(str(topology)) + + +if __name__ == "__main__": + port, host, node = get_input() + add_cabler(port, host, node) + nodes = read_config_Nodes() + neigbors = get_input_neigbors(node) + update_topology(node, neigbors) + + print("Where are here 0") + print ("python " + startNode + " " +node) + os.system("python " + startNode + " " +node + "&") + print("Where are here 1") + os.system("python "+ startCQC + " " +node + "&") + print("Where are here 2") diff --git a/run/cabler.py b/run/cabler.py index f573669e..18863d26 100755 --- a/run/cabler.py +++ b/run/cabler.py @@ -144,6 +144,7 @@ def add_node( self.topology[key].append((name, hostname, port)) self.topology['Nodes'].append(name) + self.__write_all_the_things() def remove_node(self, name): for key in ('appNodes', 'cqcNodes', 'Nodes', 'virtualNodes'): @@ -265,4 +266,4 @@ def __write_virtual_nodes(self): if __name__ == '__main__': - Command().main() + Command().main() \ No newline at end of file diff --git a/run/startNode.py b/run/startNode.py index 9571fb30..db84823d 100755 --- a/run/startNode.py +++ b/run/startNode.py @@ -37,5 +37,5 @@ virtualFile = os.environ.get('NETSIM') + "/config/virtualNodes.cfg" be = backEnd(sys.argv[1], virtualFile) - +print("----> ", sys.argv[1]) node = be.start(maxQubits=Settings.CONF_MAXQUBITS, maxRegisters=Settings.CONF_MAXREGS) diff --git a/virtNode/virtual.py b/virtNode/virtual.py index 70769c2f..79ac4d3c 100755 --- a/virtNode/virtual.py +++ b/virtNode/virtual.py @@ -197,6 +197,11 @@ def connectNet(self): e)) raise e + def remote_update_hostDict(self, node_topology): + if len(self.hostDict) != len(node_topology): + self.config.read_config(Settings.CONF_TOPOLOGY_FILE) + + def remote_check_connections(self): """ Checks if all connections are up. (Just checks if the number of connections equal the number of nodes in config-file) @@ -219,6 +224,11 @@ def get_connection(self, name): except Exception as e: raise e + def remote_connect_to_node_by_name(self, remote_node_name): + print("remte_node_name: {}".format(remote_node_name)) + if remote_node_name not in self.conn: + self.connect_to_node(self.config.hostDict[remote_node_name] ) + def connect_to_node(self, node): """ Connects to other node. If node not up yet, waits for CONF_WAIT_TIME seconds.