Alura > Cursos de Data Science > Cursos de Machine Learning > Conteúdos de Machine Learning > Primeiras aulas do curso IA aumentada: adicionando a dimensão de tempo ao problema de voos

IA aumentada: adicionando a dimensão de tempo ao problema de voos

Criando uma matriz tridimensional - Apresentação

Olá, pessoal! Meu nome é Guilherme Silveira, sou instrutor e fundador da Alura, e vou te acompanhar nesse curso onde vamos falar sobre algoritmos de otimização.

Audiodescrição: Guilherme Silveira se identifica como uma pessoa branca, não binária, de cabelos curtos, escuros e ondulados e olhos castanhos. Está com uma camiseta bege e headphone. Ao fundo, estúdio com iluminação verde. À direita, uma estante com decorações.

Pré-requisitos

Vamos dar continuidade a um projeto que já começamos, visando resolver problemas de otimização. Se você ainda não fez os cursos anteriores, é importante você que os faça para entender em que ponto estamos no projeto e quais serão os nossos próximos passos.

Vamos fazer uma breve revisão para entender o que abordaremos, mas é essencial que você já tenha feito os cursos anteriores para entender o código, o problema, a situação e o domínio em que estamos trabalhando.

Contexto

Nosso exemplo concreto envolve aviões em um aeroporto. Nós temos aviões, que são nossos recursos, estacionando em nosso aeroporto, que são outros recursos que possuímos, como as vagas de estacionamento.

Quando eles estacionam, temos um custo associado ao estacionamento, além de regras e restrições, como a onde determinado avião ou passageiro pode ir.

Em suma, precisamos atender a todas as regras, preferencialmente também aquelas que são opcionais, e ainda minimizar o custo.

Perceba que isso é um problema complexo que envolve muitos aviões, estacionamentos, regras e uma variedade de combinações diferentes. Por exemplo, o primeiro avião pode estar no estacionamento 0 ou 1, mas não pode estar no 3 ou 4.

São tantas combinações que é humanamente inviável calcular todas. E muitas vezes, no computador, também é computacionalmente inviável calcular todas. Por isso, precisamos de algoritmos.

Matemáticos desenvolveram algoritmos para otimizar essas computações no papel.

Por exemplo, suponha que temos dois estacionamentos, um mais caro e um mais barato, onde você estaciona para minimizar o custo? No mais barato. Nós já temos essa regra em nossa cabeça, mas matemáticos criaram muitas outras regras. E cientistas da computação também criaram regras para que o computador faça esse trabalho em conjunto com a matemática de forma ainda mais otimizada.

O que vamos aprender?

Já trabalhamos com vários estacionamentos, aviões, regras e custos para otimizar o serviço de alocação de recursos desse projeto. Contudo, ainda não trabalhamos com o tempo, que será nossa terceira dimensão.

Portanto, as variáveis utilizadas na otimização de recursos são:

  1. Avião;
  2. Estacionamento;
  3. Tempo.

Vamos trabalhar com o tempo a partir deste curso. O avião tem hora para chegar, ficar e sair.

Queremos seguir diversas regras de acordo com essa terceira dimensão. Portanto, é uma dimensão a mais do problema que nos faz trabalhar com esse nosso problema computacional de uma forma ainda mais matemática.

Com isso, passamos a entender melhor como esses algoritmos resolvem o nosso problema e como devemos pensar para que o algoritmo possa resolver o nosso problema em tempo hábil.

A ideia de modelar o nosso problema de uma forma computacional é o que queremos atacar neste curso, para que possamos otimizar essas restrições.

Claro, estamos no domínio de aviões e estacionamentos de acordo com os cursos anteriores, mas isso é aplicável a outros problemas de otimização de operação que você vai encontrar.

Até breve!

Criando uma matriz tridimensional - Entendendo as janelas de tempo

A nossa ideia é continuar utilizando ferramentas que resolvem certos tipos de problemas computacionais e matemáticos para auxiliar no nosso cenário, que é o aeroporto. Temos um aeroporto que possui recursos específicos, tais como os aviões, que precisam ser alocados em lugares determinados, com restrições diversas. Essas restrições podem ser de custo, de passageiros, de passaporte e outras que surgirem.

Este tipo de cenário se repete em várias outras situações com restrições, como salas de aula, e queremos melhorar e compreender mais as complicações que surgem à medida que desenvolvemos esses modelos matemáticos computacionais.

Vamos retomar o modelo com o qual estávamos trabalhando anteriormente.

// código omitido

X = [[modelo.NewBoolVar(f'aviao_{i}_em_estacionamento_{j}') for j in range(total_estacionam for i in range(total_avioes)]

// código omitido

No modelo anterior, estávamos utilizando uma variável que nomeamos de x, pois ela segue um padrão bidimensional. Ela tem duas dimensões: uma para o avião e outra para o estacionamento, indicando se o avião vai estacionar ou não naquele estacionamento. Se a resposta for sim, é representada por 1, se for não, por 0.

Vamos exemplificar isso em uma planilha.

Imaginemos três estacionamentos: Estacionamento 1, Estacionamento 2 e Estacionamento 3, e também três aviões: Avião 1, Avião 2 e Avião 3. Assim, temos uma matriz 3x3. Se o Avião 1 pousar no Estacionamento 2, então teremos o número 1 naquela posição e 0 nas demais. Se o Avião 2 pousar no Estacionamento 1, é 1, 0, 0. E se o Avião 3 pousa no Estacionamento 3, então é 0, 0, 1.

#avião 1avião 2avião 3
estacionamento1010
estacionamento2100
estacionamento3001

Essa matriz pode ser representada de diferentes maneiras, podemos rotacioná-la, com estacionamentos nas colunas e aviões nas linhas, o que resultaria nas mesmas soluções, apenas trabalhando com linhas e colunas de forma invertida.

#estacionamento1estacionamento2estacionamento3
avião 1010
avião 2100
avião 3001

Não podemos ter dois 1's na mesma linha, pois um avião não pode estar em dois estacionamentos ao mesmo tempo. Da mesma forma, não pode haver dois 1's na mesma coluna, porque não pode haver dois aviões estacionados simultaneamente no mesmo estacionamento.

Esse problema pode ocorrer ao alocarmos as pistas de pouso, sendo uma decisão final daquele momento. No nosso caso, desejamos planejar com antecedência. Isto é, no dia anterior já queremos ter um plano e à medida que os aviões atrasam ou adiantam, realizamos o cálculo novamente.

Um avião não pode estar em dois estacionamentos ao mesmo tempo, isso é um fato. No entanto, a frase "um estacionamento não pode ter dois aviões" colocamos "ao mesmo tempo" no final. Isso porque um avião pode estacionar, decolar e outro avião estaciona, o que é bem comum e pode ocorrer.

Ao pensarmos no plano do dia e não somente no plano do momento, precisamos trabalhar com o tempo. Precisamos considerar: quem, onde e o tempo.

Adicionando a dimensão tempo

Agora, vamos considerar a dimensão do tempo. Um avião pode estacionar, decolar e outro avião pode ocupar o mesmo lugar em um momento diferente. Podemos trabalhar com intervalos de tempo, como janelas de uma hora, e assim teremos uma matriz para cada hora do dia.

Assim, podemos ter o avião 1 às 2h da manhã em um estacionamento; e depois ter um avião 2 às 5h da manhã no mesmo estacionamento. Como modelamos isso? Ao tentarmos aplicar desta forma, temos como referência os primeiros modelos que fizemos, onde a variável recebia qualquer número. E não no formato mais recente, em que trabalhamos com 0 e 1 (binário).

A vantagem de usar binário é trabalhar com somas e aplicar garantias de forma mais simples. Portanto, iremos trabalhar com uma matriz de 0 e 1.

Suponhamos o seguinte cenário às 7h da manhã:

#estacionamento1estacionamento2estacionamento3
avião 1010
avião 2100
avião 3001

O avião 2 está no estacionamento 1; o avião 1 está no estacionamento 2 e o avião 3 está no estacionamento 3. Ao incluirmos um quarto avião, ele não está em nenhum estacionamento.

#estacionamento1estacionamento2estacionamento3
avião 1010
avião 2100
avião 3001
avião 4000

No entanto, na próxima janela de tempo (que pode ser de hora em hora ou horas em horas, depende do problema), no caso usaremos de 1h em 1h. Portanto, às 8h da manhã teremos outra matriz com o mesmo tamanho, mas agora o avião 1, 2 já saiu e não estão em nenhum estacionamento/ já o avião 4 está no estacionamento 1.

#estacionamento1estacionamento2estacionamento3
avião 1000
avião 2000
avião 3000
avião 4100

Assim, para cada hora do dia teremos 24 janelas (pensando nas 24 horas). Portanto, 24 matrizes. Se tínhamos uma matriz 4x3, sendo 4 aviões e 3 estacionamentos; agora, teremos uma matriz 24x4x3, sendo 24 matrizes (janelas de tempo) com 4 aviões e 3 estacionamentos.

// código omitido

X = [[modelo.NewBoolVar(f'aviao_{i}_em_estacionamento_{j}') for j in range(total_estacionam for i in range(total_avioes)]

// código omitido

Quando analisamos o código e observamos os loops for, percebemos que temos o loop for j e o loop for i, onde o for i é o externo e itera sobre os aviões. Vamos utilizar o mesmo padrão, mas agora com três loops: um para os aviões, um para os estacionamentos e um para o tempo.

Nosso desafio agora é criar uma grande matriz que representa, por exemplo, 4 aviões, 3 estacionamentos e 24 intervalos de tempo. Faremos uma janela de tempo mais simples para facilitar a compreensão, mas em um contexto real, um aeroporto pode optar por janelas de 15 em 15 minutos, resultando em 96 janelas de tempo.

Estamos utilizando o tempo como uma nova dimensão de trabalho, algo muito comum quando os recursos envolvem o tempo. Se houver outra dimensão que você precise considerar, o trabalho será análogo.

Até a próxima!

Criando uma matriz tridimensional - Adicionando a nova dimensão

Vamos ao código!

Lembrando, ao abrir o nosso notebook antigo, instalamos o OR-Tools e o Pandas como pré-requisitos. Essa linha vamos simplesmente copiar e colar no novo notebook para executarmos.

!pip install ortools==9.7.2996 pandas==2.1.0

Depois, importamos a ferramenta CP Model do OR-Tools. Também só copiamos e colamos.

from ortools.sat.python import cp_model

vamos verificar o que mais precisamos. A variaveis_a_logar, função de logar variável, por enquanto não precisamos, podemos deixar de lado.

Código do notebook anterior:

def resolve(solucionador, modelo, X):
status = solucionador.Solve(modelo) 
print(f"Status: {status}")

if status == cp_model.OPTIMAL: 
print("Optimal")

for i, linha in enumerate(X):
for j, variavel in enumerate (linha): 
valor = solucionador.Value(variavel)
if valor == 1: 
print(f"{variavel} = {valor}")

print(f"Custo total={solucionador.ObjectiveValue()}")

else:
print("Solucao nao encontrada")

Queremos modificar um pouco a função resolve(), então começaremos a escrevê-la. A função recebe o solucionador, o modelo e X, e deve solicitar a resolução. Para realizar a resolução, utilizamos solucionador.Solve(modelo). Posteriormente, verificamos o status, e, no nosso caso, imprimimos o status e verificamos se é ótimo (o instrutor está analisando o código do notebook anterior). Podemos copiar e colar na nova célula o print() e if().

Imprimimos o status para verificarmos, e se for ótimo, imprimimos que encontramos uma solução ótima. Caso contrário, imprimimos que não encontramos solução, assim: else: print("Solução não encontrada"). É isso, solução não encontrada.

Por enquanto, temos:

def resolve(solucionador, modelo, X):
status = solucionador.Solve(modelo)
print(f"Status: {status}")

if status == cp_model.OPTIMAL: 
print("Optimal")
else:
print("Solução não encontrada")

Essa é a nossa função de resolver, e a diferença em relação à versão anterior é que agora ela não imprime as variáveis. Ela apenas indica se a resolução foi bem-sucedida ou não. Mais tarde, imprimiremos as variáveis, e como estas serão mais complexas, com uma terceira dimensão, é vantajoso abordarmos isso em conjunto.

Vamos ao nosso exemplo.

Temos um último exemplo, que trabalhava com duas variáveis que são importantes: o modelo e o solucionador, que também é copy-paste simples. Copiamos a geração dessas variáveis e passamos para a próxima célula.

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

Criamos o modelo, criamos o solucionador, criamos o total de aviões. Vamos criar um primeiro exemplo que temos três aviões, total estacionamentos, temos três estacionamentos, só que agora temos mais uma dimensão, total de tempo.

Recordando, quantas janelas de tempo desejamos? Temos a janela de 15 minutos, a de 1 hora (24 janelas), e a de 3 horas (8 janelas por dia). A escolha do tamanho dessa dimensão é pessoal, o que fizer sentido para você. Optamos por usar 5 para facilitar a visualização e avaliação da lógica do processo. Se isso faz sentido para você, ótimo; caso contrário, ajustaremos conforme necessário.

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

total_avioes = 3
total_estacionamentos = 3
total_tempo = 5

Temos esses três valores, agora o que falta criar é a variável X, é aquela nossa matriz de três dimensões, vamos fazer os vários for. O primeiro for que faremos é o for no número de aviões, no [for i in range(total_avioes)].

Por quê? Porque quando chamamos o X, desejamos que a primeira dimensão, o primeiro colchete, seja o avião ( o mais importante). Logo, queremos que seja primeiro o avião.

Após escolhermos o avião, nos deparamos com os estacionamentos e o tempo. Se fizermos isso, e passarmos que para cada um desses valores, criaremos uma variável modelo.NewBoolVar, uma nova variável booleana, 0 ou 1, e o nome dessa variável será aviao_{i}. Estamos criando uma matriz de uma dimensão, que terá tamanho 3.

Podemos tentar imprimir o X para verificar o resultado com print(X).

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

total_avioes = 3
total_estacionamentos = 3
total_tempo = 5

X = [modelo.NewBoolVar(f'aviao_{i}') for i in range(total_avioes)]

print(X)

Obtemos como retorno:

[aviao_0(0..1), aviao_1(0..1), aviao_2(0..1)]

Temos como retorno o avião 0, o avião 1 e o avião 2. Até aqui, tudo bem. O que fazíamos antes é que fazíamos mais um for. Depois que fizemos esse for i in range(total_avioes, adicionamos mais um colchete para adicionar mais um for. Teclamos "Enter" para ficar mais claro, for j in range(total_estacionamentos).

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

total_avioes = 3
total_estacionamentos = 3
total_tempo = 5

X = [[modelo.NewBoolVar(f'aviao_{i}')
for j in range(total_estacionamentos)]
for i in range(total_avioes)]

print(X)

Vamos rodar.

O retorno abaixo foi parcialmente transcrito. Para conferi-lo na íntegra, execute o código na sua máquina.

[[aviao_0(0..1), aviao_0(0..1), aviao_0(0..1)], [aviao_1(0..1), aviao_1(0..1), aviao_1(0..1)],…

Então, agora temos uma matriz 3 por 3. Na primeira matriz, 3 por 3, temos o avião_0, mas calma aí, avião_0 está no estacionamento j. Então dentro do NewBoolVar() incluímos _estacionamento_{j}.

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

total_avioes = 3
total_estacionamentos = 3
total_tempo = 5

X = [[modelo.NewBoolVar(f'aviao_{i}_estacionamento_{j}')
for j in range(total_estacionamentos)]
for i in range(total_avioes)]

print(X)

Vamos rodar a célula. Obtemos:

O retorno abaixo foi parcialmente transcrito. Para conferi-lo na íntegra, execute o código na sua máquina.

[[aviao_0_estacionamento_0(0..1), aviao_0_estacionamento_1(0..1), aviao_0_estacionamento_2(0..1)], [aviao_1_estacionamento 0(0..1), aviao_1_estacionamento_1(0..1),…

O Avião_0 está no estacionamento 0, avião_0 no estacionamento 1, avião_0 no estacionamento 2. Essa é a primeira matriz. A segunda, que é a primeira linha, a segunda são avião_1 no estacionamento 0, avião_1 no estacionamento 1 e assim por diante.

Então, 3 de tamanho 3 dá um resultado de 3 por 3, que é o que tínhamos antes. O que queremos agora é adicionar mais um colchete, porque é mais uma dimensão. Neste novo colchete, vamos fazer for k in range(total_tempo).

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

total_avioes = 3
total_estacionamentos = 3
total_tempo = 5

X = [[[modelo.NewBoolVar(f'aviao_{i}_estacionamento_{j}')
for k  in range(total_tempo)]
for j in range(total_estacionamentos)]
for i in range(total_avioes)]

print(X)

Rodamos e agora tem um monte. Faltou o nome também. Avião no estacionamento, e o tempo k.

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

total_avioes = 3
total_estacionamentos = 3
total_tempo = 5

X = [[[modelo.NewBoolVar(f'aviao_{i}_estacionamento_{j}_tempo_[k]')
for k  in range(total_tempo)]
for j in range(total_estacionamentos)]
for i in range(total_avioes)]

print(X)

Vamos verificar?

O retorno abaixo foi parcialmente transcrito. Para conferi-lo na íntegra, execute o código na sua máquina.

[[[aviao_0_estacionamento_0_tempo_0(0..1), aviao_0_estacionamento_0_tempo_1(0..1),…

Avião_0 no estacionamento 0 no tempo 0, avião_0 no estacionamento 0 no tempo 1, avião_0 no estacionamento 0 no tempo 2, e por aí vai. Avião_0 no estacionamento 0 no tempo 5, até chegar no avião_2 no estacionamento 2 no tempo 4, porque lembra que começa com 0? Então, 2, 2, 4. Está lá, matriz de 3 dimensões.

Como pensamos nessas três dimensões? Na nossa perspectiva, a primeira é o avião, então temos tamanho 3. A segunda, estacionamento, também tem tamanho 3. Já a terceira dimensão é o tempo, com tamanho 5.

Portanto, 3 por 3 por 5. Estamos considerando o mesmo conceito que pensar em três matrizes de 3 por 5, mais ou menos nesse sentido. A forma como queremos abordar isso não faz diferença para nós.

Então, temos o X. O que falta agora para nós é imprimir a solução. Precisamos tentar solucionar e imprimir a solução. Chamamos a função resolve, resolve(solucionador, modelo,X) após o print(x).

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

total_avioes = 3
total_estacionamentos = 3
total_tempo = 5

X = [[[modelo.NewBoolVar(f'aviao_{i}_estacionamento_{j}_tempo_[k]')
for k  in range(total_tempo)]
for j in range(total_estacionamentos)]
for i in range(total_avioes)]

print(X)
resolve(solucionador, modelo, X)

Rodamosa célula:

O retorno abaixo foi parcialmente transcrito. Para conferi-lo na íntegra, execute o código na sua máquina.

status: 4

Optimal

Achamos uma solução, ótimo, maravilha, encontramos.

Que solução é essa? Vamos imprimir a solução. Entretanto, imprimir a solução é mais complicado. Porque teremos que fazer um for para cada avião. Ou seja, para cada um dos aviões, utilizaremos for i in range(total_avioes):. Se quisermos seguir dessa maneira, iremos percorrer cada um dos totais de aviões.

def resolve(solucionador, modelo, X):
status = solucionador.Solve(modelo)
print(f"Status: {status}")

if status == cp_model.OPTIMAL: 
print("Optimal")
for i in range(total_avioes):
else:
print("Solução não encontrada")

Mas a variável total_avioes está global? Lembra que, no nosso código, tínhamos enumerado a nossa pequena matriz. Aplicamos essa mesma lógica. Em vez de ter que ficar recebendo a variável total_avioes, etc., nós sabemos que a primeira dimensão tem tamanho 3, no caso, é o avião.

Então, for i, que é o contador, 0, 1, 2, vírgula. O que temos dentro dela? Se escolhemos o avião zero, o que é o X[0]? Lembre-se, a primeira dimensão é o avião. Se já escolhemos o avião, resta uma matriz de tamanho de estacionamentos por tempo. Temos uma matriz de tamanho 3 por 5. Vamos testar isso, o print. Em vez de imprimir o X, vamos imprimir o X[0] do avião zero. Comentaremos a seguinte linha.

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

total_avioes = 3
total_estacionamentos = 3
total_tempo = 5

X = [[[modelo.NewBoolVar(f'aviao_{i}_estacionamento_{j}_tempo_[k]')
for k  in range(total_tempo)]
for j in range(total_estacionamentos)]
for i in range(total_avioes)]

print(X[0])
#resolve(solucionador, modelo, X)

Quando imprimirmos o X[0], obtemos:

[[aviao_estacionamento_0_tempo_0(0..1), aviao_0_estacionamento_0_tempo_1(0..1),…

Observem que é uma matriz de tamanho avião_0_0_0, avião_0_0_1, avião_0_0_2, avião_0_0_3, avião_0_0_4, acabou. Então, ela tem 5 colunas. E quantas linhas? A segunda linha e a terceira linha. Portanto, é uma matriz de 3 por 5. Podemos imprimir os vários len, podemos imprimir o tamanho do X. O tamanho do X tem que ser 3, por quê? Porque são 3 aviões, primeira dimensão.

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

total_avioes = 3
total_estacionamentos = 3
total_tempo = 5

X = [[[modelo.NewBoolVar(f'aviao_{i}_estacionamento_{j}_tempo_[k]')
for k  in range(total_tempo)]
for j in range(total_estacionamentos)]
for i in range(total_avioes)]

print(len(X))
#resolve(solucionador, modelo, X)

Obtemos:

3

O tamanho do len(X[0]) indica que pegamos o primeiro avião, e agora temos apenas para esse avião.

modelo = cp_model.CpModel()
solucionador = cp_model.CpSolver()

total_avioes = 3
total_estacionamentos = 3
total_tempo = 5

X = [[[modelo.NewBoolVar(f'aviao_{i}_estacionamento_{j}_tempo_[k]')
for k  in range(total_tempo)]
for j in range(total_estacionamentos)]
for i in range(total_avioes)]

print(len(X))
print(len(X[0]))
#resolve(solucionador, modelo, X)

Ao rodarmos a célula:

3

3

Possuímos, novamente, 3, que correspondem aos estacionamentos. No caso do avião zero, no estacionamento zero, quantas variáveis foram criadas? Para verificar, digitamos print(len(X[0][0])) após o último print() e rodamos a célula.

3

3

5

São 5, resultantes de 3 por 3 por 5. Essa é a explicação quando escolhemos o X[0], que é uma matriz de 3 por 5.

Vamos voltar para a seguinte célula:

def resolve(solucionador, modelo, X):
status = solucionador.Solve(modelo)
print(f"Status: {status}")

if status == cp_model.OPTIMAL: 
print("Optimal")
for i, matriz_estacionamento_tempo in enumerate(X):

else:
print("Solução não encontrada")

Após o for i adicionamos uma vírgula e colocamos o estacionamento no tempo. matriz_estacionamento_tempo. Cada um desses representa um dos aviões. Agora, precisamos buscar onde há o número 1. Continuaremos procurando com o for j, onde cada iteração refere-se a uma das janelas de tempo, utilizando tempos in enumerate(matriz_estacionamento_tempo):.

def resolve(solucionador, modelo, X):
status = solucionador.Solve(modelo)
print(f"Status: {status}")

if status == cp_model.OPTIMAL: 
print("Optimal")
for i, matriz_estacionamento_tempo in enumerate(X):
for j, tempos in enumerate(matriz_estacionamento_tempo):

else:
print("Solução não encontrada")

Inicialmente, havia 3, e faremos um for de tamanho 3. O mesmo vale para o for inferior, que também é de tamanho 3 no nosso caso, referindo-se aos 3 estacionamentos. Assim, o j assumirá valores de 0, 1 ou 2, e para cada um desses 3 tempos, temos uma matriz de tamanho 3.

Faremos para cada um do tempo, for k, variavel in enumerate(tempos), agora temos cada um deles. Precisamos pegar o valor, sendo o solucionador.Value(variavel).

def resolve(solucionador, modelo, X):
status = solucionador.Solve(modelo)
print(f"Status: {status}")

if status == cp_model.OPTIMAL: 
print("Optimal")
for i, matriz_estacionamento_tempo in enumerate(X):
for j, tempos in enumerate(matriz_estacionamento_tempo):
for k, variavel in enumerate(tempos):
valor = solucionador.Value(variavel)

else:
print("Solução não encontrada")

Analisando no notebook antigo, percebam que a diferença é que colocamos mais um for. Logo, fizemos mais um for, esse é o valor. Voltando à célula atual, digitamos: se o valor for 1 (if valor ==1: ), então achamos, print(f'Avião {i} no estacionamento {j} no tempo {k}'), é isso que encontramos.

def resolve(solucionador, modelo, X):
status = solucionador.Solve(modelo)
print(f"Status: {status}")

if status == cp_model.OPTIMAL: 
print("Optimal")
for i, matriz_estacionamento_tempo in enumerate(X):
for j, tempos in enumerate(matriz_estacionamento_tempo):
for k, variavel in enumerate(tempos):
valor = solucionador.Value(variavel)
if valor ==1:
print(f'Avião {i} no estacionamento {j} no tempo {k}')

else:
print("Solução não encontrada")

Abordaremos cada avião, estacionamento e intervalo de tempo. Se o valor for 1, imprimiremos. Vamos testar; esquecemos de chamar a função resolve. Vamos remover o comentário do resolve(solucionador, modelo, X).

Obtemos como retorno:

3

3

5

Status:4

Optimal

Após executar, imprimiu o status 4, e tudo deve estar 0. A única solução que encontramos é que tudo está 0.

Como podemos ter certeza? Vamos comentar o if valor ==1: e imprimir tudo.

3

3

5

Status:4

Optimal

Avião no estacionamento no tempo 0

Avião e no estacionamento no tempo 1

Avião e no estacionamento e no tempo 2

Avião e no estacionamento no tempo 3

Agora, está tudo lá, pois nenhum valor é 1. Quer dizer, está tudo 0; não está 1. Não há nenhum problema, pois ainda não aplicamos nenhuma restrição. Já temos uma matriz de 3 dimensões e adaptamos nosso código para ela.

Próximo passo: colocar restrições. Estas vão trabalhar em cima do que já conhecemos.

Vamos lá!

Sobre o curso IA aumentada: adicionando a dimensão de tempo ao problema de voos

O curso IA aumentada: adicionando a dimensão de tempo ao problema de voos possui 132 minutos de vídeos, em um total de 43 atividades. Gostou? Conheça nossos outros cursos de Machine Learning em Data Science, ou leia nossos artigos de Data Science.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Machine Learning acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas