Programação por restrições
Luiz Henrique Cherri
Thiago Queiroz
Relembrando
Solvers de programação por restrições
● Comerciais
○ IBM ILOG CP
○ SCIP*
● Livres
○ Google or/tools
○ Choco solver
○ Baseados em PROLOG (como o ‘CHIP’)
○ SCIP*
● Muitos outros (www.constraintsolving.com/solvers)
IBM ILOG CP
● Software comercial
● Livre para uso acadêmico
● Para fins do curso, a versão de avaliação é suficiente!
○ Poucas variáveis
○ Poucas restrições
● Link para cadastro e download:
https://www-01.ibm.com/software/websphere/products/optimization/cplex-studio-community-edition
Baixar o CPLEX community edition
Acessando
Acesso via windows:
● Menu do sistema > oplide Acesso via Linux (ubuntu):
● No terminal:
○ cd /opt/ibm/ILOG/CPLEX_<VERSION>/opl/oplide/
○ ./oplide
Acesso via OSx: O CPLEX não disponibiliza a interface para o sistema!
Abrindo temos...
Visão geral
Tutoriais
Ambiente de trabalho
Novidades Amostras
Interface
Projeto Area de edição
Dados da instância Solução
Mensagens de erro Informações
Soluções Entre outros
Componentes básicas de um projeto
● Um projeto pode ser constituído por três tipos de arquivos:
○ .mod: onde o modelo é implementado;
○ .dat: dados usados na criação do modelo;
○ .ops: arquivo de configuração.
● Para se relacionarem, esses arquivos devem estar ligados à uma mesma componente de execução.
Modelando um problema com
programação por restrições
Estrutura do programa
using CP;
…
<Variáveis e domínios>
…
Minimize <expressão>
constraints { ...
<restrições>
...
}
Estrutura do programa
using CP; ← CP será utilizado pra resolver o problema
…
<Variáveis e domínios> ← Utilizados na formulação
…
Minimize <expressão> ← Função a ser minimizada (opcional) constraints {
...
<restrições> ← Garantem a factibilidade das soluções encontradas ...
}
Tipos de variáveis
● Tipos simples:
○ int : inteiro;
■ Ex: int x = 10;
●
○ float : real;
■ Ex: float y = 1.687;
●
○ string : texto;
■ Ex: string s = “Olá mundo”;
Tipos de variáveis
● É possível declarar um vetor ou matriz de qualquer tipo de dados com a seguinte sintaxe:
○ int x[1..5]; Vetor de inteiros com 5 posições
○ float y[1..5][1..10]; Matriz de valores reais, com 5 linhas e 10 colunas.
● Usando ranges:
○ range r = 1..100;
○ int x[r];
○ range a = 10..50;
○ int y[a];
Variáveis de decisão
Variáveis do modelo são declaradas apenas acrescentando o identificador dvar na declaração.
Em programação por restrições o CPLEX somente aceita variáveis com domínios inteiros!
Ex:
● dvar int a;
● dvar int b[1..a];
● dvar int c[1..10][1..10];
Construindo restrições
● Para criarmos a expressão
● Fazemos:
○ range T = 1..50;
○ dvar int x[T][T];
○ constraints{
○ forall(i in T)
■ sum(j in T) x[i][j]*x[j][i] <= 231;
○ }
Construindo restrições
● Para criarmos a expressão em que:
○ Todos os elementos nos índices pares de um vetor x são diferentes
● Fazemos:
○ range R = 1..5;
○ dvar int x[R] in R;
○ constraints {
■ allDifferent( all(i in R : i%2 == 0) x[i] );
○ }
Algumas restrições globais
● allDifferent (conjunto de variáveis)
○ allDifferent( all(i in R : i%2 == 0) x[i] );
○ allDifferent(x[i]);
● count (conjunto de variáveis, elemento a ser contado)
○ count( all(i in R) x[i], 2);
● allMinDistance
○ allMinDistance(all (i in R : i%2 == 1) x[i] , 2);
● Todas podem ser encontradas aqui.
Implementando nosso exemplo
Coloração de mapas
● Colorir o mapa de parte da Europa: Bélgica, Suíça, França, Alemanha, Holanda, Luxemburgo
● Os países adjacentes não podem possuir a mesma cor
● Quatro cores (azul, vermelho, amarelo, e cinza) seriam suficientes?
Exemplo: coloração de mapas
● O que podem ser nossas variáveis
○ Paises = {Belgica, Suica, Franca, Alemanha, Holanda, Luxemburgo}
● Qual o domínio de cada variável?
○ {azul, vermelho, amarelo, cinza}
● Como representar estas restrições
○ Belgica != Luxemburgo
○ Belgica != Franca
○ Belgica != Alemanha
○ Belgica != Holanda
○ Suica != Franca
○ … e assim por diante
Implementando
No OPL …
Na linguagem OPL
Utilizando a linguagem OPL, a forma de modelar o problema é bastante parecida com o que fizemos anteriormente.
É um problema de factibilidade!
using CP;
range r = 0..3;
string Names[r] = ["blue", "white", "yellow", "green"];
dvar int Belgium in r;
dvar int Switzerland in r;
dvar int France in r;
dvar int Germany in r;
dvar int Luxembourg in r;
dvar int Netherlands in r;
constraints {
Belgium != France;
Belgium != Germany;
Belgium != Netherlands;
Belgium != Luxembourg;
Switzerland != France;
Switzerland != Germany;
France != Germany;
France != Luxembourg;
Germany != Luxembourg;
Germany != Netherlands;
}
Implementando nosso exercício
Exercício - SUDOKU
● Completar a matriz ao lado com elementos de 1 a 9
● Não se pode repetir elementos:
○ Nas linhas
○ Nas colunas
○ Nos sub blocos 3x3 indicados
Implementando
No OPL...
Exercício: N-queens
● As rainhas de um tabuleiro de xadrez podem atacar na vertical, horizontal e diagonal
● Como posicionar N rainhas num tabuleiro NxN sem que elas possam se atacar?
Resolução - variáveis
Criamos um vetor com 12 variáveis
Q =
O domínio de cada variável é {1,2,3,4,5,6,7,8,9,10,11,12} (números de 1 à 12)
1 2 3 4 5 6 7 8 9 10 11 12
Resolução
Q =
Assim
● Não haverá duas rainhas na mesma linha por construção
● AllDifferent (Q[i] , i=1,...,12) (colunas)
● AllDifferent (Q[i] + i , i=1,...,12) (diagonal)
● AllDifferent (Q[i] − i , i=1,...,12) (diagonal)
1 2 3 4 5 6 7 8 9 10 11 12
Resolução
No OPL