presentation ready version
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 24 Feb 2019 20:53:52 +0000 (14:53 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 24 Feb 2019 20:53:52 +0000 (14:53 -0600)
conf.lua [new file with mode: 0644]
lua/graph.lua
lua/utils.lua
main.lua
modules/graph_algorithms.c
modules/graph_algorithms.h
modules/graph_module.c
modules/graph_standard.c
modules/graph_utils.c
modules/graph_utils.h
modules/utils.c

diff --git a/conf.lua b/conf.lua
new file mode 100644 (file)
index 0000000..820c076
--- /dev/null
+++ b/conf.lua
@@ -0,0 +1,6 @@
+function love.conf(t)
+       t.window.title = "Graph Visualizer"
+
+       t.window.width = 1200
+       t.window.height = 800
+end
\ No newline at end of file
index 9e91b8a7379ae4c6090178d3c0b7d1e5202ed9c3..1f89cc21d66a56a6867991c33a44ea67952a3c66 100644 (file)
@@ -111,4 +111,16 @@ function Graph:dijkstras(startID, iterations)
        return graphs.dijkstras(self.graph, startID, iterations)
 end
 
+function Graph:depthFirst(startID, iterations)
+       return graphs.depth_first_search(self.graph, startID, iterations)
+end
+
+function Graph:breadthFirst(startID, iterations)
+       return graphs.breadth_first_search(self.graph, startID, iterations)
+end
+
+function Graph:prims(startID, iterations)
+       return graphs.prims(self.graph, startID, iterations)
+end
+
 return Graph
\ No newline at end of file
index dd1793f83ebba3e735527f34543e807e8bf29735..cc21175d46bb1ace34d50676f549f7f2e9a21e2b 100644 (file)
@@ -2,6 +2,10 @@ function math.lerp(a, b, t)
        return a + (b - a) * t
 end
 
+function math.sqrDist(x1, y1, x2, y2)
+       return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)
+end
+
 function math.uuid()
        return ("xxxxxxxx-xxxx-4yxx-xxxxxxxx"):gsub('[xy]', function (c)
         local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
index 2a784c0878090e287af12ad3366cff5a90228743..0e2e22944dd4cbf118c2d001e51977ea3f8a0a29 100644 (file)
--- a/main.lua
+++ b/main.lua
@@ -13,24 +13,12 @@ function love.load()
        SIDEBAR_FONT = love.graphics.setNewFont(24)
 
        graph = Graph:new()
-
-       -- graph:addNode(100, 100)
-       -- graph:addNode(300, 100)
-       -- graph:addNode(200, 200)
-       -- graph:addNode(500, 400)
-       -- graph:addNode(300, 300)
-
-       -- graph:addArc(0, 1)
-       -- graph:addEdge(0, 2)
-       -- graph:addArc(1, 3, 99)
-       -- graph:addEdge(1, 2)
-
        regions = Regions:new()
 
        graph_region = {
                -- needed for Regions calculations
                priority = 1;
-               rect = { 200, 0, 600, 600 };
+               rect = { 200, 0, 1000, 800 };
 
                -- other properties
                selectedNode = nil;
@@ -41,7 +29,7 @@ function love.load()
                update = function(self) end;
                draw = function(self)
                        love.graphics.setColor(0.7, 0.8, 0.9)
-                       love.graphics.rectangle("fill", 0, 0, 600, 600)
+                       love.graphics.rectangle("fill", 0, 0, 1000, 800)
                        drawGraph(graph, self.selectedNode)
 
                        if self.postDrawFunction then
@@ -53,6 +41,7 @@ function love.load()
                        self.isMouseDown = true
                        self.selectedNode = nil
                        local nodes = graph:getNodes()
+                       local edges = graph:getEdges()
 
                        for _, node in pairs(nodes) do
                                local nx = node.x
@@ -65,6 +54,22 @@ function love.load()
                                        else
                                                self.clickNodeFunction(node)
                                        end
+
+                                       return
+                               end
+                       end
+
+                       for _, edge in pairs(edges) do
+                               local x1, y1 = graph:getNodePos(edge.from_node)
+                               local x2, y2 = graph:getNodePos(edge.to_node)
+
+                               local d1 = math.sqrt(math.sqrDist(x1, y1, x, y))
+                               local d2 = math.sqrt(math.sqrDist(x2, y2, x, y))
+                               local d3 = math.sqrt(math.sqrDist(x1, y1, x2, y2))
+
+                               if d1 + d2 <= d3 + 2 then
+                                       createWeightChanger(edge.id, (x1 + x2) / 2 + 100, (y1 + y2) / 2 - 50)
+                                       return
                                end
                        end
                end;
@@ -90,7 +95,7 @@ function love.load()
        -- Sidebar
        regions:add {
                priority = 1;
-               rect = { 0, 0, 200, 600 };
+               rect = { 0, 0, 200, 800 };
 
                buttons = {
                        {
@@ -106,7 +111,7 @@ function love.load()
                                click = function(self)
                                        graph:addNode(self.placeX, self.placeY)
                                        self.placeX = self.placeX + 40
-                                       if self.placeX >= 600 then
+                                       if self.placeX >= 1000 then
                                                self.placeX = 20
                                                self.placeY = self.placeY + 40
                                        end
@@ -162,7 +167,62 @@ function love.load()
                                text = "Run Dijkstras",
                                click = function()
                                        if graph_region.selectedNode ~= nil then
-                                               createDijskstraStepper(graph_region.selectedNode)
+                                               function dijkstrasStepper(start, step)
+                                                       local dj, done = graph:dijkstras(start, step)
+                                                       graph_region.postDrawFunction = function(reg)
+                                                               drawDijkstras(graph, dj)
+                                                       end
+                                                       return done
+                                               end
+                                               createStepper(graph_region.selectedNode, dijkstrasStepper)
+                                       end
+                               end;
+                       };
+                       {
+                               text = "Run DFS",
+                               click = function()
+                                       if graph_region.selectedNode ~= nil then
+                                               function dfsStepper(start, step)
+                                                       local dfs, done = graph:depthFirst(start, step)
+                                                       graph_region.postDrawFunction = function(reg)
+                                                               drawTree(graph, dfs)
+                                                       end
+                                                       return done
+                                               end
+
+                                               createStepper(graph_region.selectedNode, dfsStepper, 0)
+                                       end
+                               end;
+                       };
+                       {
+                               text = "Run BFS",
+                               click = function()
+                                       if graph_region.selectedNode ~= nil then
+                                               function bfsStepper(start, step)
+                                                       local bfs, done = graph:breadthFirst(start, step)
+                                                       graph_region.postDrawFunction = function(reg)
+                                                               drawTree(graph, bfs)
+                                                       end
+                                                       return done
+                                               end
+                                               
+                                               createStepper(graph_region.selectedNode, bfsStepper, 0)
+                                       end
+                               end;
+                       };
+                       {
+                               text = "Run Prims",
+                               click = function()
+                                       if graph_region.selectedNode ~= nil then
+                                               function primStepper(start, step)
+                                                       local prims, done = graph:prims(start, step)
+                                                       graph_region.postDrawFunction = function(reg)
+                                                               drawTree(graph, prims)
+                                                       end
+                                                       return done
+                                               end
+                                               
+                                               createStepper(graph_region.selectedNode, primStepper, 0)
                                        end
                                end;
                        };
@@ -172,16 +232,19 @@ function love.load()
                update = function(self) end;
 
                draw = function(self)
+                       love.graphics.setColor(1, 1, 1)
+                       love.graphics.rectangle("fill", unpack(self.rect))
                        love.graphics.setFont(SIDEBAR_FONT)
+
                        for i, button in ipairs(self.buttons) do
                                if self.mousePos >= (i - 1) * 60 + 10 and self.mousePos < i * 60 - 10 then
-                                       love.graphics.setColor(.4, .4, .4)
+                                       love.graphics.setColor(.9, .9, .9)
                                else
-                                       love.graphics.setColor(.2, .2, .2)
+                                       love.graphics.setColor(.7, .7, .7)
                                end
                                love.graphics.rectangle("fill", 10, (i - 1) * 60 + 10, 180, 40)
 
-                               love.graphics.setColor(1, 1, 1)
+                               love.graphics.setColor(0, 0, 0)
                                love.graphics.printf(button.text, 0, (i - 1) * 60 + 15, 200, "center")  
                        end
                end;
@@ -189,7 +252,7 @@ function love.load()
                mousedown = function(self, x, y)
                        for i, button in ipairs(self.buttons) do
                                if y >= (i - 1) * 60 + 10 and y <= i * 60 + 10 then
-                                       button.click(button)
+                                       button:click()
                                end
                        end
                end;
@@ -215,60 +278,53 @@ function love.load()
        --      mouseenter = function(self) end;
        --      mouseleave = function(self) end;
        -- }
-
-       createWeightChanger(0)
 end
 
-local dijkstrasOpen = false
-function createDijskstraStepper(start)
-       if dijkstrasOpen then return end
+local stepperOpen = false
+function createStepper(start, update, startStep)
+       if stepperOpen then return end
 
-       dijkstrasOpen = true
-       local step = -1
+       stepperOpen = true
+       startStep = startStep or -1
+       local step = startStep
 
-       local isDone = false
-       function updateDijkstras()
-               local dj, done = graph:dijkstras(start, step)
-               isDone = done
-               graph_region.postDrawFunction = function(reg)
-                       drawDijkstras(graph, dj)
-               end
-       end
-       updateDijkstras()
+       update(start, step)
 
+       local isDone = false
        local reg_id
+       local width = 1000
        local region = {
                priority = 10;
-               rect = { 200, 550, 600, 50 };
+               rect = { 200, 750, width, 50 };
 
                update = function(self) end;
                draw = function(self)
                        love.graphics.setFont(SIDEBAR_FONT)
                        love.graphics.setColor(0, 0, 0, 0.7)
-                       love.graphics.rectangle("fill", 0, 0, 600, 50)
+                       love.graphics.rectangle("fill", 0, 0, width, 50)
 
                        love.graphics.setColor(1, 1, 1)
-                       love.graphics.polygon("fill", 265, 25, 295, 10, 295, 40)
-                       love.graphics.polygon("fill", 335, 25, 305, 10, 305, 40)
+                       love.graphics.polygon("fill", (width / 2) - 35, 25, (width / 2) - 5, 10, (width / 2) - 5, 40)
+                       love.graphics.polygon("fill", (width / 2) + 35, 25, (width / 2) + 5, 10, (width / 2) + 5, 40)
 
-                       love.graphics.printf("X", 540, 5, 50, "center", 0, 1.4, 1.4)
+                       love.graphics.printf("X", width - 60, 5, 50, "center", 0, 1.4, 1.4)
                end;
                mousedown = function(self, x, y)
-                       if x >= 265 and x <= 295 then
+                       if x >= (width / 2) - 35 and x <= (width / 2) - 5 then
                                step = step - 1
                                isDone = false
-                               if step < -1 then step = -1 end
-                       elseif x >= 305 and x <= 335 then
+                               if step < startStep then step = startStep end
+                       elseif x >= (width / 2) + 5 and x <= (width / 2) + 35 then
                                if not isDone then
                                        step = step + 1
                                end
                        end
 
-                       updateDijkstras()
-                       if x >= 550 then
+                       isDone = update(start, step)
+                       if x >= width - 50 then
                                regions:remove(reg_id)
                                graph_region.postDrawFunction = nil
-                               dijkstrasOpen = false
+                               stepperOpen = false
                        end
                end;
                mouseup = function(self, x, y) end;
@@ -280,10 +336,15 @@ function createDijskstraStepper(start)
        reg_id = regions:add(region)
 end
 
-function createWeightChanger(edgeID)
-       regions:add {
+function createWeightChanger(edgeID, x, y)
+       if y < 0 then
+               y = 0
+       end
+
+       local reg_id
+       reg_id = regions:add {
                priority = 100;
-               rect = { 200, 0, 200, 100 };
+               rect = { x, y, 200, 100 };
 
                update = function(self) end;
                draw = function(self)
@@ -315,7 +376,32 @@ function createWeightChanger(edgeID)
                        end
                end;
                mousedown = function(self, x, y)
+                       if math.sqrDist(x, y, 160, 60) <= 20 * 20 then
+                               local edge = graph:getEdge(edgeID)
+                               local otherEdge = graph:getEdgeID(edge.to_node, edge.from_node, edge.weight)
+
+                               if otherEdge ~= -1 then
+                                       graph:setEdgeWeight(otherEdge, edge.weight + 1)
+                               end
+
+                               graph:setEdgeWeight(edge.id, edge.weight + 1)
+                       end
+                       if math.sqrDist(x, y, 40, 60) <= 20 * 20 then
+                               local edge = graph:getEdge(edgeID)
+                               local otherEdge = graph:getEdgeID(edge.to_node, edge.from_node, edge.weight)
+
+                               if edge.weight >= 2 then
+                                       if otherEdge ~= -1 then
+                                               graph:setEdgeWeight(otherEdge, edge.weight - 1)
+                                       end
 
+                                       graph:setEdgeWeight(edge.id, edge.weight - 1)
+                               end
+                       end
+
+                       if x >= 170 and y <= 30 then
+                               regions:remove(reg_id)
+                       end
                end;
                mouseup = function(self, x, y) end;
                mousemove = function(self, x, y, dx, dy) end;
@@ -324,23 +410,9 @@ function createWeightChanger(edgeID)
        }
 end
 
-function love.mousepressed(x, y, button, isTouch, presses)
-       regions:mousedown(x, y)
-end
-
-function love.mousereleased(x, y, button, isTouch, presses)
-       regions:mouseup(x, y)
-end
-
-function love.mousemoved(x, y, dx, dy)
-       regions:mousemove(x, y, dx, dy)
-end
-
-function love.update()
-       regions:update()
-end
-
 -- DRAWING FUNCTIONS
+local NODE_INNER_RADIUS = 17
+local NODE_OUTER_RADIUS = 20
 
 function drawEdge(x1, y1, x2, y2, directed, weight, color)
        love.graphics.setColor(color)
@@ -365,12 +437,12 @@ function drawEdge(x1, y1, x2, y2, directed, weight, color)
                love.graphics.rectangle("fill", cx - arrowSize * .6, cy - arrowSize * .6, arrowSize * 1.2, arrowSize * 1.2)
        end
 
-       love.graphics.setColor(1, 1, 1)
-       love.graphics.printf(tostring(weight), cx - 20, cy - 10, 40, "center")
+       if weight ~= nil then
+               love.graphics.setColor(1, 1, 1)
+               love.graphics.printf(tostring(weight), cx - 20, cy - 10, 40, "center")
+       end
 end
 
-local NODE_INNER_RADIUS = 17
-local NODE_OUTER_RADIUS = 20
 function drawGraph(graph, selectedNode)
        local nodes = graph:getNodes()
        local edges = graph:getEdges()
@@ -420,6 +492,35 @@ function drawDijkstras(graph, dijkstras)
        end
 end
 
+function drawTree(graph, tree)
+       love.graphics.setFont(GRAPH_FONT)
+
+       for _, edge in ipairs(tree) do
+               local x1, y1 = graph:getNodePos(edge.from)
+               local x2, y2 = graph:getNodePos(edge.to)
+
+               drawEdge(x1, y1, x2, y2, 0, nil, {1, 0, 0})
+       end
+end
+
+
+-- Love 
+function love.update()
+       regions:update()
+end
+
 function love.draw()
        regions:draw()
 end
+
+function love.mousepressed(x, y, button, isTouch, presses)
+       regions:mousedown(x, y)
+end
+
+function love.mousereleased(x, y, button, isTouch, presses)
+       regions:mouseup(x, y)
+end
+
+function love.mousemoved(x, y, dx, dy)
+       regions:mousemove(x, y, dx, dy)
+end
index 7f5773a85d6ebe55a11d288a7b615792f71e038a..919583509c01969123d0a9cb1da69d0ea4d96e21 100644 (file)
@@ -23,7 +23,7 @@ static dj_node_p dj_search(header head, int start_node)
                }
 
                edge edge_walker = walker->neighbor_list;
-               while (edge_walker != NULL && is_in_list(visited_nodes, edge_walker->to_id) == 1) 
+               while (edge_walker != NULL && is_in_list(visited_nodes, edge_walker->to_id) == 1)
                {
                        edge_walker = edge_walker->next_edge;
                }
@@ -37,6 +37,7 @@ static dj_node_p dj_search(header head, int start_node)
                        push(stack, edge_walker->to_id);
                }
        }
+
        return visited_nodes;
 }
 
@@ -45,26 +46,28 @@ int breadth_first_search(lua_State *L)
        header head = (header)lua_touserdata(L, 1);
        int start_id = lua_tointeger(L, 2);
        int iterations = lua_tointeger(L, 3);
+       lua_pop(L, 3);
 
        int previous_node = start_id;
 
        int current_iterations = 0;
 
-       sq_node_p visited_nodes = NULL;
+       sq_node_p visited = NULL;
        sq_node_p from_visited_nodes = NULL;
-       enque(visited_nodes, start_id);
-       enque(from_visited_nodes, start_id);
-
 
        sq_node_p queue = NULL;
+       sq_node_p from_queue = NULL;
        enque(queue, start_id);
+       enque(from_queue, start_id);
 
        while(queue != NULL && current_iterations <= iterations)
        {
                int node_id = front(queue);
+               int previous_node = front(from_queue);
                deque(queue);
+               deque(from_queue);
 
-               if(sq_contains(visited_nodes, node_id))
+               if(sq_contains(visited, node_id))
                        continue;
 
                connect runner = find_node(head, node_id);
@@ -74,49 +77,45 @@ int breadth_first_search(lua_State *L)
                while(edge_runner != NULL)
                {
                        enque(queue, edge_runner->to_id);
+                       enque(from_queue, runner->node_id);
                        edge_runner = edge_runner->next_edge;
                }
 
                enque(from_visited_nodes, previous_node);
-               previous_node = node_id;
-               enque(visited_nodes, node_id);
+               enque(visited, node_id);
 
                current_iterations++;
        }
 
-       deque(visited_nodes);
-       deque(from_visited_nodes);
-
-
        //BUILD OUT RETURN TO LUA
        lua_newtable(L);
-       sq_node_p vwalker;
-       sq_node_p fvwalker;
+
        int index = 1;
-       while (vwalker != NULL)
+       while (visited != NULL)
        {
                lua_pushnumber(L, index);
 
                lua_newtable(L);
 
-               lua_pushnumber(L, front(fvwalker));
+               lua_pushnumber(L, front(from_visited_nodes));
                lua_setfield(L, 3, "from");
-               deque(fvwalker);
+               deque(from_visited_nodes);
 
-               lua_pushnumber(L, front(vwalker));
+               lua_pushnumber(L, front(visited));
                lua_setfield(L, 3, "to");
-               deque(vwalker);
+               deque(visited);
 
                lua_settable(L, 1);
 
                index++;
        }
 
+       lua_pushboolean(L, queue == NULL);
 
-       sq_delete(visited_nodes);
+       sq_delete(visited);
        sq_delete(from_visited_nodes);
        sq_delete(queue);
-       return 1;
+       return 2;
 }
 
 int depth_first_search(lua_State *L)
@@ -124,77 +123,75 @@ int depth_first_search(lua_State *L)
        header head = (header)lua_touserdata(L, 1);
        int start_id = lua_tointeger(L, 2);
        int iterations = lua_tointeger(L, 3);
-
-       int previous_node = start_id;
+       lua_pop(L, 3);
 
        int current_iterations = 0;
 
-       sq_node_p visited_nodes = NULL;
+       sq_node_p visited = NULL;
        sq_node_p from_visited_nodes = NULL;
-       enque(visited_nodes, start_id);
-       enque(from_visited_nodes, start_id);
+       //enque(visited, start_id);
+       //enque(from_visited_nodes, start_id);
 
        sq_node_p stack = NULL;
+       sq_node_p from_stack = NULL;
        push(stack, start_id);
+       push(from_stack, start_id);
 
-       while(stack != NULL && current_iterations <= iterations)
+       while (stack != NULL && current_iterations <= iterations)
        {
                int node_id = top(stack);
+               int previous_node = top(from_stack);
                pop(stack);
+               pop(from_stack);
 
-               if(sq_contains(visited_nodes, node_id))
+               if(sq_contains(visited, node_id))
                        continue;
 
                connect runner = find_node(head, node_id);
 
                edge edge_runner = runner->neighbor_list; //grab the neighbor list of our current node
 
-               while(edge_runner != NULL)
+               while (edge_runner != NULL)
                {
                        push(stack, edge_runner->to_id);
+                       push(from_stack, runner->node_id);
                        edge_runner = edge_runner->next_edge;
                }
 
                enque(from_visited_nodes, previous_node);
-               previous_node = node_id;
-               enque(visited_nodes, node_id);
+               enque(visited, node_id);
 
                current_iterations++;
        }
 
-       deque(from_visited_nodes);
-       deque(visited_nodes);
-
-
        //BUILD OUT RETURN TO LUA
        lua_newtable(L);
-       sq_node_p vwalker;
-       sq_node_p fvwalker;
        int index = 1;
-       while (vwalker != NULL)
+       while (visited != NULL)
        {
                lua_pushnumber(L, index);
 
                lua_newtable(L);
 
-               lua_pushnumber(L, front(fvwalker));
+               lua_pushnumber(L, front(from_visited_nodes));
                lua_setfield(L, 3, "from");
-               deque(fvwalker);
+               deque(from_visited_nodes);
 
-               lua_pushnumber(L, front(vwalker));
+               lua_pushnumber(L, front(visited));
                lua_setfield(L, 3, "to");
-               deque(vwalker);
+               deque(visited);
 
                lua_settable(L, 1);
 
                index++;
        }
 
+       lua_pushboolean(L, stack == NULL);
 
-       sq_delete(visited_nodes);
+       sq_delete(visited);
        sq_delete(from_visited_nodes);
        sq_delete(stack);
-       return 1;
+       return 2;
 }
 
 int dijkstras(lua_State *L)
@@ -314,3 +311,182 @@ int dijkstras(lua_State *L)
        return 2;
 }
 
+int prims(lua_State *L)
+{
+       header head = (header)lua_touserdata(L, 1);
+       int start_id = lua_tointeger(L, 2);
+       int iterations = lua_tointeger(L, 3);
+       lua_pop(L, 3);
+
+       sq_node_p visited_nodes = NULL;
+       sq_node_p from_visited_nodes = NULL;
+       enque(visited_nodes, start_id);
+       enque(from_visited_nodes, start_id);
+
+       int min_edge_weight;
+       int from_node_id;
+       int to_node_id;
+
+       int current_iterations = 0;
+       int is_completed = 0;
+       
+       while (current_iterations <= iterations)
+       {
+               min_edge_weight = -1;
+               from_node_id = -1;
+               to_node_id = -1;
+
+               edge edge_runner = NULL;
+               sq_node_p node_runner = visited_nodes;
+               while(node_runner != NULL)
+               {
+                       edge_runner = find_node(head, node_runner->value)->neighbor_list;
+                       while(edge_runner != NULL)
+                       {
+                               if(sq_contains(visited_nodes, edge_runner->to_id) == 0 && (edge_runner->weight < min_edge_weight || min_edge_weight == -1))
+                               {
+                                       min_edge_weight = edge_runner->weight;
+                                       from_node_id = node_runner->value;
+                                       to_node_id = edge_runner->to_id;
+                               }
+
+                               edge_runner = edge_runner->next_edge;
+                       }
+
+                       node_runner = node_runner->next;
+               }
+
+               if(min_edge_weight == -1)
+               {
+                       is_completed = 1;
+                       break;
+               }
+
+               enque(visited_nodes, to_node_id);
+               enque(from_visited_nodes, from_node_id);
+
+               current_iterations++;
+       }
+
+
+       //RETURN STUFF
+       lua_newtable(L);
+       deque(visited_nodes);
+       deque(from_visited_nodes);
+
+       int index = 1;
+       while (visited_nodes != NULL)
+       {
+               lua_pushnumber(L, index);
+
+               lua_newtable(L);
+
+               lua_pushnumber(L, front(from_visited_nodes));
+               lua_setfield(L, 3, "from");
+               deque(from_visited_nodes);
+
+               lua_pushnumber(L, front(visited_nodes));
+               lua_setfield(L, 3, "to");
+               deque(visited_nodes);
+
+               lua_settable(L, 1);
+
+               index++;
+       }
+
+       lua_pushboolean(L, is_completed == 1);
+
+       //MEMORY IS ALREADY FREE'D FROM DEQUEs
+       //sq_delete(visited_nodes);
+       //sq_delete(from_visited_nodes);
+       return 2;
+}
+
+
+int kruskals(lua_State *L)
+{
+       header head = (header)lua_touserdata(L, 1);
+       int iterations = lua_tointeger(L, 3);
+       lua_pop(L, 2);
+
+       sq_node_p visited_nodes = NULL;
+       sq_node_p from_visited_nodes = NULL;
+
+       int min_edge_weight;
+       int from_node_id;
+       int to_node_id;
+
+       int current_iterations = 0;
+       int is_completed = 0;
+       
+       while (current_iterations <= iterations)
+       {
+               min_edge_weight = -1;
+               from_node_id = -1;
+               to_node_id = -1;
+
+               edge edge_runner = NULL;
+               connect node_runner = head->front; 
+               while(node_runner != NULL)
+               {
+                       edge_runner = node_runner->neighbor_list;
+                       while(edge_runner != NULL)
+                       {
+                               if((sq_contains(visited_nodes, edge_runner->to_id) == 0 || sq_contains(visited_nodes, node_runner->node_id) == 0) && (edge_runner->weight < min_edge_weight || min_edge_weight == -1))
+                               {
+                                       min_edge_weight = edge_runner->weight;
+                                       from_node_id = node_runner->node_id;
+                                       to_node_id = edge_runner->to_id;
+                               }
+
+                               edge_runner = edge_runner->next_edge;
+                       }
+
+                       node_runner = node_runner->next_node;
+               }
+
+               if(min_edge_weight == -1)
+               {
+                       is_completed = 1;
+                       break;
+               }
+
+               enque(visited_nodes, to_node_id);
+               enque(from_visited_nodes, from_node_id);                
+
+               iterations++;
+       }
+
+
+       //RETURN STUFF
+       lua_newtable(L);
+       deque(visited_nodes);
+       deque(from_visited_nodes);
+
+       int index = 1;
+       while (visited_nodes != NULL)
+       {
+               lua_pushnumber(L, index);
+
+               lua_newtable(L);
+
+               lua_pushnumber(L, front(from_visited_nodes));
+               lua_setfield(L, 3, "from");
+               deque(from_visited_nodes);
+
+               lua_pushnumber(L, front(visited_nodes));
+               lua_setfield(L, 3, "to");
+               deque(visited_nodes);
+
+               lua_settable(L, 1);
+
+               index++;
+       }
+
+       lua_pushboolean(L, is_completed == 1);
+
+       //MEMORY IS ALREADY FREE'D FROM DEQUEs
+       //sq_delete(visited_nodes);
+       //sq_delete(from_visited_nodes);
+       return 2;
+}
\ No newline at end of file
index 4cc8572bab54048b9455ef1dd66c450060b22f82..ab63cb28f798ac258bf0256015fffd1e02fca48d 100644 (file)
@@ -1,3 +1,4 @@
+
 #ifndef __GRAPH_ALGORITHM_H__
 #define __GRAPH_ALGORITHM_H__
 
@@ -6,5 +7,8 @@
 #include "graph_types.h"
 
 LUA_FUNCTION(dijkstras);
+LUA_FUNCTION(depth_first_search);
+LUA_FUNCTION(breadth_first_search);
+LUA_FUNCTION(prims);
 
 #endif
\ No newline at end of file
index 41f3cfd4203d84876b449c93610bb125910d56d8..7f3d2fec646a5ac5b68f5d42c2b06b8b0401ec63 100644 (file)
@@ -26,6 +26,9 @@ int luaopen_graphs(lua_State *L)
 
                { "print_graph", print_graph },
                { "dijkstras", dijkstras },
+               { "depth_first_search", depth_first_search },
+               { "breadth_first_search", breadth_first_search },
+               { "prims", prims },
                
                { NULL, NULL }
        };
index cabbd730751429b860c33b169613910ab2705d2f..0c77360cd7cdfdedf4506e4d6de32cf1f4bafbee 100644 (file)
@@ -31,7 +31,7 @@ int add_node(lua_State *L)
        new_node->x = 0;
        new_node->y = 0;
 
-       if (head->node_count == 0)
+       if (head == NULL || head->node_count == 0 || head->front == NULL)
        {
                new_node->node_id = 0;
                head->front = new_node;
@@ -54,6 +54,7 @@ int add_node(lua_State *L)
                        walker->next_node = new_node;
                }
        }
+
        head->node_count++;
 
        lua_pushnumber(L,new_node->node_id);
index eec6ad0f4a0434f1939fa06f8d1f4c2d41db7058..4b1ec28091bc70e9b5d47b3603455e39c534f8e7 100644 (file)
@@ -96,7 +96,8 @@ int get_edge_id(lua_State *L)
        int edge_id = lua_tointeger(L, 2);
        lua_pop(L, 2);
 
-       edge e = get_edge(head, edge_id);
+       connect node = NULL;
+       edge e = get_edge(head, edge_id, &node);
        if (e == NULL) {
                lua_pushnil(L);
        } else {
@@ -105,6 +106,12 @@ int get_edge_id(lua_State *L)
                lua_pushnumber(L, e->weight);
                lua_setfield(L, 1, "weight");
 
+               lua_pushnumber(L, node->node_id);
+               lua_setfield(L, 1, "from_node");
+
+               lua_pushnumber(L, e->to_id);
+               lua_setfield(L, 1, "to_node");
+
                lua_pushnumber(L, e->edge_id);
                lua_setfield(L, 1, "id");
        }
@@ -119,7 +126,7 @@ int set_edge_weight(lua_State *L)
        int new_weight = lua_tointeger(L, 3);
        lua_pop(L, 3);
 
-       edge e = get_edge(head, edge_id);
+       edge e = get_edge(head, edge_id, NULL);
        if (e == NULL) return 0;
 
        e->weight = new_weight;
@@ -225,7 +232,7 @@ edge find_edge(header head, int from_node, int to_node, int weight)
        return jogger;
 }
 
-edge get_edge(header head, int edge_id)
+edge get_edge(header head, int edge_id, connect* node)
 {
        connect jogger = head->front;
        while (jogger != NULL)
@@ -236,6 +243,9 @@ edge get_edge(header head, int edge_id)
                {
                        if (curr_edge->edge_id == edge_id)
                        {
+                               if (node != NULL)
+                                       *node = jogger;
+
                                return curr_edge;
                        }
 
index b6f1f267e215239a57f7f91d6116c3efa1a220a0..63d4c3d2f8a51579ba4fd51b39a24760a96ab9e1 100644 (file)
@@ -40,6 +40,6 @@ LUA_FUNCTION(print_graph);
 
 connect find_node(header head, int node_id);
 edge    find_edge(header head, int from_node, int to_node, int weight);
-edge   get_edge(header head, int edge_id);
+edge   get_edge(header head, int edge_id, connect* node);
 
 #endif
\ No newline at end of file
index 4352cb56e75ef21ac03edf24048dd4ea48e9fc7d..12717cd11817f3647c1119f7d991707d01a64aa3 100644 (file)
@@ -44,8 +44,7 @@ sq_node_p sq_pop(sq_node_p stack_top)
 
        stack_top = stack_top->next;
 
-       int n = temp->value;
-       free(temp);
+       free(temp); //dump the removed top of stack
 
        return stack_top;
 }
@@ -76,17 +75,17 @@ sq_node_p sq_enque(sq_node_p front_of_queue, int val)
 
 sq_node_p sq_deque(sq_node_p front_of_queue)
 {
-       if(front_of_queue == NULL)
+       sq_node_p temp = front_of_queue;
+
+       if(temp == NULL)
        {
                puts("QUEUE IS ALREADY EMPTY");
                return NULL;
        }
 
-       sq_node_p temp = front_of_queue;
-
        front_of_queue = front_of_queue->next;
 
-       free(temp); //dump the removed queue
+       free(temp); //dump the removed front of queue
 
        return front_of_queue;
 }
@@ -120,15 +119,8 @@ void sq_print(sq_node_p sq)
 
 void sq_delete(sq_node_p sq)
 {
-       sq_node_p runner = sq;
-
        while(sq != NULL)
-       {
-               sq_node_p tmp = sq;
-               sq = sq->next;
-
-               free(tmp);
-       }
+               pop(sq);
 }
 
 dj_node_p insert_dj(dj_node_p front_of_list, int id, int distance)