---
# System prepended metadata

title: Notas para CheckPoint 1

---

**Edit** : Aceitar soluções não válidas e aplicar uma penalização.

# Notas para CheckPoint 1

## 1) Definição do problema

Num mapa x por y existem armazéns ...

## 2) Trabalhos relacionados

- Kaggle de 2020 com o problema de 2016, da Google: https://www.kaggle.com/c/hashcode-drone-delivery
- Solução de primeiro lugar usando Scala: https://www.kaggle.com/lyxthe/1st-place-solution | https://github.com/miraan/google-hash-code-qualification-round
- Segundo lugar, python: https://www.kaggle.com/royceda/drone-linear-prog-and-routing-heuristic-90-done
- Outra solução usando Python: https://www.kaggle.com/spacelx/2020-hc-dd-2nd-place-solution-w-or-tools

Problema é semelhante a um CVRP (Capacitated Vehicle Routing Problem)

- Google OR-Tools para VRP e CVRP: https://developers.google.com/optimization/routing/vrp | https://developers.google.com/optimization/routing/cvrp
    - Também se adicionar "Pickup and deliveries": https://developers.google.com/optimization/routing/pickup_delivery
- LocalSolver : https://www.localsolver.com/benchmarkcvrp.html | https://www.localsolver.com/docs/last/exampletour/vrp.html

- CVRPPAD - https://link.springer.com/article/10.1007/s10479-017-2722-x | https://link.springer.com/content/pdf/10.1007/s10479-017-2722-x.pdf

- Genetic Algorithm :
    - A genetic algorithm based approach to vehicle routing problem with simultaneous pick-up and deliveries (2011): https://www.sciencedirect.com/science/article/pii/S0360835211003482
    - A vehicle routing problem solved by using a hybrid genetic algorithm (2007) [Gene WTF]: https://www.sciencedirect.com/science/article/pii/S0360835207001222
    - Waiting strategy for the vehicle routing problem with simultaneous pickup and delivery using genetic algorithm (2020) [Bom Gene]: https://www.sciencedirect.com/science/article/pii/S0957417420307429
    - Ainda para checkar (2005): https://www.sciencedirect.com/science/article/pii/S0952197607000887

## 3) Formulação do problema

### Representação da Solução
![](https://i.imgur.com/R4EnsPD.png)

Node <- Indice do WareHouse ou indice da order

Dois tipos de alelos, entrega e _pick-up_. Entrega com valores de Demand a negativo e _pick-up_ com valores positivos. 

Formação de soluções iniciais: Os alelos de entrega são obrigatórios, os de pick-up são até uma certain extent.

Criar solução inicial que obedeça a constraints e assegura que todas as orders são entregues, mesmo que fiquem com baixa pontuação:
```python
P -> Product
Pq -> Quantidade de Produto
Pr -> Resto de Produto
WH -> WareHouse
WHn -> WareHouse node
A -> Alelo
Ap -> Alelo pickup
Ad -> Alelo Deliver
Dc -> Drone capacity
Da -> Lista de alelos deliver
Rp -> remainder product

-- Formar alelos:
-- Na criação de lista de alelos deliver, se mod(demand) > Dc, cria [2, inf] alelos 
-- para a mesma delivery com quantidades diferentes.

Da[] <- CreateList(Orders)
For each Ad in Da[]:
    Pr <- Ad.Quantity
    for WH in WH[]:
        If WH has P
            N <- calculateProduct(Pr) //available vs needed, updates Pr
            Ap <- alelo (_, Pq, WHn, N)
            Cromossoma.push(Ap)
            if Pr == 0:
                break
    Remove WH's with 0 products
    Cromossoma.push(Ad)

calculateProduct(needed):
    if available == needed
        internal value = 0
        needed = 0
        returns needed
    elif available > needed
        updates internal amount -> available - needed 
        needed = 0
        returns needed
    elif needed > available
        internal value = 0
        needed = needed - available
        returns needed
    
-- Formar cromossoma solution:

index <- 1
For each A in Cromossoma:
    assign drone with index
    if A is Deliver
        index++
    if index > nº Drones
        index <- 1

-- Para cada alelo de delivery, drone fica com alelos anteriores de pick up. 
-- Quando ficar sem drones recomeça.
```
:::info
Outra solução possivel, usando o método acima, começar pelos WH de indice superior.
:::


Soluções aleatórias (GA):

2 partes:
- Formação de alelos
- Formação de locus/genes

Cria-se configuração de alelos, tenta-se povoar locus x vezes. Se não der nenhuma solução fazível, forma-se outra configuração de alelos.
```python
-- Na criação de lista de alelos deliver, se mod(demand) > Dc, 
-- cria [2, inf] alelos para a mesma delivery com quantidades diferentes.

WH[] <- Vai sendo modificada, retirando produtos e quantidades. 
Quando WH ficar vazio, retira-se da lista

while Da[] not empty
    if rdm() > 0.5 // adiciona Deliver allele
        Ad <- rdm(Da[])
        D <- rdm(Drone)
        if checkConstraints() || 0
            cromossoma.push(D,Ad)
    else 
        if WH[] empty
            continue
        WH <- rdm(WH[])
        P <- rdm(WH)
        Pq <- rdm(P[WH])
        D <- rdm(Drone) || 0
        if checkConstraint()
            cromossoma.push(D, Pq, WHn, P)

-- Pode acontecer de que vai sendo criada uma solução cuja qualquer adição não obedeça a constraints
-- Neste caso, ou se refaz a árvore, ou se retira n genes recentemente adicionados do cromossa (backtrack) e não se aplia o mesmo gene outra vez na mesma posição
-- also, pode-se adicionar um drone 0 em vez de um id válido, significa que esse gene fica disponivel para ser alcançado mas não tem um drone. Genes deliver também podem ter 0, já que todas as orders não precisam de ser completas

```

### Neighborhood/Mutation 

#### Mutações nos cromossomas

- Trocar drones de 2 alelos para alterar trajetos (funciona com drones nulos)
- 2 alelos do mesmo WH e item -> desiquilibrar as quantidades
- Adiciona genes de Supply: Caso haja items em WH que não estão a ser picked up, adiciona esse gene com quantidade aleatória entre [1, min(Pq,Dc)] e drone nulo
- Junta 2 genes de deliver num mesmo, ficando na posição do primeiro, com um dos drones, escolhido aleatório
- Junta 2 genes de deliver num mesmo, ficando na posição do segundo, com um dos drones, escolhido aleatório
- Junta 2 genes de supplier num mesmo, ficando na posição do primeiro, com um dos drones, escolhido aleatório
- Junta 2 genes de supplier num mesmo, ficando na posição do segundo, com um dos drones, escolhido aleatório

#### Mutações nos genes

- Dividir um alelo de supplier em 2 com quantidades iguais
- Dividir um alelo de supplier em 2 com quantidades desiguais
- Pôr um gene com drone None

### Crossover functions

![](https://i.imgur.com/vWT1Rby.png)

Provoca alterações nas rotas dos drones. Por exemplo, um drone que enche e só envia muito depois pode ficar livre mais cedo ou entregar mais perto.

### Rigid constraints

- Caminho de drone não pode ultrapassar os turnos previstos
```
Vendo os genes de cada drone
Começando no primeiro gene, busca o segundo e guarda os nós de cada
Calcula a distância entre os nós, adiciona 1
Guarda esse valor num somatório
Quando chegar ao último gene, acaba
Verifica se valor de somatório é < que nº de turnos
```
- Drone não pode ter mais carga que a capacidade/carga negativa
```
Vendo os genes de cada drone
CargaAtual <- 0
Por cada gene
    Atualiza valor da carga com o valor da demand
    Se carga atual for > carga drone ou < 0 -> not feasible
```

- Drone só pode entregar produtos que tem (id e quantidade)
```
Para cada drone
Para cada gene desse drone
  Atualiza lista de produtos (id's e quantidade) em cada gene
  Se entrega um produto que não possui -> not feasible
```

- X Drone não pode retirar de um armazém mais quantidade do que a que o WH tem disponivel
```
Vendo os genes de cada armazém
Por cada gene:
    Atualiza valor de produto
    se quantidade de qualquer produto < 0 -> not feasible
```

- X Drone não pode levantar produtos de Customer nodes, apenas WH
```
Para cada gene
    Ver Node e determinar se é WH ou Customer
    Ver Demand
    Se Demand não corresponder ao tipo -> not feasible
```

- X Nenhuma order recebe mais produto do que o previsto
```
Para cada node de customer
Verifica quantidaeds recebidas e atualiza o que ainda precisa de receber
Se valor ficar negativo (recebeu a mais) -> not-feasible
```


### Evaluation functions

Cada order pode ter entre 1 e 100 pontos. Tendo n orders, o máximo total possível de pontos é 100*n. De acordo com o enunciado, a order fica completa quando o último item é entregue

Somatório da pontuação de todas as orders / 100*n -> [0,1]

Q: Como determinar se uma encomenda foi concluida?

A: Verificar se todos os genes de uma certa encomenda contêm drones associados, se sim, então foi realizada, já que obedece às restrições.

Q: Como determinar ultimo turn de uma encomenda?

A: Ver os genes de cada drone e criar uma lista de pares Ação-IntervaloDeTurnos, com as seguintes ações:
- PickUp
    - Andamento + 1 - PA
- Deliver
    - Andamento + 1 - DA

Exemplo Drone1:
PA - 1-6 (5 de andamento + 1 pickup)
PA - 7 (pickup apenas)
PE - 8-12 (4 de andamento + 1 delivery)
PE - 13 (apenas delivery)


## 4) Trabalho feito até agora

Parsing