Example #1
0
def test_agent_hello(DummyAgent, address_config_file):
    ag = DummyAgent(1, str(address_config_file))
    ag.start()
    messenger = ZTesterMessenger('tester')
    participants = Participants(str(address_config_file))
    ctx = zmq.Context()
    ssend = ctx.socket(zmq.PUSH)
    ssend.connect(participants.address('agent'))
    srecv = ctx.socket(zmq.PULL)
    srecv.bind(participants.address('mediator'))
    ssend.send_string(str(messenger.build_start_message()))
    content = list(range(10))
    ssend.send_string(
        json.dumps({
            'sender': 'oi',
            'receiver': '',
            'type': 'bumba',
            'content': content
        }))
    msg = Message.from_json(srecv.recv_json())
    assert msg.sender == 'agent'
    assert msg.type == 'RESULT'
    assert msg.content == content[::-1]
    ssend.send_string(str(messenger.build_stop_message()))
    ag.join()
Example #2
0
 def __init__(self, aux_id, main_config, run_config, address_config, component_config=None):
     super().__init__()
     self.aux_id = aux_id
     self.config = load_config(main_config)
     self.run_config = load_config(run_config, self.config['simulation']['variables'])
     self.participants = Participants(address_config)
     if component_config is not None:
         self.components = ComponentManager.get_component_enum(component_config)
     self.sockets = {}
Example #3
0
 def __init__(self, participants_config, components_config=None):
     super().__init__()
     # TODO: give a better name
     self.places = []
     self.agent_positions = {}
     self.participants = Participants(participants_config)
     self._messenger = None
     if components_config is not None:
         self.components = ComponentManager.get_component_enum(
             components_config)
Example #4
0
 def __init__(self, address_config, component_config=None):
     super().__init__()
     # communication
     participants = Participants(address_config)
     self.address = participants.address('strategy')
     self.tester_address = participants.address('tester')
     self.socket_receive = None
     self.socket_send = None
     # internal state
     if component_config is not None:
         self.components = ComponentManager.get_component_enum(component_config)
Example #5
0
 def __init__(self, ag_id, address_config, component_config=None):
     super().__init__()
     self.id = ag_id
     # communication
     participants = Participants(address_config)
     self.address = participants.address(self.alias)
     self.mediator_address = participants.address('mediator')
     self.socket_receive = None
     self.socket_send = None
     self._messenger = None
     # internal state
     if component_config is not None:
         self.components = ComponentManager.get_component_enum(component_config)
Example #6
0
 def __init__(self, ag_id, address_config, component_config=None):
     super().__init__()
     self.id = ag_id
     # communication
     participants = Participants(address_config)
     self.address = participants.address(self.alias)
     self.mediator_address = participants.address('mediator')
     self.socket_receive = None
     self.socket_send = None
     self._messenger = None
     # internal state
     if component_config is not None:
         self.components = ComponentManager.get_component_enum(
             component_config)
Example #7
0
 def __init__(self, participants_config, components_config=None):
     super().__init__()
     # TODO: give a better name
     self.places = []
     self.agent_positions = {}
     self.participants = Participants(participants_config)
     self._messenger = None
     if components_config is not None:
         self.components = ComponentManager.get_component_enum(components_config)
Example #8
0
 def __init__(self, participants_config, tester_alias="tester"):
     super().__init__()
     self.simulation_participants = SimulationParticipants(participants_config)
     self.participants = {}
     self.participant_sockets = {}
     self.tester_alias = tester_alias
     # TODO please, rename this
     self.sockets_participants = {}
     self._log = []
Example #9
0
def test_participants_invalid_alias_and_address(address_configuration_file, config_json):
    participants = Participants(str(address_configuration_file))
    alias, address = random.choice(list(config_json.items()))
    with pytest.raises(KeyError):
        participants.alias(address + address)
    with pytest.raises(KeyError):
        participants.address(alias + alias)
Example #10
0
class Tester(BaseTester):
    messenger_class = TesterMessenger

    def __init__(self,
                 main_config,
                 run_config,
                 address_config,
                 component_config=None):
        super().__init__()
        self.config = load_config(main_config)
        self.run_config = load_config(run_config,
                                      self.config['simulation']['variables'])
        self.participants = Participants(address_config)
        if component_config is not None:
            self.components = ComponentManager.get_component_enum(
                component_config)
        self.sockets = {}

    @property
    def alias(self):
        return 'tester'

    def run(self):
        logging.info('Tester: running.')
        mode = Mode.from_string(self.config['simulation']['mode'])
        self.context = zmq.Context()
        self.socket_receive = self.context.socket(zmq.PULL)
        self.socket_receive.bind(self.participants.address('tester'))
        self.initialize_participants()
        self.main_loop(mode)
        logging.debug('Tester: stopping.')
        time.sleep(2)

    def initialize_participants(self):
        logging.info("Tester: initializing participants")
        for alias in self.run_config.keys():
            self.initialize_participant(alias)

    def initialize_participants_distributed(self):
        logging.info("Tester: initializing participants")
        self.initialize_participant('strategy')
        self.config['auxiliares'].keys()
        for participant in self.participants.aliases:
            if not participant.startswith('tester_'):
                continue
            self.initialize_participant(participant)

    def stop_participants(self):
        logging.info("Tester: stopping participants")
        stop_message = str(self.messenger.build_stop_message())
        for alias in self.run_config.keys():
            self.sockets[alias].send_string(stop_message)

    def main_loop(self, mode):
        result = None
        if mode == Mode.CENTRALIZED:
            result = self.main_loop_centralized()
        elif mode == Mode.DISTRIBUTED:
            result = self.main_loop_distributed()
        else:
            msg = "Unknown mode: {}".format(mode)
            logging.error(msg)
            raise CoreException(msg)
        return result

    def main_loop_centralized(self):
        """
        """
        start_message = str(self.messenger.build_start_message())
        stop_message = str(self.messenger.build_stop_message())

        self.sockets['strategy'].send_string(
            str(self.build_strategy_config_message()))
        self.sockets['strategy'].send_string(start_message)
        self.sockets['mediator'].send_string(
            str(self.build_mediator_config_message()))
        while True:
            logging.debug('Tester: waiting message from strategy')
            msg = self.receive_message()
            logging.debug('Tester received {}'.format(str(msg)))
            if msg.sender != 'strategy':
                logging.error(
                    'received message from {} instead of strategy'.format(
                        msg.sender))
                # we shouldn't been receiving messages from any other sender at this point...
                break
            if msg.type == 'STOP':
                logging.debug('stop participants')
                self.stop_participants()
                break
            elif msg.type == 'EVALUATE':
                time.sleep(.01)
                self.sockets['mediator'].send_string(start_message)
                logging.debug('Tester: lets configure environment')
                evaluation_id = msg.content.get('id')
                environ_config = self.build_environment_config_message(
                    msg.content)

                self.sockets['environment'].send_string(str(environ_config))
                self.sockets['environment'].send_string(start_message)
                # TODO this must work for multiple agents
                logging.debug('Tester: lets configure agent(s)')
                for agent_alias in self.get_agents_aliases():
                    self.sockets[agent_alias].send_string(
                        str(self.build_agent_config_message()))
                    self.sockets[agent_alias].send_string(start_message)
                logging.debug('Tester: waiting for mediator\'s answer')
                msg = self.receive_message()
                logging.debug('Tester evaluate {}'.format(str(msg)[:50]))
                result = {
                    'id': evaluation_id,
                    'data': self.evaluate(msg.content)
                }
                # TODO check if the message is from mediator or raise error
                logging.debug(
                    'Tester: send answer to strategy {}'.format(result))
                result_message = self.messenger.build_result_message(
                    receiver='strategy', content=result)
                self.sockets['strategy'].send_string(str(result_message))
        logging.debug('Tester: waiting report...')
        msg = self.receive_message()
        self.report_result(msg)

    def receive_message_from_poller(self, poller, socket, timeout):
        result = poller.poll(timeout)
        if socket in result:
            return Message.from_string(socket.recv_string())
        return None

    def get_auxiliary_testers_aliases(self):
        return [a for a in self.run_config.keys() if a.startswith('aux')]

    def main_loop_distributed(self):
        start_message = str(self.messenger.build_start_message())
        stop_message = str(self.messenger.build_stop_message())

        self.sockets['strategy'].send_string(
            str(self.build_strategy_config_message()))
        self.sockets['strategy'].send_string(start_message)

        eval_buffer = deque()
        available_testers = set(self.get_auxiliary_testers_aliases())
        working_testers = set()
        poller = zmq.Poller()
        poller.register(self.socket_receive, zmq.POLLIN)
        should_stop = False
        while not should_stop or len(working_testers) > 0:
            socket = dict(poller.poll(100))
            if self.socket_receive in socket:
                msg = Message.from_string(self.socket_receive.recv_string())
                if msg.sender == 'strategy':
                    if msg.type == 'EVALUATE':
                        eval_buffer.append(msg)
                    elif msg.type == 'STOP':
                        should_stop = True
                elif msg.sender.startswith('aux'):
                    working_testers.remove(msg.sender)
                    available_testers.add(msg.sender)
                    self.sockets['strategy'].send_string(str(msg))

            while len(available_testers) > 0 and len(eval_buffer) > 0:
                msg = eval_buffer.popleft()
                # handle stop message
                tester = available_testers.pop()
                working_testers.add(tester)
                # TODO
                msg.sender = 'tester'
                self.sockets[tester].send_string(str(msg))
        time.sleep(2)
        self.stop_participants()
        logging.debug('tester, waiting report...')
        msg = self.receive_message()
        self.report_result(msg)
        poller.unregister(self.socket_receive)
Example #11
0
class Environment(abc.ABC, Process):
    messenger_class = EnvironmentMessenger

    def __init__(self, participants_config, components_config=None):
        super().__init__()
        # TODO: give a better name
        self.places = []
        self.agent_positions = {}
        self.participants = Participants(participants_config)
        self._messenger = None
        if components_config is not None:
            self.components = ComponentManager.get_component_enum(components_config)

    @property
    def messenger(self):
        if self._messenger is None:
            if self.messenger_class is None:
                raise ZephyrusException("Calling 'messenger' without defining 'messenger_class'")
            self._messenger = self.messenger_class('environment')
        return self._messenger

    def run(self):
        # TODO add log
        context = zmq.Context()
        self.socket_receive = context.socket(zmq.PULL)
        self.socket_receive.bind(self.participants.address('environment'))
        self.socket_send = context.socket(zmq.PUSH)
        # connect with interaction
        self.socket_send.connect(self.participants.address('mediator'))
        logging.info("Environment: running.")
        self.ready()

    def ready(self):
        while True:
            logging.debug('Environmnent is ready.')
            msg = Message.from_string(self.socket_receive.recv_string())
            if msg.type == "START":
                self.mainloop()
            elif msg.type == "STOP":
                logging.info("Environment: stopping.")
                break
            elif msg.type == "CONFIG":
                self.configure(msg.content)
            else:
                logging.error("Environmnent received an invalid message.")
                logging.error(str(msg))

    @abc.abstractmethod
    def mainloop(self):
        pass

    @abc.abstractmethod
    def configure(self, config_data):
        pass

    def __str__(self):
        return 'Environ: ' + ' '.join(self.places[:])

    def add_agent(self, agent_id, line, col):
        if not 0 <= line < self.nlines or 0 <= col < self.ncols:
            raise ValueError("Invalid line or col provided")
        self.agent_pos[agent_id] = (line, col)
        return len(self.agent_pos)
Example #12
0
class AuxiliaryTester(BaseTester):
    messenger_class = AuxiliaryTesterMessenger

    def __init__(self, aux_id, main_config, run_config, address_config, component_config=None):
        super().__init__()
        self.aux_id = aux_id
        self.config = load_config(main_config)
        self.run_config = load_config(run_config, self.config['simulation']['variables'])
        self.participants = Participants(address_config)
        if component_config is not None:
            self.components = ComponentManager.get_component_enum(component_config)
        self.sockets = {}

    @property
    def alias(self):
        return 'aux_{}'.format(self.aux_id)

    def run(self):
        logging.info('Auxiliary {}: running.'.format(self.aux_id))
        self.context = zmq.Context()
        # connect to main
        self.socket_main = self.context.socket(zmq.PUSH)
        self.socket_main.connect(self.participants.address('tester'))
        self.socket_receive = self.context.socket(zmq.PULL)
        self.socket_receive.bind(self.participants.address(self.alias))
        self.initialize_participants()
        self.main_loop()
        logging.debug('Auxiliary {}: stopping'.format(self.aux_id))
        time.sleep(2)

    def initialize_participants(self):
        logging.info("Auxiliary Tester: initializing participants")
        for alias in self.run_config.keys():
            self.initialize_participant(alias)

    def stop_participants(self):
        logging.info("Auxiliary Tester: stopping participants")
        stop_message = str(self.messenger.build_stop_message())
        for alias in self.run_config.keys():
            self.sockets[alias].send_string(stop_message)

    def main_loop(self):
        start_message = str(self.messenger.build_start_message())
        stop_message = str(self.messenger.build_stop_message())

        self.sockets['mediator'].send_string(str(self.build_mediator_config_message()))
        while True:
            logging.debug('Auxiliary {}: waiting message from strategy'.format(self.aux_id))
            msg = self.receive_message()
            logging.debug('Auxiliary Tester {}: received {}'.format(self.aux_id, str(msg)))
            if msg.sender != 'tester':
                logging.error('received message from {} instead of tester'.format(msg.sender))
                # we shouldn't been receiving messages from any other sender at this point...
                break
            if msg.type == 'STOP':
                logging.debug('stop participants')
                self.stop_participants()
                break
            elif msg.type == 'EVALUATE':
                self.sockets['mediator'].send_string(start_message)
                time.sleep(.01)
                logging.debug('Auxiliary: lets configure environment')
                evaluation_id = msg.content.get('id')
                environ_config = self.build_environment_config_message(msg.content)
                self.sockets['environment'].send_string(str(environ_config))
                self.sockets['environment'].send_string(start_message)
                # TODO this must work for multiple agents
                logging.debug('Auxiliary: lets configure agent(s)')
                for agent_alias in self.get_agents_aliases():
                    self.sockets[agent_alias].send_string(str(self.build_agent_config_message()))
                    self.sockets[agent_alias].send_string(start_message)
                logging.debug('Auxiliary: waiting for mediator\'s answer')
                msg = self.receive_message()
                logging.debug('Auxiliary: evaluate {}'.format(str(msg)[:50]))
                result = {
                    'id': evaluation_id,
                    'data': self.evaluate(msg.content)
                }

                # TODO check if the message is from mediator or raise error
                logging.debug('Auxiliary: send answer to strategy')
                result_message = self.messenger.build_result_message(receiver='tester', content=result)
                self.socket_main.send_string(str(result_message))
Example #13
0
class Mediator(Process):
    messenger_class = MediatorMessenger

    def __init__(self, participants_config, tester_alias="tester"):
        super().__init__()
        self.simulation_participants = SimulationParticipants(participants_config)
        self.participants = {}
        self.participant_sockets = {}
        self.tester_alias = tester_alias
        # TODO please, rename this
        self.sockets_participants = {}
        self._log = []

    @property
    def messenger(self):
        if getattr(self, '_messenger', None) is None:
            self._messenger = self.messenger_class('mediator')
        return self._messenger

    def run(self):
        self.context = zmq.Context()
        self.socket_receive = self.context.socket(zmq.PULL)
        address = self.simulation_participants.address('mediator')
        self.socket_receive.bind(address)
        self.socket_tester = self.context.socket(zmq.PUSH)
        address = self.simulation_participants.address(self.tester_alias)
        self.socket_tester.connect(address)
        self.connect_to_participants()
        logging.info('Mediator: running.')
        self.ready()

    def connect_to_participants(self):
        self.remove_all_participants()
        logging.debug('Mediator is connecting to all participants')
        for alias, address in self.participants.items():
            self.sockets_participants[alias] = self.context.socket(zmq.PUSH)
            self.sockets_participants[alias].connect(address)

    def remove_all_participants(self):
        logging.debug('Mediator is removing all participants')
        # explicitly closing sockets altough GC handles it for us.
        # http://pyzmq.readthedocs.io/en/latest/api/zmq.html#zmq.Socket.close
        for socket in self.sockets_participants.values():
            pass
            # if not socket.closed:
            #    print('oi')
            #    socket.close()
        self.sockets_participants = {}

    def ready(self):
        while True:
            logging.debug('Mediator is ready!!')
            # TODO APL
            msg = Message.from_string(self.socket_receive.recv_string())
            logging.debug('Mediator: received {}'.format(str(msg)))
            if msg.type == "FINISH":
                self.broadcast(self.messenger.build_finish_message())
                break
            elif msg.type == "START":
                self.mainloop()
            elif msg.type == "CONFIG":
                self.configure(msg.content)
            elif msg.type == "STOP":
                logging.info("Mediator: stopping.")
                break
            else:
                logging.error('Mediator received invalid message {}'.format(str(msg)))

    def get_next_message_string(self):
        if len(self.msg_buffer) > 0:
            return self.msg_buffer.popleft()
        return self.socket_receive.recv_string()

    def configure(self, content):
        self.participants = content
        self.connect_to_participants()

    def mainloop(self):
        active_participants = set(self.participants.keys())
        logging.debug('Mediator, participants are: {}'.format(self.participants))
        nstarted = 0
        self.msg_buffer = deque()
        while nstarted < len(active_participants):
            msg_str = self.socket_receive.recv_string()
            msg = Message.from_string(msg_str)
            if msg.receiver != 'mediator' or msg.type != 'START':
                self.msg_buffer.append(msg_str)
                logging.debug("Monitor: buffering message '{}'".format(msg_str))
                # TODO raise error
            else:
                logging.debug("Monitor: a  participant started")
                nstarted += 1
        while len(active_participants) > 0:
            msg_str = self.get_next_message_string()
            logging.debug('Mediator, received {}'.format(msg_str))
            msg = Message.from_string(msg_str)
            sender = msg.sender
            receiver = msg.receiver

            if sender is None or receiver is None:
                emsg = "Messages sent through Mediator must specify both sender and receiver."
                raise CoreException(emsg)

            if receiver == 'mediator':
                # TODO we must made clear the difference between FINISH and STOP
                if msg.type == 'STOP':
                    active_participants.remove(sender)
            else:
                self._log.append(msg_str)
                logging.debug('Mediator: sending it to {}'.format(receiver))
                self.sockets_participants[receiver].send_string(msg_str)
        # TODO We must improve this. Think about how badly this scales.
        msg = Message('mediator', 'tester', 'RESULT', self._log)
        self.socket_tester.send_string(str(msg))
        self._log = []

    def add_participant(self, pid: int, address: str):
        # TODO apl
        # print 'adcionou participante', pid, 'em', endereco
        self.participants[pid] = address

    def remove_particioant(self, pid: int):
        del self.participants[pid]

    def broadcast(self, message):
        raw = str(message)
        for pid in self.participants:
            self.sockets_participants[pid].send(raw)
Example #14
0
class Environment(abc.ABC, Process):
    messenger_class = EnvironmentMessenger

    def __init__(self, participants_config, components_config=None):
        super().__init__()
        # TODO: give a better name
        self.places = []
        self.agent_positions = {}
        self.participants = Participants(participants_config)
        self._messenger = None
        if components_config is not None:
            self.components = ComponentManager.get_component_enum(
                components_config)

    @property
    def messenger(self):
        if self._messenger is None:
            if self.messenger_class is None:
                raise ZephyrusException(
                    "Calling 'messenger' without defining 'messenger_class'")
            self._messenger = self.messenger_class('environment')
        return self._messenger

    def run(self):
        # TODO add log
        context = zmq.Context()
        self.socket_receive = context.socket(zmq.PULL)
        self.socket_receive.bind(self.participants.address('environment'))
        self.socket_send = context.socket(zmq.PUSH)
        # connect with interaction
        self.socket_send.connect(self.participants.address('mediator'))
        logging.info("Environment: running.")
        self.ready()

    def ready(self):
        while True:
            logging.debug('Environmnent is ready.')
            msg = Message.from_string(self.socket_receive.recv_string())
            if msg.type == "START":
                self.mainloop()
            elif msg.type == "STOP":
                logging.info("Environment: stopping.")
                break
            elif msg.type == "CONFIG":
                self.configure(msg.content)
            else:
                logging.error("Environmnent received an invalid message.")
                logging.error(str(msg))

    @abc.abstractmethod
    def mainloop(self):
        pass

    @abc.abstractmethod
    def configure(self, config_data):
        pass

    def __str__(self):
        return 'Environ: ' + ' '.join(self.places[:])

    def add_agent(self, agent_id, line, col):
        if not 0 <= line < self.nlines or 0 <= col < self.ncols:
            raise ValueError("Invalid line or col provided")
        self.agent_pos[agent_id] = (line, col)
        return len(self.agent_pos)
Example #15
0
def test_participants_invalid_config_file(tmpdir):
    p = tmpdir.mkdir("foo").join("fakeconfig.json")
    p.write("[invalid gibberish]")
    with pytest.raises(ImproperlyConfigured):
        Participants(str(p))
Example #16
0
def test_participants_alias_and_address(address_configuration_file, config_json):
    participants = Participants(str(address_configuration_file))
    alias, address = random.choice(list(config_json.items()))
    assert participants.alias(address) == alias
    assert participants.address(alias) == address