A biblioteca contém 15 algoritmos de otimização, 9 de programação dinâmica e 6 algoritmos gulosos. Abaixo podemos ver os algoritmos contidos e quem os implementou.
A biblioteca segue os padrões de código de Python da PEP8
- Mochila binária
- Maior subsequência comum
- Distância de edição
- Caminho mais curto (Algoritmo de Dijkstra)
- Coloração de grafos
- Triângulo de Pascal
- Soma de subconjunto
- Multiplicação de matrizes
- Seleção de atividades
- Mochila fracionária
- Quebra de palavras
- Troco em moedas
- Empilhamento de caixas
- Árvore geradora mínima (Algoritmo de Kruskal)
- Árvore geradora mínima (Algoritmo de Prim)
Um conjunto de testes para cada algoritmo foi desenvolvido e é executado se você rodar o script do algoritmo em questão. Para a criação dos testes automatizados, foi utilizado o módulo unittest.
Exemplo, algoritmo da Maior Subsequência Comum (LCS):
import unittest
class TestLcs(unittest.TestCase):
def test_example(self):
self.assertEqual(lcs('ABC', 'AC', 3, 2), 2)Para rodar toda a suíte de testes, use o seguinte comando no terminal no diretório raiz do projeto:
$ make test
Os algoritmos estão implementados de forma que pode-se chamá-los por duas funções:
import algorithms
# Se chamados pela funcao com 'call' antes, os algoritmos chamam a funcao original
# e printam a saída detalhadamente
algorithms.call_edit_distance(str1, str2)
# Podemos chamar as funcoes otimizadas diretamente utilizando seus parametros originais
algorithms.edit_distance(str1, str2, len(A), len(B))import algorithms
# A entrada é a capacidade da mochila, o peso dos itens e o valor dos itens
# Se for mais de um item, deve-se colocá-los em listas de tamanhos iguais.
# n é a quantidade de valores inseridos, preferencialmente colocar len(value) ou len(weight)
algorithms.max_knapsack.py(cap, weight, value, n)
# A saída é o valor máximo da mochilaA algoritmo da mochila binária pega itens que contém pesos e valores e coloca o máximo de valor possível mediante a capacidade da mochila. Teve sua aplicação principal no algoritmo de Criptografia de chave pública.
- Complexidade O(2^n)
import algorithms
# A entrada são as duas strings que serão comparadas e o tamanho respectivo destas
algorithms.lcs(str1, str2, A, B)
# A saída é o valor inteiro da maior subsequência comumO algoritmo da maior subsequência comum analisa duas strings e visualiza qual o tamanho da maior sequencia comum entre elas. Entre as suas aplicações estão a engine da wiki e sistemas de controle de versão.
- Complexidade O(2^n)
import algorithms
# A entrada são as duas strings que serão comparadas e o tamanho respectivo destas
algorithms.edit_distance(str1, str2, m, n)
# A saída é o valor inteiro do número de operações necessárias para convertar str1 em str2O algoritmo da distância de edição pega duas strings e as compara para saber quantas operações seriam necessárias para que uma string se tornasse a outra.
- Complexidade O(m x n) - Sendo m o tamanho de uma string e n o de outra
import algorithms
# A entrada são dois inteiros, n representa o número da linha e k o da coluna
algorithms.binomial_coefficient(n, k)
# A saída é o valor inteiro do coeficiente binomial do triângulo de pascalO algoritmo pega o número de linhas e de colunas e cálcula pelo triângulo de pascal o coeficiente binomial. Esse algoritmo é utilizado na matemática.
- Complexidade O(n x k)
import algorithms
# A entrada é um array de números e a soma a ser analisada
algorithms.is_subset_sum(set, sum)
# A saída é um booleano dizendo se a soma está contida ou não.O algoritmo confere se em um dado set de números, um número inteiro está contido na soma de números deste set.
- Complexidade O(sum * n)
import algorithms
# A entrada é um array de números e o tamanho dela.
algorithms.matrix_chain_order(arr, n)
# A saída é a menor quantidade possível de múltiplicações das matrizesO algoritmo dá a forma mais eficiente de multiplicar as matrizes de tamanho indicado
- Complexidade O(n³)
import algorithms
# Dado uma string de letras não espaçadas, o algoritmo determina se é possível separá-las em
# palavras de acordo com um dicionário
algorithms.word_break(string, dicionario)
# A saída é True caso seja possível separar as palavrasO algoritmo é usado em corretores de texto como forma de corrigir erros de digitação.
- Complexidade O(n * m), onde n é o tamanho da string e m é o tamanho do dicionário
import algorithms
# A entrada é a quantidade de dinheiro a ser trocado e uma array com as moedas disponíveis para troco
algorithms.coin_change(quantidade, moedas_disponiveis)
# A saída é o menor número de moedas quando esse é possível determinar. Caso não seja, retorna FalseO algoritmo pode ser usado para cálcular o troco de uma determinada transação.
- Complexidade O(n * m), onde n é o número de moedas e m é a quantidade de dinheiro a ser trocada
import algorithms
# A entrada é uma array de dimensões das caixas
algorithms.box_stack(dimensions)
# A saída é a maior altura que as caixas podem ser empilhadas sem violar as restrições de tamanhoO algoritmo pode ser usado para determinar a melhor forma de organizar objetos de dimensões fixas dentro de um espaço.
- Complexidade O(n²)
import algorithms
# A entrada é o grafo, que é representado por um dict e o vértice que será comparado aos outros
graph = {0: {1: 2, 3: 2}, 1: {0: 2, 2: 6}, 2: {1: 6}, 3: {0: 0}}
algorithms.shortest_path(graph, start)
# A saída é uma lista com os valores sequenciais do caminho mais curto
# de cada vértice para o vértice indicado em startO algoritmo do caminho mais curto de Dijkstra mede o caminho mais curto entre um ponto e outro, sua aplicação é vastamente utilizada na programação, como em problemas de Redes telefônicas ou Controle de aeronaves
- Complexidade O(V²)
import algorithms
# A entrada é o grafo, que é representado por um dicionário e as cores que serão dadas aos grafos
graph = {0: {1: 2, 3: 2}, 1: {0: 2, 2: 6}, 2: {1: 6}, 3: {0: 0}}
colors = ['Red', 'Blue', 'Green', 'Yellow', 'Black']
algorithms.colored_graphs(graphs, colors)
# A saída é a respectiva cor de cada vértice do grafoO algoritmo da distância de edição pega duas strings e as compara para saber quantas operações seriam necessárias para que uma string se tornasse a outra.
- Complexidade O(V² + E)
import algorithms
# A entrada são as duas lista, start e finish
algorithms.max_activities(s, f)
# A saída é uma lista indicando quais atividades podem ser executadas por uma única pessoaO algoritmo seleciona o máximo número de atividades possíveis, mediante o tempo de começo e fim destas, que podem ser realizadas por uma única pessoa. Dentre as aplicações estão algoritmos para otimizar rotinas.
import algorithms
# A entrada é a capacidade da mochila, uma listas do objeto item
# que contém peso e valor e o tamanho da lista
items_list = [algorithms.Item(60, 10), algorithms.Item(40, 10), algorithms.Item(50, 30)]
algorithms.fractional_knapsack(W, items_list, n)
# A saída é o valor máximo da mochilaA algoritmo da mochila binária pega itens que contém pesos e valores e coloca o máximo de valor possível mediante a capacidade da mochila. Ao contrário do algoritmo da Mochila Binária, aqui podemos quebrar os valores em várias partes, agilizando o algoritmo.
- Complexidade O(n x log n)
import algorithms
# A entrada são as duas lista, a primeira de vertices e a segunda de conexões (arestas)
algorithms.kruskal(vertices, edges)
# A saída é uma lista de conexões entre os vérticesO algoritmo seleciona o menor caminho percorrido para conextar todos os nós de um grafo com o menor custo possível. É usado, por exemplo, em problemas que envolvem percorrer um espaço (físico ou virtual) no menor tempo/percurso possível, como gerenciar a entrega de envelopes em uma cidade.
- Complexidade O(E log V), onde E é o número de conexões (arestas) e V é o número de vértices
import algorithms
# A entrada são as duas lista, a primeira de vertices e a segunda de arestas
algorithms.prim(vertices, edges)
# A saída é uma lista de conexões entre os vérticesAssim como o Alguritmo de Kruskal, o Algoritmo de Prim é usado para determinar o percurso menos custoso para percorrer todos os nós de um grafo, porém é especializado em grafos mais densos, para o caso em que existem mais arestas que vértices, onde sua performance é melhor. Um exemplo seria o roteamento de pacotes via redes de computador, que é um grafo bastante denso onde quanto menor a latência mais rápido o pacote chegará a outro lado rede.
- Complexidade O(E + V log V) (Amortizada), onde E é o número de arestas e V é o número de vértices