def start(args): """ Start the import and path calculation. """ # Set the start node start_node = Node((15, -4, 6)) dest_node = Node((0, 0, 0)) # End node is the center of the cube # Read the data from the csv file file_controller = FileController() logging.info('Importing data from %s...', args.import_path) links, nodes = file_controller.import_file(args.import_path, start_node, dest_node) logging.info('Successfully imported data from %s!', args.import_path) # Calculate the path a_star_controller = AStarController(links, nodes, start_node, dest_node) logging.info('Starting path search...') start_time = time.perf_counter() cheapest_path = a_star_controller.search_path() end_time = time.perf_counter() if cheapest_path: logging.info('Cheapest path successfully found in %.3f ms!' % ((end_time - start_time) * 1000)) if args.export_path: logging.info('Exporting result to: %s' % args.export_path) file_controller.export_file(args.export_path, cheapest_path) logging.info('Result successfully exported!') sys.exit(0) else: logging.fatal('Cheapest path could not be found.') sys.exit(1)
def test_SearchNotPossible_ShouldReturnFalse(self): ValidationUtility.set_up_test_method('impossible', Node((2, 0, 0)), Node((0, 0, 0))) result = ValidationUtility.a_star_controller.search_path() self.assertFalse(result)
def testDoubleAssignment(self): node1 = Node() node2 = Node() node1.set_data("BLAHBLAH") node2.set_data("ARRRRGHH") self.assertNotEquals(node1.get_data(),node2.get_data(), "Global variables don't cause issues.")
def test_DestroyWithBlaster_ShouldCostOne(self): ValidationUtility.set_up_test_method('destroy', Node((0, 0, 0)), Node((0, 0, 0))) expected = 1 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].g # get the final cost self.assertEqual(expected, actual)
def test_LadderDown_ShouldCostPointFive(self): ValidationUtility.set_up_test_method('simple_links', Node((0, 0, 1)), Node((0, 0, 0))) # cost 0.5 through ladder down # cost 1 to destroy expected = 1.5 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].g # get the final cost self.assertEqual(expected, actual)
def test_Door_ShouldCostTwo(self): ValidationUtility.set_up_test_method('simple_links', Node((1, 0, 0)), Node((0, 0, 0))) # cost 2 through door # cost 1 to destroy expected = 3 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].g # get the final cost self.assertEqual(expected, actual)
def test_BlastWall_ShouldCostThree(self): ValidationUtility.set_up_test_method('blasting', Node((1, 0, 0)), Node((0, 0, 0))) # cost 3 to blast through wall # cost 1 to destroy expected = 4 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].g # get the final cost self.assertEqual(expected, actual)
def test_UseEnergy_ShouldReduceEnergyCount(self): ValidationUtility.set_up_test_method('energy', Node((2, 0, 0)), Node((0, 0, 0)), energy=2) expected = 0 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].energy_units # get the final energy unit count self.assertEqual(expected, actual)
def test_Search_ShouldTakeCheaperPath(self): ValidationUtility.set_up_test_method('cheapest', Node((2, 0, 0)), Node((0, 0, 0))) # cheaper.csv has shortest path of cost 6 # cost 3 through open doors # cost 2 through closed door # cost 1 to destroy expected = 12 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].g # get the final cost self.assertEqual(expected, actual)
def test_RegenerationBlastWall_ShouldReduceRegenerationTimeByThree(self): ValidationUtility.set_up_test_method('regeneration_blasting', Node((2, 0, 0)), Node((0, 0, 0))) # regeneration time at 5 # blast wall takes 3 # destroy takes 1 expected = 1 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].regeneration_time # get the final cost self.assertEqual(expected, actual)
def test_RegenerationLadderUp_ShouldReduceRegenerationTimeByTwo(self): ValidationUtility.set_up_test_method('regeneration_ladder_up', Node((1, 0, -1)), Node((0, 0, 0))) # regeneration time at 5 # ladder up takes 2 # destroy takes 1 expected = 2 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].regeneration_time # get the final cost self.assertEqual(expected, actual)
def test_RegenerationOpen_ShouldReduceRegenerationTimeByOne(self): ValidationUtility.set_up_test_method('regeneration_open', Node((1, 1, 0)), Node((0, 0, 0))) # regeneration time at 5 # open takes 1 # destroy takes 1 expected = 3 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].regeneration_time # get the final cost self.assertEqual(expected, actual)
def test_EnergyCooldown_ShouldRegardCooldownOfFive(self): ValidationUtility.set_up_test_method('energy', Node((2, 0, 0)), Node((0, 0, 0))) # cost 3 through sentinel hallway # cost 5 for cooldown (wait) # cost 3 through sentinel hallway # cost 1 to destroy expected = 12 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].g # get the final cost self.assertEqual(expected, actual)
def test_UseBlaster_ShouldReduceBlasterCount(self): ValidationUtility.set_up_test_method('blasting', Node((1, 0, 0)), Node((0, 0, 0)), blaster=1) expected = 0 result = ValidationUtility.a_star_controller.search_path() actual = result[ len(result) - 1].tritanium_blaster # get the final tritanium blaster count self.assertEqual(expected, actual)
def test_LeastResistance_ShouldHaveTwelveEnergyUnits(self): ValidationUtility.set_up_test_method('least_resistance', Node( (3, 0, 0)), Node((0, 0, 0))) # least_resistance.csv has shortest path of cost 13 # path with least resistance is door (5x2) and open (1x1) # path of same length is sentinel(3)-wait(5)-sentinel(3) # energy_units should be unchanged because path of least resistance is taken expected = 12 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].energy_units # get the final cost self.assertEqual(expected, actual)
def import_file(self, import_path, start_node: Node, dest_node: Node): """ Read the csv file from the given import path. :param start_node: Start node of the graph. :param dest_node: Destination node of the graph. :param import_path: Path to the csv file. :return: Links and nodes from the csv file. """ # If the import path is not valid, exit if not self.is_path_valid(import_path): sys.exit(2) # Add the start and dest nodes to the nodes list self.nodes.append(start_node) self.nodes.append(dest_node) # Starting the import with open(import_path) as csv_file: # Iterate through each row reader = csv.reader(csv_file, delimiter=';') for i, row in enumerate(reader): if i == 0: continue # Get the nodes node1 = Node( (int(row[0] or '0'), int(row[1] or '0'), int(row[2] or '0'))) node2 = Node( (int(row[3] or '0'), int(row[4] or '0'), int(row[5] or '0'))) # Add the nodes, if they haven't been added yet found_node = next( (node for node in self.nodes if node1 == node), None) if found_node: node1 = found_node else: self.nodes.append(node1) found_node = next( (node for node in self.nodes if node2 == node), None) if found_node: node2 = found_node else: self.nodes.append(node2) # Add the link self.links.append( Link(node1, node2, int(row[6] or '0'), int(row[7] or '0'), int(row[8] or '0'), int(row[9] or '0'))) # Print the file if debug is enabled self.print_file() return self.links, self.nodes
def test_RegenerationLadderDown_ShouldReduceRegenerationTimeByPointFive( self): ValidationUtility.set_up_test_method('regeneration_ladder_down', Node((1, 0, 1)), Node((0, 0, 0))) # regeneration time at 5 # ladder down takes 0.5 # destroy takes 1 expected = 3.5 result = ValidationUtility.a_star_controller.search_path() actual = result[len(result) - 1].regeneration_time # get the final cost self.assertEqual(expected, actual)
def __init__(self, fw_code, set_of_coordinate_pairs, speed): self.nodes = [] self.bridges = [] self.locks = [] self.fw_code = fw_code if speed is None or math.isnan(speed) or speed == 0: speed = 13 self.speed = speed * 1000 / 60 GlobalVars.fairway_section_dict[self.fw_code] = self tmp = [] for coordinate_pairs in set_of_coordinate_pairs: for coordinates in coordinate_pairs: coordinates_tuple = (coordinates[0], coordinates[1]) if coordinates_tuple not in tmp: tmp.append(coordinates_tuple) for coordinates in tmp: lon = coordinates[0] lat = coordinates[1] x, y = lon, lat node = Node(x, y) GlobalVars.node_x_min = min(x, GlobalVars.node_x_min) GlobalVars.node_x_max = max(x, GlobalVars.node_x_max) GlobalVars.node_y_min = min(y, GlobalVars.node_y_min) GlobalVars.node_y_max = max(y, GlobalVars.node_y_max) self.nodes.append(node)
def init_nodes(self): ends = [] forks_before_lights = [] forward_right_lights = [] left_backward_lights = [] forks_after_lights = [] for i in range(4): dest = Node(i * 2, NodeType.basic) ends.append(dest) src = Node(i * 2 + 1, NodeType.basic) ends.append(src) for i in range(4): src_fork_before_lights = Node(i + 8, NodeType.fork) ends[i*2+1].add_edge(src_fork_before_lights, 1000) forks_before_lights.append(src_fork_before_lights) forward_right_light = Node(i + 12, NodeType.traffic_light) src_fork_before_lights.add_edge(forward_right_light, 50) left_backward_light = Node(i + 16, NodeType.traffic_light) src_fork_before_lights.add_edge(left_backward_light, 50) left_backward_lights.append(left_backward_light) forward_right_lights.append(forward_right_light) forward_right_fork = Node(i + 20, NodeType.fork) forward_right_light.add_edge(forward_right_fork, 50) forward_right_fork.add_edge(ends[(i*2 + 4) % len(ends)], 1000) forward_right_fork.add_edge(ends[(i*2 + 2) % len(ends)], 1000) left_backward_fork = Node(i + 24, NodeType.fork) left_backward_light.add_edge(left_backward_fork, 50) left_backward_fork.add_edge(ends[(i*2+6) % len(ends)], 1000) left_backward_fork.add_edge(ends[(i*2) % len(ends)], 1000) forks_after_lights.append(left_backward_fork) forks_after_lights.append(forward_right_fork) # start_node = Node(1, NodeType.basic) # # fork_node = Node(2, NodeType.fork) # start_node.add_edge(fork_node, 50) # # left_node = Node(3, NodeType.basic) # fork_node.add_edge(left_node, 50) # right_node = Node(4, NodeType.basic) # fork_node.add_edge(right_node, 50) return ends
def node_add(): if request.json: if ("node" in request.json) and ('name' not in request.json.get('node') or 'description' not in request.json.get('node')): return make_response(400, 6, "name and description json fields required") else: node_json = request.json.get('node') node_description = node_json['description'] node_name = node_json['name'] else: return make_response(400, 6, "Invalid request data") node = Node(name=node_name) node.ownerId = g.user.id node.description = node_description db_node = Node.query.filter(Node.name == node_name, Node.ownerId == g.user.id).first() if db_node: if request.method == 'PUT': node_remove(db_node.id) else: return make_response(409, 1, str("user " + g.user.username + ' already have node ' + node_name)) try: db.session.add(node) db.session.commit() except exc.SQLAlchemyError: return make_response(500, 2, "Database exception") return jsonify({'hypermedia': { 'self': { 'resource': str('/api/node/' + str(node.id)), 'method': 'GET' }, 'replace': { 'resource': str('/api/node/' + str(node.id)), 'method': 'PUT' }, 'delete': { 'resource': str('/api/node/delete/' + str(node.id)), 'method': 'DELETE' } }, 'message': 'Created.'}), 201
import numpy as np from model.Tetramino import Tetramino from model.Node import Node node_representation = np.array( [ [1, 1], [1, 1] ] ) initial_node = Node(node_representation) initial_node.next_node = initial_node class SquareTetramino(Tetramino): def __init__(self): super().__init__(initial_node)
def merge_nodes(mine: TscnFile, theirs: TscnFile, result: TscnFile, resolution: Callable[[str, Printable, Printable], Resolution]): # We start at the root node and work down the tree of each file # we tree to keep node order as is as far as possible. assert len(mine.nodes) > 0, "MINE file has no node. This is invalid." assert len(theirs.nodes) > 0, "THEIRS file has no node. This is invalid." # Now we need to partition up the nodes so we can do a comparison between them and start the merging partitions: list[NodePartition] = partition_nodes(mine.nodes, theirs.nodes) # Now we can walk the partitions and merge if necessary for partition in partitions: if partition.is_only_mine: # node exists only on my side, so we can just add it to the result for my_node, _ in partition.nodes: result.nodes.append(my_node) elif partition.is_only_theirs: # node exists only on their side, so we can just add it to the result for _, their_node in partition.nodes: result.nodes.append(their_node) else: # node exists on both sides and we need to merge it for my_node, their_node in partition.nodes: if not my_node.represents_same_thing(their_node): # If the two nodes represent different things, there is no way to merge them as the properties are # dependent on the type of the node and therefore merging properties of two different # types together just makes not any sense. Therefore in this case the only thing # we can do is ask which of the both nodes we would like to have. decision = resolution( "The same node has different types/scripts. " "This cannot be merged. Which node should I take?", my_node, their_node) if decision == Resolution.MINE: result.nodes.append(my_node) elif decision == Resolution.THEIRS: result.nodes.append(their_node) else: assert False, "Unexpected input." else: # The nodes represent the same thing. Now we can compare their properties and build a result node. result_node = Node(my_node.type, my_node.name, my_node.parent, my_node.instance, my_node.instance_placeholder) properties: DiffResult[tuple[str, Value]] = diff_bag_properties( my_node, their_node) # Stuff that is same in both nodes, goes to the result for (key, value), _ in properties.same: result_node.set_property(key, value) # Stuff that is in my node only, also goes into the result for key, value in properties.only_in_mine: result_node.set_property(key, value) # Stuff that is in their node only, also goes into the result for key, value in properties.only_in_theirs: result_node.set_property(key, value) # Stuff that is different in both needs to be decided upon for (key, my_value), (_, their_value) in properties.different: decision = resolution( f"Node {result_node.full_path_reference().to_string()} -> " f"Property \"{key}\" is different in both sides. " f"Which one should I take?", my_value, their_value) if decision == Resolution.MINE: result_node.set_property(key, my_value) elif decision == Resolution.THEIRS: result_node.set_property(key, their_value) else: assert False, "Unexpected input." result.nodes.append(result_node)
import numpy as np from model.Tetramino import Tetramino from model.Node import Node up_node_representation = np.array([[0, 1, 1], [1, 1, 0]]) down_node_representation = np.array([ [1, 0], [1, 1], [0, 1], ]) up_node = Node(up_node_representation) down_node = Node(down_node_representation) up_node.next_node = down_node down_node.next_node = up_node class STetramino(Tetramino): def __init__(self): super().__init__(up_node)
def testAssignment(self): node = Node() node.set_data("BLARGH") self.assertEquals(node.get_data(), "BLARGH","Assignment worked.")
def read_file(): # Get inputfile from command line inputfile = '' try: opts, args = getopt.getopt(sys.argv[1:], 'i:', ['ifile=']) except getopt.GetoptError: print('You need to pass at least one argument:') print('__main__.py -i <inputfile>') sys.exit(2) for opt, arg in opts: if opt in ("-i", "--ifile"): inputfile = arg if len(sys.argv) < 3: print('You need to pass at least one argument:') print('__main__.py -i <inputfile>') sys.exit(2) # Read file with open( os.path.join(os.path.dirname(os.path.realpath(__file__)), inputfile), 'r') as file: nodes = [] links = [] counter = 0 print('Input:') for line in file: counter += 1 # Check if the maximum number of items has been reached if counter > MAX_ITEMS: break # Check if line is node result = re.search( '^\\s*([a-zA-Z][a-zA-Z0-9]*)\\s?=\\s?([0-9]*);.*', line) if result: # Check if name exceeds max length if len(result.group(1)) > MAX_IDENT: continue # Check if node id exceeds max number if int(result.group(2)) > MAX_NODE_ID: continue # Check if name is root (reserved) if result.group(1) is 'Root': continue nodes.append(Node(int(result.group(2)), result.group(1))) print(nodes[-1].name, ':', nodes[-1].node_id) continue # Check if line is link result = re.search( '^\\s*([a-zA-Z][a-zA-Z0-9]*)\\s?-\\s?([a-zA-Z][a-zA-Z0-9]*)\\s?:\\s?([0-9]*);.*', line) if result: # Check if name exceeds max length if len(result.group(1)) > MAX_IDENT or len( result.group(2)) > MAX_IDENT: continue # Check if link cost exceeds max cost if int(result.group(3)) > MAX_COST: continue # Check if name is root (reserved) if result.group(1) is 'Root' or result.group(2) is 'Root': continue links.append( Link(result.group(1), result.group(2), int(result.group(3)))) print(links[-1].node_id_1, '-', links[-1].node_id_2, ':', links[-1].cost) continue # Check if line is comment result = re.search('//.*', line) if result: continue # Check if line is empty result = re.search('^\\s*$', line) if result: continue print('Error in line (', counter, '): ', line) return Graph(nodes, links)
from model.Tetramino import Tetramino from model.Node import Node up_node_representation = np.array([[0, 0, 1], [1, 1, 1]]) right_node_representation = np.array([ [1, 0], [1, 0], [1, 1], ]) down_node_representation = np.array([[1, 1, 1], [1, 0, 0]]) left_node_representation = np.array([[1, 1], [0, 1], [0, 1]]) up_node = Node(up_node_representation) right_node = Node(right_node_representation) down_node = Node(down_node_representation) left_node = Node(left_node_representation) up_node.next_node = right_node right_node.next_node = down_node down_node.next_node = left_node left_node.next_node = up_node class LRightTetramino(Tetramino): def __init__(self): super().__init__(up_node)