class UserAgent(Agent): def __init__(self, jid, password, data_endpoint, verify_security=False): super().__init__(jid, password, verify_security) self.dataEndpoint = data_endpoint self.logger = Logger("UserAgent") class UserBehav(OneShotBehaviour): def __init__(self, data_endpoint, logger): self.logger = logger self.dataEndpoint = data_endpoint super().__init__() async def on_end(self): pass async def run(self): self.logger.agent_run() threshold = Configuration.THRESHOLD knn_agents = Configuration.KNN_AGENTS data_agent = DataAgent(Endpoints.DAGENT, Endpoints.PASS, threshold, knn_agents) self.logger.agent_created("DataAgent") await data_agent.start() #data_agent.web.start(hostname="localhost", port="10001") validation_agent = ValidationAgent(Endpoints.VAGENT, Endpoints.PASS, Endpoints.UAGENT) self.logger.agent_created("ValidationAgent") await validation_agent.start() async def setup(self): self.logger.agent_started() behav = self.UserBehav(data_endpoint=self.dataEndpoint, logger=self.logger) self.add_behaviour(behav)
class ValidationAgent(Agent): def __init__(self, jid, password, user_endpoint, verify_security=False): self.userEndpoint = user_endpoint self.logger = Logger('ValidationAgent') super().__init__(jid, password, verify_security) class ListeningBehav(CyclicBehaviour): def __init__(self, user_endpoint, logger): self.userEndpoint = user_endpoint self.messageService = MessageService() self.logger = logger self.knnResponse = dict() self.results = [] self.labels = dict() self.query_count = None super().__init__() async def on_end(self): max(self.results, key=lambda knn: knn.weight) msg = self.messageService.create_message(self.userEndpoint, "inform", "content") await self.send(msg) await self.agent.stop() async def run(self): msg = await self.receive(timeout=1) if msg is not None: if msg.metadata[Tags.PHASE_TAG] == Tags.VALIDATE: knn_result = self.messageService.decode_message_to_dict( msg.body) self.logger.custom_message( f'**KNN{knn_result[4]}** with {knn_result[3]} data Predicted {knn_result[0]}' f' with weight: {knn_result[1]}' f' for Query id {msg.metadata["index"]} euclidean: {knn_result[2]}' ) if msg.metadata["index"] not in self.knnResponse.keys(): self.knnResponse[msg.metadata["index"]] = list() self.knnResponse[msg.metadata["index"]].append(knn_result) if msg.metadata[Tags.PHASE_TAG] == Tags.QUERYING: true_label = self.messageService.decode_message_to_dict( msg.body) self.logger.custom_message( f'Query id: {msg.metadata["index"]}; Real class: {true_label}' ) self.labels[msg.metadata["index"]] = true_label if msg.metadata[Tags.PHASE_TAG] == Tags.KILL: self.query_count = len(self.labels) if self.query_count is not None and self.query_count == len(self.knnResponse) and \ len(self.knnResponse[f'{self.query_count - 1}']) == len(self.knnResponse['0']): results, accuracy = self.count_results() self.logger.custom_message( f'Prediction {self.__get_results(results)}') self.logger.custom_message( f'Original {self.__get_results(self.labels.values())}' ) self.logger.custom_message(f'{"{:.2f}".format(accuracy)}%') def __get_results(self, labels): result = '' for i, label in enumerate(labels): result += f'Query{i}: {label} ' return result def count_results(self): classes = [] results = [] euclidean_distances = [] counter = 0 for key in self.knnResponse.keys(): for val in self.knnResponse[key]: classes.append(val[0]) euclidean_distances.append(val[2]) multiplier = [5, 3, 2] for i in range(3): index_of_min_value = euclidean_distances.index( min(euclidean_distances)) for _ in range(multiplier[i]): classes.append( self.knnResponse[key][index_of_min_value][0]) euclidean_distances[index_of_min_value] = max( euclidean_distances) + 1 try: results.append(mode(classes)) except: results.append(1) if results[-1] == self.labels[key]: counter += 1 classes = [] euclidean_distances = [] return results, counter / len(results) * 100 async def setup(self): self.logger.agent_started() print(f"ValidationAgent started at {datetime.datetime.now().time()}") behav = self.ListeningBehav(user_endpoint=self.userEndpoint, logger=self.logger) self.add_behaviour(behav)
class DataAgent(Agent): def __init__(self, jid, password, threshold, knn_agents_limit, verify_security=False): super().__init__(jid, password, verify_security) self.logger = Logger('DataAgent') self.knn_agents_limit = knn_agents_limit self.threshold = threshold class BiddingBehav(CyclicBehaviour): def __init__(self, threshold, knn_agents_limit, logger): super().__init__() self.data = None self.threshold_data = list() self.norm = dict() self.scaled_data_with_labels = None self.knn_agents = {} self.agent_count = 0 self.threshold = threshold self.knn_agents_limit = knn_agents_limit self.logger = logger self.messageService = MessageService() self.processed_data_index = 0 self.processed_knn_agent = 1 self.test_scaled_data = None self.test_scaled_data_with_labels = None self.processed_test_data_index = 0 def on_subscribe(self, jid): self.presence.approve(jid) self.presence.subscribe(jid) async def run(self): self.presence.on_subscribe = self.on_subscribe self.__get_data(Configuration.TRAIN_DATA) if self.processed_data_index < len(self.scaled_data_with_labels): await self.__split_dataset() else: await self.__send_train_data() if self.processed_test_data_index == len( self.test_scaled_data_with_labels): await self.on_end() async def on_end(self): msg = self.messageService.create_message_from_data_frame( Endpoints.VAGENT, 'Kill', '') await self.send(msg) await self.agent.stop() def __get_data_from_file(self, file_path): try: raw_data = pd.read_csv(file_path, sep=",") labels = raw_data[raw_data.columns[-1]] data = raw_data.iloc[:, :-1] return [raw_data, data, labels] except IOError as e: self.logger.custom_message(f'Cannot open file. {e}') def __get_data(self, file_path): raw_data, self.data, labels = self.__get_data_from_file(file_path) self.scaled_data_with_labels = self.__normalize_data(self.data) self.scaled_data_with_labels['quality'] = labels def __get_test_data(self, file_path): raw_data, data, labels = self.__get_data_from_file(file_path) self.test_scaled_data = self.__normalize_data(data) self.test_scaled_data_with_labels = self.test_scaled_data.copy() self.test_scaled_data_with_labels['quality'] = labels def __normalize_data(self, data): for columnName, columnData in data.iteritems(): if len(self.norm) is not len(self.data.columns): self.norm[columnName] = max(columnData) data[columnName] = data[columnName] / self.norm[columnName] return data async def __split_dataset(self): row = self.scaled_data_with_labels.iloc[self.processed_data_index] assigned = False if len(self.knn_agents) > 0: self.threshold_data.append( KnnService.get_euclidean_measure( self.knn_agents[self.processed_knn_agent][Tags.CENTER], row[:-1])) if KnnService.get_euclidean_measure(self.knn_agents[self.processed_knn_agent][Tags.CENTER], row[:-1]) < self.threshold\ or self.processed_knn_agent == self.knn_agents_limit: if self.processed_knn_agent == self.knn_agents_limit: self.processed_knn_agent = self.threshold_data.index( min(self.threshold_data)) + 1 await self.__send_row(self.processed_knn_agent, row) await self.__wait_for_center(self.processed_knn_agent) assigned = True if len(self.knn_agents ) == self.processed_knn_agent or assigned: self.processed_knn_agent = 1 self.threshold_data = list() else: self.processed_knn_agent += 1 return if not assigned: self.agent_count += 1 await self.__create_new_agent(self.agent_count, row) self.processed_data_index += 1 self.logger.progress_message(self.processed_data_index / len(self.scaled_data_with_labels)) async def __create_new_agent(self, number, row): agent = KnnAgent(f'knn{number}@localhost', Endpoints.PASS, number, Endpoints.DAGENT) await agent.start(auto_register=True) #agent.web.start(hostname="localhost", port="10000") self.logger.agent_created(f'Knn{number}Agent') if agent.is_alive(): await self.__send_row(number, row) self.knn_agents.setdefault(number, { "Agent": agent, Tags.CENTER: 0 }) await self.__wait_for_center(number) async def __wait_for_center(self, number): cc_response = await self.receive(timeout=5) if cc_response is None: return if cc_response.metadata[Tags.PHASE_TAG] == Tags.CENTER: self.knn_agents[number][ Tags.CENTER] = MessageService.decode_message_to_dict( cc_response.body) async def __send_row(self, agent_index, row): msg = self.messageService.create_message_from_data_frame( f'knn{agent_index}@localhost', Tags.BIDDING, row.to_json(), agent_index) await self.send(msg) async def __send_train_data(self): self.__get_test_data(Configuration.TEST_DATA) row = self.test_scaled_data.iloc[self.processed_test_data_index] for agent_index in range(self.agent_count): msg = self.messageService.create_message_from_data_frame( f'knn{agent_index + 1}@localhost', Tags.QUERYING, row.to_json(), agent_index) msg.set_metadata('index', f'{self.processed_test_data_index}') await self.send(msg) msg = self.messageService.create_message_from_data_frame( Endpoints.VAGENT, Tags.QUERYING, f'{self.test_scaled_data_with_labels.iloc[self.processed_test_data_index]["quality"]}' ) msg.set_metadata('index', f'{self.processed_test_data_index}') await self.send(msg) self.processed_test_data_index += 1 async def setup(self): b = self.BiddingBehav(threshold=self.threshold, logger=self.logger, knn_agents_limit=self.knn_agents_limit) self.add_behaviour(b) self.logger.agent_started()
class KnnAgent(Agent): def __init__(self, jid, password, number, creator_jid, verify_security=False): super().__init__(jid, password, verify_security) self.logger = Logger(f'Knn{number}Agent') self.number = number self.creatorJid = creator_jid class KnnBehav(CyclicBehaviour): def __init__(self, number, creator_jid, logger): super().__init__() self.number = number self.creatorJid = creator_jid self.data = pd.DataFrame() self.knnService = KnnService() self.messageService = MessageService() self.logger = logger async def run(self): msg = await self.receive(timeout=5) if msg is None: return if msg.body == Tags.DONE: self.logger.custom_message('Killed') await self.agent.stop() return if msg and msg.metadata[Tags.PHASE_TAG] == Tags.BIDDING: row = self.messageService.decode_message_to_dict( message_json=msg.body) self.knnService.add_data(row) cc = self.knnService.calculate_center(row) cc_response = self.messageService.create_message( self.creatorJid, Tags.CENTER, cc, self.number) await self.send(cc_response) return if msg and msg.metadata[Tags.PHASE_TAG] == Tags.QUERYING: row = self.messageService.decode_message_to_dict( message_json=msg.body) if len(self.knnService.data) >= 5: [label, weight] = self.knnService.knn(row) euclidean_distance = self.knnService.get_euclidean_measure( self.knnService.center, list(row.values())) q_response = self.messageService.create_message( Endpoints.VAGENT, Tags.VALIDATE, [ label, weight, euclidean_distance, len(self.knnService.data), self.number ]) q_response.set_metadata('index', msg.metadata['index']) self.logger.custom_message( f'Sufficient amount of data: {len(self.knnService.data)} - sending to validate' ) await self.send(q_response) else: self.logger.custom_message( f'Insufficient amount of data: {len(self.knnService.data)}' ) return def on_subscribe(self, jid): self.logger.agent_subscribe(jid) self.presence.approve(jid) self.presence.subscribe(jid) def on_subscribed(self, jid): self.logger.agent_subscribed(jid) async def setup(self): knn_behav = self.KnnBehav(self.number, self.creatorJid, self.logger) self.behav1 = knn_behav self.add_behaviour(knn_behav) self.logger.agent_started()