nnaisense / evotorch

Advanced evolutionary computation library built directly on top of PyTorch, created at NNAISENSE.
https://evotorch.ai
Apache License 2.0
1.01k stars 63 forks source link

Unable to solve for integer decision variables #23

Closed this-josh closed 2 years ago

this-josh commented 2 years ago

I have a problem which requires an integer solution, when running my searcher I get the error RuntimeError: "normal_kernel_cpu" not implemented for 'Int'

Here is an example, if dtype=torch.float it works fine, and torch.prod(torch.tensor([2,3], dtype=torch.int)) works as expected.

import torch
from evotorch import Problem
from evotorch.algorithms import SNES
from evotorch.logging import StdOutLogger

def prod(x: torch.Tensor) -> torch.Tensor:
  return torch.prod(x,dim=-1)

problem = Problem(
"min",
prod,
initial_bounds=(-10, 10),
solution_length=100,
vectorized=True,
dtype=torch.int,
)

searcher = SNES(problem, popsize=1000, stdev_init=10)
_ = StdOutLogger(searcher, interval=50)

searcher.run(num_generations=100)

I've got the same error on Red Hat Linux and my M1 Mac, with python 3.9 and 3.10 and evotorch 0.2.0.

flukeskywalker commented 2 years ago

The reason for this error is that SNES is a distribution-based search algorithm, which is designed for real-valued variables. For discrete variables, you can use a genetic algorithm through SteadyStateGA, by defining crossover and mutation operators for your solution type (EvoTorch has some built-in operators for real-coded solutions only currently, so you will need to define these for now) to be used. Once you've defined operators to do crossover and mutation, you can use them like this:

ga = evotorch.algorithms.SteadyStateGA(problem, popsize=...)
ga.use(MyCrossover(problem, arg1=..., arg2=...,))
ga.use(MyMutation(problem, arg1=...))

If you face any issues implementing these operators let us know and we'll try to help!

this-josh commented 2 years ago

I see thank you for your clear and detailed explanation. I did try SteadyStateGA but got the same errors, from your description I expected these came from the built-in operators I was using. I'll have a think about whether I should implement some additional operators. For now I'll close this ticket.