diff --git a/Makefile b/Makefile index 4d18490..3a748a2 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,8 @@ SRC_MODULES = \ kruskal \ heap \ union_find \ - demo + demo \ + doc TARGETS = \ src_target @@ -36,6 +37,9 @@ src_target: $(SRC_MODULES:%=$(EBIN)/%.beam) $(EBIN)/%.beam: %.erl $(ERLC) $(ERLC_FLAGS) -o $(EBIN) $< +edoc: + @(./makedoc.rb) + dialyze: $(TARGETS) dialyzer -n -Wunmatched_returns $(EBIN)/*.beam diff --git a/doc/overview.edoc b/doc/overview.edoc new file mode 100644 index 0000000..8484b3d --- /dev/null +++ b/doc/overview.edoc @@ -0,0 +1,20 @@ +@author Aggelos Giantsios +@copyright 2013 Aggelos Giantsios +@title Welcome to erlang-algorithms! +@doc The goal of this project is to implement some useful algorithms and data structures in Erlang so as to help anyone who may need them. + +== Currently Implemented Data Structures == +
This module implements directed and undirected graphs that are either +%% weighted or unweighted.
+%% +%%It is basically syntactic sugar for the digraph module with added +%% support for undirected graphs.
+%% +%%In order to create a graph you must load it from a file. +%% The file that contains the graph must have the following format.
+%% +%%directed
or undirected
that denotes the type of the graph.unweighted
or d
or f
that denotes the type of the edge weights.
+%% unweighted
is for an unweighted graph.d
is for decimal integer weights.f
is for floating point number weights in proper Erlang syntax.For examples you can check the files in the test_data directory.
+%% -module(graph). -%% External Exports -export([new_graph/1, del_graph/1, vertices/1, edges/1, edge_weight/2, edges_with_weights/1, out_neighbours/2, num_of_vertices/1, num_of_edges/1, pprint/1]). -%% Exported Types -export_type([graph/0, vertex/0, edge/0]). -%% Types Declarations +%% +%% @type graph(). A directed or undirected graph. +%%It is wrapper for a digraph with the extra information on its type.
+%% -record(graph, {type :: graphtype(), graph :: digraph()}). --type graph() :: #graph{}. --type vertex() :: non_neg_integer() | atom(). +-opaque graph() :: #graph{}. +-type vertex() :: non_neg_integer(). -type edge() :: {vertex(), vertex()}. -type graphtype() :: 'directed' | 'undirected'. -type weighttype() :: 'unweighted' | 'd' | 'f'. @@ -46,7 +83,7 @@ %% Exported Functions %% ========================================================== -%% Create a new graph from a file +%% @doc Create a new graph from a file -spec new_graph(file:name()) -> graph(). new_graph(File) -> @@ -62,26 +99,26 @@ new_graph(File) -> 'ok' = init_edges(G, M, IO, T, W), #graph{type=T, graph=G}. -%% Delete a graph +%% @doc Delete a graph -spec del_graph(graph()) -> 'true'. del_graph(G) -> digraph:delete(G#graph.graph). -%% Get the vertices of a graph +%% @doc Return a list of the vertices of a graph -spec vertices(graph()) -> [vertex()]. vertices(G) -> digraph:vertices(G#graph.graph). -%% Return the number of vertices in a graph +%% @doc Return the number of vertices in a graph -spec num_of_vertices(graph()) -> non_neg_integer(). num_of_vertices(G) -> Vs = vertices(G), length(Vs). -%% Get the edges of a graph +%% @doc Return a list of the edges of a graph -spec edges(graph()) -> [edge()]. edges(G) -> @@ -93,34 +130,34 @@ edges(G) -> remove_duplicate_edges(Es, []) end. -%% Return the number of edges in a graph +%% @doc Return the number of edges in a graph -spec num_of_edges(graph()) -> non_neg_integer(). num_of_edges(G) -> Es = edges(G), length(Es). -%% Get the weight of an edge +%% @doc Return the weight of an edge -spec edge_weight(graph(), edge()) -> term(). edge_weight(G, E) -> {E, _V1, _V2, W} = digraph:edge(G#graph.graph, E), W. -%% Get the edges of a graph along with their weights +%% @doc Return a list of the edges of a graph along with their weights -spec edges_with_weights(graph()) -> [{edge(), term()}]. edges_with_weights(G) -> Es = edges(G), lists:map(fun(E) -> {E, edge_weight(G, E)} end, Es). -%% Get the out neighbours of a vertex +%% @doc Return a list of the out neighbours of a vertex -spec out_neighbours(graph(), vertex()) -> [vertex()]. out_neighbours(G, V) -> digraph:out_neighbours(G#graph.graph, V). -%% Pretty print a graph +%% @doc Pretty print a graph -spec pprint(graph()) -> 'ok'. pprint(G) -> diff --git a/src/heap.erl b/src/heap.erl index 28b4a44..cdc16b4 100644 --- a/src/heap.erl +++ b/src/heap.erl @@ -1,48 +1,63 @@ %% +%% %CopyrightBegin% +%% %% Copyright © 2013 Aggelos Giantsios %% - %% Permission is hereby granted, free of charge, to any person obtaining a copy of this software %% and associated documentation files (the “Software”), to deal in the Software without restriction, %% including without limitation the rights to use, copy, modify, merge, publish, distribute, %% sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is %% furnished to do so, subject to the following conditions: - +%% %% The above copyright notice and this permission notice shall be included %% in all copies or substantial portions of the Software. - +%% %% THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED %% TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. %% IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER %% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN %% CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - %% -%% Min-Heap, Max-Heap, Priority Queue +%% %CopyrightEnd% %% +%% @copyright 2013 Aggelos Giantsios +%% @author Aggelos Giantsios + +%% ============================================================================ +%% @doc Min-Heap, Max-Heap for Priority Queues +%% +%% %% This module implements min-heaps and max-heaps for use in priority queues. -%% Each value in the heap is assosiated with a reference so that the user can change its priority in O(log n). +%% Each value in the heap is assosiated with a reference so that +%% the user can change its priority in O(log n). %% %% The implementation is based on ETS tables for the O(1) lookup time. %% It supports all the basic heap operations: -%% * min/1, max/1 in O(1) -%% * take_min/1, take_max/1 in O(log n) -%% * insert/2 in O(log n) -%% * update/3 in O(log n) -%% * from_list/2 in Θ(n) - +%%min/1
, max/1
in O(1)take_min/1
, take_max/1
in O(log n)insert/2
in O(log n)update/3
in O(log n)from_list/2
in O(n)In order to achieve the above complexities the heap needs to store
+%% an extra tuple {Key, Reference}
for every
+%% Key
stored. In addition, the size of the heap is
+%% stored as a tuple {size, Size}
.
If M
is max
then it will be a max heap,
+%% else if M
is min
it will be a min heap.
If it is a min heap, it returns {error, min_heap}
.
If it is a max heap, it returns {error, max_heap}
.
It returns a tuple with the element added and a reference +%% so that one can change its priority.
-spec insert(heap(), term()) -> refterm(). insert(H, X) -> @@ -152,9 +156,7 @@ insert(H, X) -> insert_loop(H, I, P), {X, Ref}. -%% ----------------------------------------------------------------------- -%% Removes and returns the max -%% ----------------------------------------------------------------------- +%% @doc Removes and returns the maximum priority element of a max heap. -spec take_max(heap()) -> term() | {'error', 'min_heap' | 'empty_heap'}. take_max(H) when H#heap.mode =:= 'max' -> @@ -162,20 +164,16 @@ take_max(H) when H#heap.mode =:= 'max' -> take_max(_H) -> {'error', 'min_heap'}. -%% ----------------------------------------------------------------------- -%% Removes and returns the min -%% ----------------------------------------------------------------------- +%% @doc Removes and returns the minimum priority element of a min heap. -spec take_min(heap()) -> term() | {'error', 'max_heap' | 'empty_heap'}. - + take_min(H) when H#heap.mode =:= 'min' -> pop(H); take_min(_H) -> {'error', 'max_heap'}. -%% ----------------------------------------------------------------------- %% Deletes and returns the element at the top of the heap %% and re-arranges the rest of the heap -%% ----------------------------------------------------------------------- -spec pop(heap()) -> term(). pop(H) -> @@ -199,10 +197,9 @@ pop(H) -> Head end. -%% ----------------------------------------------------------------------- -%% Changes the priority of the element referenced with Ref to Value -%% and then re-arranges the heap -%% ----------------------------------------------------------------------- +%% @doc Change the priority of an element. +%%It changes the priority of the element referenced with
+%% Ref
to Value
and then re-arranges the heap.
It returns the heap and a list of tuples {Key, Ref}
+%% where Key
is the term that was added and Ref
+%% is its reference (used to change its priority).