Пример #1
0
def test_between_graphs_edges():
    b0 = Wire("b0")
    b1 = Wire("b1")
    b2 = Wire("b2")
    b3 = Wire("b3")
    v0 = Node("v0", 0.0, "X", 3)
    v1 = Node("v1", 0.0, "X", 3)
    v2 = Node("v2", 0.0, arity=3)
    v3 = Node("v3", 0.0, arity=3)
    e0 = Edge("e0", v0, v3)
    e1 = Edge("e1", v1, v2)
    e2 = Edge("e2", v2, v0)
    e3 = Edge("e3", v1, v3)
    e4 = Edge("e4", v0, b1)
    e5 = Edge("e5", v2, b0)
    e7 = Edge("e7", v1, b2)
    e8 = Edge("e8", v3, b3)
    inputs = [b1, b2]
    outputs = [b0, b3]
    nodes = [v3, v1, v0, v2]
    edges = [e3, e5, e0, e4, e2, e8, e1, e7]
    graph = Graph(nodes, edges, inputs, outputs)
    g1 = Graph([v0], [e4], [b1])
    g2 = Graph([v3, v1, v2], [e2, e0, e1, e3, e7, e8, e5], [b2], [b0, b3])
    result = qf.between_graphs_edges(g1, g2, graph)
    expected_result = [e2, e0]
    assert set(result) - set(expected_result) == set()
Пример #2
0
 def test_size_3_graph(self):
     graph = Graph(3)
     graph.add_edge(0,1)
     graph.add_edge(1,2)
     colors = Heurstics.color_graph(graph)
     self.assertEqual(3, len(colors))
     self.assertEqual(2,len(set(colors.values())))
Пример #3
0
def test_connected_graphs_split():

    #  a  b  c
    #  |  |  |
    # n0 n1 n2    g
    #  |\/|\/|    |
    #  |/\|/\|    h
    # n3 n4 n5
    #  |  |  |
    #  d  e  f
    #
    # problem if an edge has the same name as a node

    a, b, c, d, e, f = Wire('a'), Wire('b'), Wire('c'), Wire('d'), Wire(
        'e'), Wire('f')
    g, h = Wire('g'), Wire('h')
    n0, n1, n2, n3, n4, n5 = Node('n0'), Node('n1'), Node('n2'), Node(
        'n3'), Node('n4'), Node('n5')
    e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 = \
        Edge('e0', a, n0), Edge('e1', b, n1), Edge('e2', c, n2), \
        Edge('e3', n0, n3), Edge('e4', n0, n4), \
        Edge('e5', n1, n3), Edge('e6', n1, n4), Edge('e7', n1, n5), \
        Edge('e8', n2, n4), Edge('e9', n2, n5), \
        Edge('e10', d, n3), Edge('e11', e, n4), Edge('e12', f, n5), \
        Edge('e13', n0, n0)
    e14 = Edge('e14', g, h)
    inputs = [a, b, c, g]
    outputs = [d, e, f, h]
    nodes = [n0, n1, n2, n3, n4, n5]
    edges = [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14]
    graph = Graph(nodes, edges, inputs, outputs)
    small_graph = Graph(inputs=[g], outputs=[h], edges=[e14])
    g1, g2 = qf.connected_graphs_split(graph)
    assert g1 == small_graph or g2 == small_graph
Пример #4
0
 def test_size_3_graph(self):
     graph = Graph(3)
     graph.add_edge(0, 1)
     graph.add_edge(1, 2)
     colors = Heurstics.color_graph(graph)
     self.assertEqual(3, len(colors))
     self.assertEqual(2, len(set(colors.values())))
Пример #5
0
def test_graph_subtraction():

    #  a  b  c
    #  |  |  |
    # n0 n1 n2
    #  |\/|\/|
    #  |/\|/\|
    # n3 n4 n5
    #  |  |  |
    #  d  e  f

    a, b, c, d, e, f = Wire('a'), Wire('b'), Wire('c'), Wire('d'), Wire(
        'e'), Wire('f')
    n0, n1, n2, n3, n4, n5 = Node('0'), Node('1'), Node('2'), Node('3'), Node(
        '4'), Node('5')
    e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12 = \
        Edge('0', a, n0), Edge('1', b, n1), Edge('2', c, n2), \
        Edge('3', n0, n3), Edge('4', n0, n4), \
        Edge('5', n1, n3), Edge('6', n1, n4), Edge('7', n1, n5), \
        Edge('8', n2, n4), Edge('9', n2, n5), \
        Edge('10', d, n3), Edge('11', e, n4), Edge('12', f, n5)
    inputs = [a, b, c]
    outputs = [d, e, f]
    nodes = [n0, n1, n2, n3, n4, n5]
    edges = [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12]
    graph = Graph(nodes, edges, inputs, outputs)
    inputs_graph = Graph(inputs=inputs)
    assert graph - inputs_graph == Graph(nodes, edges, [], outputs)
Пример #6
0
 def build_polygons_graph(polygons, sorted_points, p_to_c = None, cnum = None):
     opened = set()
     graph = Graph.Graph(len(polygons))
     if not p_to_c is None:
         cgraph = Graph.Graph(cnum)
     for p in sorted_points:
         if abs(p.x + 8.204722) < Builder.EPS:
             print 'I found it'
         if p.is_first:
             if not p.pid in opened:
                 opened.add(p.pid)
         for pid in opened:
             if graph.is_adjacent_vertices(p.pid, pid):
                 continue
             if pid == p.pid:
                 continue
             assert polygons[pid].id == pid
             if polygons[pid].min_y <= p.y <= polygons[pid].max_y\
                     and polygons[pid].min_x <= p.x <= polygons[pid].max_x:
                 if not p_to_c is None:
                     if p_to_c[pid] == p_to_c[p.pid] or cgraph.is_adjacent_vertices(p_to_c[pid], p_to_c[p.pid]):
                         continue
                 if Builder.check_in(p, polygons[pid]):
                     graph.add_edge(p.pid, pid)
                     graph.add_edge(pid, p.pid)
                     cgraph.add_edge(p_to_c[p.pid], p_to_c[pid])
                     cgraph.add_edge(p_to_c[pid], p_to_c[p.pid])
         if p.is_last:
             #assert p.pid in opened
             opened.remove(p.pid)
     if not p_to_c is None:
         return cgraph
     return graph
Пример #7
0
def connected_graphs_split(graph: Graph) -> (Graph, Graph):
    """ If possible, splits a graph in two separate graphs, the first one has to be connected.

    Args:
        graph (Graph): graph to be split in two

    Returns:
        (Graph, Graph): a connected graph and the rest of the edges, nodes and so on ...
    """
    # possible improvement, return balanced graphs
    if graph.nodes:
        increasing_graph = Graph(nodes=[graph.nodes[0]])
        # the potential loops must be included
        edges = [
            edge for edge in graph.edges
            if edge.n1 == graph.nodes[0] and edge.n2 == graph.nodes[0]
        ]
        increasing_graph.edges = edges
    elif graph.inputs:
        increasing_graph = Graph(inputs=[graph.inputs[0]])
    elif graph.outputs:
        increasing_graph = Graph(outputs=[graph.outputs[0]])
    else:
        # graph empty
        return Graph([], [], [], []), deepcopy(graph)
    while increasing_graph.augment(graph):
        pass
    leftover = graph - increasing_graph
    return increasing_graph, leftover
Пример #8
0
    def test_square_graph(self):
        graph = Graph(4)
        graph.add_edge(0,1)
        graph.add_edge(1,2)
        graph.add_edge(2,3)
        graph.add_edge(3,0)

        colors = Heurstics.color_graph(graph)

        self.assertEqual(4, len(colors))
        self.assertEqual(2, len(set(colors.values())))
Пример #9
0
def augment_dataset(train_triples,
                    dev_triples,
                    add_paths=False,
                    max_path_length=8):

    train_graph = Graph(train_triples)
    full_graph = Graph(train_triples + dev_triples)

    # start with original edges in the training and dev set
    train = PathQuery.from_triples(train_triples)
    dev = PathQuery.from_triples(dev_triples)
    test = []  # empty for now

    if add_paths:
        print 'adding paths'
        # number of paths to augment existing triples with
        num_augment = lambda triples: len(triples) * (max_path_length - 1)

        # augment with paths
        train.extend(
            sample_paths(train_graph, 3 * num_augment(train_triples),
                         max_path_length))  # previously 980000
        dev.extend(
            sample_paths(full_graph, num_augment(dev_triples),
                         max_path_length))  # previously 35000

    # make unique, and eliminate train dev overlap
    print 'before: train {}, dev {}'.format(len(train), len(dev))
    train, dev = set(train), set(dev)
    dev -= train

    # remove trivial queries (queries that type match all entities)
    trivial_train_paths = set(get_trivial_path_queries(train_graph, train))
    trivial_dev_paths = set(get_trivial_path_queries(train_graph, dev))

    train -= trivial_train_paths
    dev -= trivial_dev_paths

    train, dev = list(train), list(dev)
    random.shuffle(train)
    random.shuffle(dev)

    print 'after: train {}, dev {}'.format(len(train), len(dev))

    if platform.system() != 'Darwin':
        # save generated datasets
        print 'saving datasets'
        dsets = {'train': train, 'dev': dev, 'test': test}
        for name, dset in dsets.iteritems():
            with open('{}.cpkl'.format(name), 'w') as f:
                pickle.dump(dset, f)
        print 'done'

    return train, dev, test, train_graph, full_graph
Пример #10
0
    def test_full_4_graph(self):
        graph = Graph(4)
        graph.add_edge(0, 1)
        graph.add_edge(0, 2)
        graph.add_edge(0, 3)

        graph.add_edge(1, 2)
        graph.add_edge(1, 3)

        graph.add_edge(2, 3)

        colors = Heurstics.color_graph(graph)

        self.assertEqual(4, len(colors))
        self.assertEqual(4, len(set(colors.values())))
Пример #11
0
    def test_size_10_graph(self):
        graph = Graph(10)

        self.add_rays(graph)

        colors_1 = self.heuristics.color_graph(graph)
        colors_2 = self.exact.get_colors_by_graph(graph)

        self.assertEqual(10, len(colors_1))
        self.assertEqual(2, len(set(colors_1.values())))

        self.assertEqual(10, len(colors_2))
        self.assertEqual(2, len(set(colors_2)))

        self.add_circuit(graph)

        self.exact = Exact({})
        colors_1 = self.heuristics.color_graph(graph)
        colors_2 = self.exact.get_colors_by_graph(graph)

        self.assertEqual(10, len(colors_1))
        self.assertEqual(3, len(set(colors_1.values())))

        self.assertEqual(10, len(colors_2))
        self.assertEqual(3, len(set(colors_2)))
Пример #12
0
def filter_edges_inputs_outputs_by_nodes_negative(
        nodes: List[Node], containing_graph: Graph) -> Graph:
    """

    Since the node list is split in two, many edges and wires don't need to be considered for the next iteration of
    each half. Thus, the edges, inputs and outputs are filtered so they are not passed to the next iteration if they are
    in relation with the given nodes from the other half

    Args:
        nodes (List[Node]): nodes to apply the filter from
        containing_graph (Graph): graph to be filtered

    Returns:
        Graph: graph containing the edges, inputs and outputs without the members in relation with the given nodes
    """
    new_edges = containing_graph.edges[:]
    new_inputs = containing_graph.inputs[:]
    new_outputs = containing_graph.outputs[:]
    for edge in containing_graph.edges:
        if set(edge).intersection(
                nodes):  # edge doesn't contain any node from the list
            new_edges.remove(edge)
            if set(edge).intersection(containing_graph.inputs):
                new_inputs.remove(
                    list(set(edge).intersection(containing_graph.inputs))[0])
            if Wire(edge.name) in containing_graph.inputs:
                new_inputs.remove(Wire(edge.name))
            if set(edge).intersection(containing_graph.outputs):
                new_outputs.remove(
                    list(set(edge).intersection(containing_graph.outputs))[0])
            if Wire(edge.name) in containing_graph.outputs:
                new_outputs.remove(Wire(edge.name))
    return Graph(edges=new_edges, inputs=new_inputs, outputs=new_outputs)
Пример #13
0
def test_split_and_reunite():
    b0 = Wire("b0")
    b1 = Wire("b1")
    b2 = Wire("b2")
    b3 = Wire("b3")
    v0 = Node("v0", 0.0, "X", 3)
    v1 = Node("v1", 0.0, "X", 3)
    v2 = Node("v2", 0.0, arity=3)
    v3 = Node("v3", 0.0, arity=3)
    e0 = Edge("e0", v0, v3)
    e1 = Edge("e1", v1, v2)
    e2 = Edge("e2", v2, v0)
    e3 = Edge("e3", v1, v3)
    e4 = Edge("e4", v0, b1)
    e5 = Edge("e5", v2, b0)
    e7 = Edge("e7", v1, b2)
    e8 = Edge("e8", v3, b3)
    inputs = [b1, b2]
    outputs = [b0, b3]
    nodes = [v3, v1, v0, v2]
    edges = [e3, e5, e0, e4, e2, e8, e1, e7]
    graph = Graph(nodes, edges, inputs, outputs)
    m1 = [[32, 0, 0, 0], [0, 0, 0, 32], [0, 0, 0, 32], [32, 0, 0, 0]]
    m2 = np.zeros((4, 4))
    m3 = np.zeros((4, 4))
    m4 = np.zeros((4, 4))
    expected_result = Pi4Matrix(m1, m2, m3, m4, 6)
    assert not (qf.split_and_reunite(graph) - expected_result).any()
Пример #14
0
 def test_simple_case(self):
     graph = Graph.Graph(2)
     graph.add_edge(0,1)
     colors = self.exact.get_colors_by_graph(graph)
     self.assertEqual(2,len(colors))
     self.assertEqual(0,colors[0])
     self.assertEqual(1,colors[1])
Пример #15
0
def test_graph_bool_true():
    # assert g doesn't call bool(), hence the weird code with the if

    g = Graph([Node('n')])

    if g:
        assert True
    else:
        assert False
Пример #16
0
def test_matrix_linker():
    v0 = Node("v0", arity=2, node_type="hadamard")
    v3 = Node("v3", arity=2, node_type="hadamard")
    v5 = Node("v5", angle=1.0, arity=3, node_type="X")
    we5 = Wire("e5")
    we6 = Wire("e6")
    e5 = Edge("e5", v5, v0)
    e6 = Edge("e6", v0, v3)
    graph1 = Graph([v0], [e5, e6], [we5], [we6])
    we8 = Wire("e8")
    v8 = Node("v8", 0.5, arity=4)
    e8 = Edge("e8", v8, v3)
    graph2 = Graph([v3], [e8, e6], [we8, we6], [])
    result = qf.matrix_linker(graph1, graph2)
    p1 = ConnectionPoint(False, True)
    p2 = ConnectionPoint(True, False, 1)
    expected_result = [InterMatrixLink(p1, p2)]
    assert result == expected_result
Пример #17
0
 def test_3_case(self):
     graph = Graph.Graph(3)
     graph.add_edge(0,1)
     graph.add_edge(1,2)
     colors = self.exact.get_colors_by_graph(graph)
     self.assertEqual(3,len(colors))
     self.assertEqual(0,colors[0])
     self.assertEqual(1,colors[1])
     self.assertEqual(0,colors[2])
Пример #18
0
 def reset(self):
     self.clear()
     self.nodePrompt = None
     self.data = Graph()
     self.graph = GraphItem()
     self.addItem(self.graph)
     self.graph.setRect(self.sceneRect())
     self.counter = 0
     self.edges_matrix = defaultdict(lambda: defaultdict(list))
     self.edges = {}
     self.moving_edges = []
     self.selected_node = None
Пример #19
0
def test_graph_augmentation():

    #  a  b  c
    #  |  |  |
    # n0 n1 n2
    #  |\/|\/|
    #  |/\|/\|
    # n3 n4 n5
    #  |  |  |
    #  d  e  f

    a, b, c, d, e, f = Wire('a'), Wire('b'), Wire('c'), Wire('d'), Wire(
        'e'), Wire('f')
    n0, n1, n2, n3, n4, n5 = Node('0'), Node('1'), Node('2'), Node('3'), Node(
        '4'), Node('5')
    e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13 = \
        Edge('0', a, n0), Edge('1', b, n1), Edge('2', c, n2), \
        Edge('3', n0, n3), Edge('4', n0, n4), \
        Edge('5', n1, n3), Edge('6', n1, n4), Edge('7', n1, n5), \
        Edge('8', n2, n4), Edge('9', n2, n5), \
        Edge('10', d, n3), Edge('11', e, n4), Edge('12', f, n5), \
        Edge('13', n0, n0)
    inputs = [a, b, c]
    outputs = [d, e, f]
    nodes = [n0, n1, n2, n3, n4, n5]
    edges = [e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13]
    graph = Graph(nodes, edges, inputs, outputs)
    inputs_graph = Graph(inputs=inputs, nodes=[n0], edges=[e0, e13])
    inputs_graph.augment(graph)
    expected_result = Graph([n0, n1, n2, n3, n4],
                            [e0, e1, e2, e3, e4, e5, e6, e8, e13], inputs, [])
    assert inputs_graph == expected_result
Пример #20
0
    def test_square_case(self):
        graph = Graph.Graph(4)
        graph.add_edge(0,1)
        graph.add_edge(1,2)
        graph.add_edge(2,3)
        graph.add_edge(0,3)

        colors = self.exact.get_colors_by_graph(graph)

        self.assertEqual(4,len(colors))
        self.assertEqual(0,colors[0])
        self.assertEqual(1,colors[1])
        self.assertEqual(0,colors[2])
        self.assertEqual(1,colors[3])
Пример #21
0
    def test_size_300_graph(self):
        graph = Graph(300)

        self.add_rays(graph)

        colors = self.heuristics.color_graph(graph)

        self.assertEqual(300, len(colors))
        self.assertEqual(2, len(set(colors.values())))

        self.add_circuit(graph)

        colors = self.heuristics.color_graph(graph)
        self.assertEqual(300, len(colors))
        self.assertEqual(3, len(set(colors.values())))
Пример #22
0
    def deserialize(self, data: str) -> None:
        obj = self.str_to_obj(data)
        self._assert(isinstance(obj, dict), 'Json must be an object')
        nodes_list = obj.get('nodes') or []
        self._assert(isinstance(nodes_list, list), 'Nodes must be an array')
        edges_list = obj.get('edges') or []
        self._assert(isinstance(edges_list, list), 'Edges must be an array')
        results_list = obj.get('results') or []
        self._assert(isinstance(results_list, list),
                     'Results must be an array')

        self.data = Graph()
        for node_obj in nodes_list:
            node = self.deserialize_node(node_obj)
            self.data.nodes[node.id] = node

        for edge_obj in edges_list:
            edge = self.deserialize_edge(edge_obj)
            self.data.edges[edge.id] = edge

        for result in results_list:
            self.data.results.append(self.deserialize_result(result))
Пример #23
0
    def test_size_25(self):
        graph = Graph(25)

        self.add_rays(graph)

        colors_1 = self.heuristics.color_graph(graph)
        #why toooo long
        #colors_2 = self.exact.get_colors_by_graph(graph)

        self.assertEqual(25, len(colors_1))
        self.assertEqual(2, len(set(colors_1.values())))

        #self.assertEqual(25, len(colors_2))
        #self.assertEqual(3, len(set(colors_2)))

        self.add_circuit(graph)

        colors_1 = self.heuristics.color_graph(graph)
        #why toooo long
        #colors_2 = self.exact.get_colors_by_graph(graph)

        self.assertEqual(25, len(colors_1))
        self.assertEqual(3, len(set(colors_1.values())))
Пример #24
0
def main(diagram_file_path: str, inputs: List[str], outputs: List[str]) -> (bool, List[str], List[str], GenericMatrix):
    """main(diagram_file_path: str, inputs: List[str], outputs: List[str]) -> bool, List[str], List[str], GenericMatrix

    Computes the diagram matrix from the diagram given, the diagram inputs are precises separately (once integrated
    in Quantomatic, the inputs are asked to the user via a dialogue box)

    Args:
        diagram_file_path (path): Path the de diagram data file (extension : .qgraph, format : json)
        inputs (list[string]): Ordered list of inputs taken for this matrix calculation.
        outputs (list[string]): Ordered list of outputs taken for this matrix calculation.
    Returns:
         matrix: The matrix corresponding to the given diagram
    """
    wne_dir = load_dictionaries(diagram_file_path)
    wires, nodes, edges = dictionary_to_data(*wne_dir)  # the star is used to expand the tuple (unpack the argument)

    assumed_order, inputs, outputs = manage_i_o(wires, edges, inputs, outputs)

    start_wires = i_o_to_data(inputs, wires)
    end_wires = i_o_to_data(outputs, wires)

    m = qf.split_and_reunite(Graph(nodes, edges, start_wires, end_wires))
    return assumed_order, inputs, outputs, m
Пример #25
0
def test_graph_bool_false():

    g = Graph()

    assert not g
Пример #26
0
 def new(self):
     self.opened = True
     self.data = Graph()
     return self.opened
Пример #27
0
def split_and_reunite(graph: Graph) -> GenericMatrix:
    """Recursive function taking in a graph and returning the corresponding matrix.

    To do so, split the graph in two, passes the two halves to it's next iteration and reunite the two matrix obtained
    using the :ref:`fusion_matrices <fusion_matrices>` method from :ref:`divide_conquer`.

    The main part of this function is converting the graph format to the matrix format. tmp

    Args:
        graph (Graph): diagram considered

    Returns:
        GenericMatrix: matrix corresponding to the given diagram
    """
    if len(graph.nodes) == 0:
        return no_node_matrix(graph.edges, graph.inputs, graph.outputs)
    elif len(graph.nodes) == 1 and not no_node_edges_detection(graph.edges):
        try:
            return UsedFragment.node_to_matrix(graph.nodes[0],
                                               len(graph.inputs),
                                               len(graph.outputs))
        except AttributeError:
            return fallback_node_to_matrix(graph.nodes[0], len(graph.inputs),
                                           len(graph.outputs))
    else:
        graph1, graph2 = connected_graphs_split(graph)
        if not graph2:
            # we rewrite graph1 and graph2 so they contain two parts of the current graph1
            if no_node_edges_detection(graph.edges):
                # probably dead code since if a graph has such an edge (containing no node, only I/O), and has nodes,
                # the connected_graphs_split function would return two distinct graphs
                #
                # degenerate cases, when a graph contains only wires
                # in this case, graph1 will contain the I/O connected to another I/O and graph2 will contain the rest
                graph2 = Graph(nodes=graph.nodes)

                graph2 += filter_edges_inputs_outputs_by_nodes(
                    graph2.nodes, graph)
                graph1 = graph - graph2
            else:
                if graph.inputs:
                    graph1 = Graph(inputs=[graph.inputs[0]])
                    graph1.augment(graph)
                elif graph.nodes:
                    graph1 = Graph(nodes=[graph.nodes[0]])
                else:
                    raise RuntimeError(
                        'A graph with no node shouldn\'t enter in this branch')

                graph1 += graph1.neighbouring_i_o(graph)
                graph2 = graph - graph1

                in_between_edges = between_graphs_edges(graph1, graph2, graph)

                graph1.edges += in_between_edges

                in_between_wires = []
                for edge in in_between_edges:
                    in_between_wires.append(Wire(edge.name))

                graph1.outputs += in_between_wires
                graph2.inputs += in_between_wires

            first_half_matrix = split_and_reunite(graph1)
            second_half_matrix = split_and_reunite(graph2)

            inter_matrix_link = matrix_linker(graph1, graph2)
        else:
            first_half_matrix = split_and_reunite(graph1)
            second_half_matrix = split_and_reunite(graph2)
            inter_matrix_link = []

        input_connections = wires_to_connection_point_node_sorted(
            graph.inputs, graph.edges, graph1.nodes, graph2.nodes, False)
        output_connections = wires_to_connection_point_node_sorted(
            graph.outputs, graph.edges, graph1.nodes, graph2.nodes, True)

        return divide_conquer.fusion_matrices(first_half_matrix,
                                              second_half_matrix,
                                              input_connections,
                                              output_connections,
                                              inter_matrix_link)
Пример #28
0
from data import Graph, Vertex, ChainingHashTable
from datetime import time, timedelta
import datetime
from algorithim import algo2
from input import readPackages, readLocations

truck1 = Truck()
truck2 = Truck()
hashTable = ChainingHashTable()

milesList = [0]

readPackages('packages.csv', hashTable)

#construct a graph object
graph = Graph()

readLocations(graph)

#list of predefined truck package ids.
truck1LoadList = [14, 15, 16, 34, 20, 29, 1, 40, 31, 13, 37, 30]
truck2LoadList = [21, 28, 2, 10, 38, 3, 8, 32, 6, 36, 12, 18, 23, 25]
truck1LoadList2 = [19, 4, 33, 7, 5, 9, 39, 27, 35, 17, 24, 26, 22, 11]

#truck 1's first load
#O(N)
for packageID in truck1LoadList:

    truck1.loadPackage(hashTable.search(packageID))
#O(N)
#truck 2's first load