def test_determine_colour(self):
     """ Ensure colours are returned with the relevant values. """
     gui = Visualizer(None)
     assert gui._determine_colour(0) == 'red'
     assert gui._determine_colour(1) == 'green'
     assert gui._determine_colour(2) == 'cyan'
     assert gui._determine_colour(3) == 'blue'
     assert gui._determine_colour(500) == 'blue'
Пример #2
0
 def start(self):
     """ Begins gui. """
     self.__root = Tk()
     self._gui = Visualizer(self.__root)
     self._gui.subscribe(self)  # Register to gui
     self.subscribe(self._gui)  # Register gui to this
     self.__root.protocol("WM_DELETE_WINDOW", self._gui_close)
     self.__root.mainloop()
 def test_validate_input(self):
     """ Tests the validation of input. """
     gui = Visualizer(None)
     gui._builder.get_object = Mock()
     returnable = Mock()
     returnable.get = Mock()
     
     returnable.get.return_value = "Not valid" # Check error raised when invalid value is given
     gui._builder.get_object.return_value = returnable
     try:
         gui._validate_input()
         assert False
     except Exception:
         assert True
    def test_notifying_observers(self):
        """ Ensures the norifying of observers happens with the correct argument. """
        gui = Visualizer(None)

        observer = Mock()   # Setup with a fake observer
        observer.update = Mock()
        gui._observers = [observer]

        gui._builder.get_object = Mock()    # Setup fake values
        returnable = Mock()
        returnable.get = Mock()

        returnable.get.return_value = "999"   # Look for 999
        gui._builder.get_object.return_value = returnable
        gui._notify_observers()

        observer.update.assert_called_with({"method": "999", "clique_size": 999, "graph_size": 999})
    def test_draw_graph(self, det_col):
        """ Ensures a graph is drawn with the corredct items. """
        gui = Visualizer(None)
        fake_canvas = Mock()
        fake_canvas.create_oval = Mock()
        fake_canvas.create_line = Mock()
        fake_canvas.winfo_width = Mock(return_value=5)
        fake_canvas.winfo_height = Mock(return_value=5)
        gui._builder = Mock()
        gui._builder.get_object = Mock()
        gui._builder.get_object.return_value = fake_canvas

        # Test vertice drawing
        g = Graph() # Setup graph
        vertex_one = Vertex(0)
        g.add_vertex(vertex_one)
        g.add_vertex(Vertex(1))
        g.add_vertex(Vertex(2))
        gui._draw_graph(g)  # Try drawing
        assert fake_canvas.create_oval.call_count == 3

        # Test edge drawing
        edge = Edge(0, vertex_one, vertex_one, colour=5)   # Setup (Continued from above)
        g.add_edge(edge)
        gui._draw_graph(g)   # Try drawing
        det_col.assert_called_with(5)
        assert fake_canvas.create_line.call_count == 1
    def test_init(self, builder_mock, handlers_mock, obs_mck, sub_mck):
        """ Tests the initialisation of the gui. """
        builder_mock.add_from_file = Mock()
        builder_mock.get_object = Mock()

        gui = Visualizer(None)  # Do the thing
        sub_mck.assert_called_with(gui)         # Ensure parent constructors are called.
        obs_mck.assert_called_with(gui)
        assert builder_mock.call_count == 1     # Ensure builder has been created.
        assert handlers_mock.call_count == 1    # Ensure event handlers have been added.
    def test_update(self, thrd):
        """ Ensures the view updates if a graph is provided. """
        gui = Visualizer(None)
        args = {"graph": "GRAPH", "generation": "gen", "evals": "evals", "best_fitness": 0.999, "finished": "fin", "history": {"fitness": [1], "evaluation": [1]}}   # Try with a graph
        gui.update(args)
        assert thrd.call_count == 1

        args = {}   # Try without a graph
        gui.update(args)
        assert thrd.call_count == 1   # (Continuing from previous test)
    def test_btn_solve(self, validate_mock, notify_mock):
        """ Ensure action checks validation before notifying observers. """
        gui = Visualizer(None)

        validate_mock.return_value = True   # Try with valid input
        gui._btn_solve_press()
        assert notify_mock.call_count == 1

        validate_mock.return_value = False   # Try with invalid input
        gui._btn_solve_press()
        assert notify_mock.call_count == 1  # (Last test added one)
Пример #9
0
class Simulator(Subject, Observer):
    """ A simulator to process party problems. """
    def __init__(self):
        """ Initializes a user interface and sets up callbacks. """
        Subject.__init__(self)
        Observer.__init__(self)
        self._graph = None
        self._method = None
        self._algo_thread = None
        self._poll_thread = None
        self._gui = None

    def start(self):
        """ Begins gui. """
        self.__root = Tk()
        self._gui = Visualizer(self.__root)
        self._gui.subscribe(self)  # Register to gui
        self.subscribe(self._gui)  # Register gui to this
        self.__root.protocol("WM_DELETE_WINDOW", self._gui_close)
        self.__root.mainloop()

    def _gui_close(self):
        """ The gui has been closed, cut threads. """
        self._method._set_finished_flag(True)
        if self._algo_thread is not None: self._algo_thread.join()
        if self._poll_thread is not None: self._poll_thread.join()
        self.__root.destroy()
        raise SystemExit

    def _solve(self, clique_size, graph_size, method):
        """ Solves the given clique problem. """
        # Generate a Graph
        self._graph = ConnectedGraph(graph_size)
        # Generate an equation to solve and its variables
        result = self._generate_equation(clique_size)
        self._equation = result[0]
        var_set = result[1]
        self._goal_fitness = len(self._equation._clauses)
        # Generate a method to solve equation
        self._method = self._determine_method(method)()
        # Run algorithm on a seperate thread
        self._algo_thread = Thread(target=self._method.run,
                                   args=(
                                       self._equation,
                                       len(var_set),
                                   ))
        # Run poller on seperate thread
        self._poll_thread = Thread(target=self._poll)
        self._algo_thread.start()
        self._poll_thread.start()

    def _determine_method(self, method):
        """ Returns the Genetic Algorithm class to be instantiated. """
        if method == "EvoSAP":
            print("EvoSAP - Original")
            return EvoSAP
        elif method == "FlipGA":
            print("FlipGA - Original")
            return FlipGA
        elif method == "BlindGA":
            print("BlindGA - Original")
            return BlindGA
        elif method == "EvoSAP1":
            print("EvoSAP - Mutation 1")
            return EvoSAP_1
        elif method == "EvoSAP2":
            print("EvoSAP - Mutation 2")
            return EvoSAP_2
        elif method == "FlipGA1":
            print("FlipGA - Mutation 1")
            return FlipGA_1
        elif method == "FlipGA2":
            print("FlipGA - Mutation 2")
            return FlipGA_2

    def _poll(self):
        """ Polls the algorithm, updating observers when required. """
        cur_fit = -1
        org = None
        sleep(2)
        while not self._method.is_finished():
            org = self._method.get_best_genome()
            if org is not None:
                self._method.get_best_genome().evaluate(self._equation)
                # Update graph
                self._generate_graph(org)
                # Update observers
                self._notify_observers(org)
                sleep(2)
        # Update when finished
        org = self._method.get_best_genome()
        self._generate_graph(org)
        self._notify_observers(org)

    def _generate_graph(self, org):
        """ Generates a graph based on current state of method's best orgnism. """
        genome = org.get_genes()
        count = 1
        for gene in genome:  # For each gene (edge)
            if gene.get_information():
                self._graph.get_edge(count).set_colour(1)
            else:
                self._graph.get_edge(count).set_colour(0)
            count = count + 1

    def _generate_equation(self, clique_size):
        """ Generates a boolean equation and variable set based on the parameters. """
        # Generate string equivalent
        bln_eq_str = ""
        var_set = []
        vertex_combinations = combinations(
            self._graph.get_vertices(),
            clique_size)  # Get all combinations of vertices
        for combination in vertex_combinations:
            # Generate clause and inverse clause
            clause_one = ""
            clause_two = ""
            for edge in self._graph.get_edges(
            ):  # Get all edges in this combination
                if (edge.get_origin() in combination) and (edge.get_target()
                                                           in combination):
                    edge_id = str(
                        edge.get_id())  # Found an edge in this combination
                    var_id = "{" + edge_id + "}"
                    clause_one = clause_one + "+¬" + var_id + ""
                    clause_two = clause_two + "+" + var_id + ""

            # Format clause
            clause_one = "(" + clause_one[
                1:] + ")"  # The substring removes the first redundant "AND" symbol
            clause_two = "(" + clause_two[1:] + ")"
            # Add clause to equation
            bln_eq_str = bln_eq_str + "." + clause_one + "." + clause_two
        # Generate variables list
        for edge in self._graph.get_edges():
            var_id = "{" + str(edge.get_id()) + "}"
            var_set.append(var_id)
        # Format Equation
        bln_eq_str = bln_eq_str[1:]  # Removes redundant AND symbol
        # Generate equation object
        return (Equation(bln_eq_str), var_set)

    def _notify_observers(self, org):
        """ Notifies observers of genetic parameters and graph. """
        best_genome = self._method.get_best_genome()
        if best_genome is not None:
            args = {
                "generation": self._method.get_generation(),
                "evals": self._method.get_num_evaluations(),
                "best_fitness": best_genome.evaluate(self._equation),
                "graph": self._graph,
                "finished": self._method.is_finished(),
                "history": {
                    "fitness": list(self._method.get_fitness_history()),
                    "evaluation": list(self._method.get_evaluation_history())
                }
            }
            for o in self._observers:
                o.update(args)

    def update(self, args):
        """ Get clique and graph size and begin simulation. """
        clique_size = args['clique_size']
        graph_size = args['graph_size']
        method = args['method']
        self._solve(clique_size, graph_size, method)