Platypus icon indicating copy to clipboard operation
Platypus copied to clipboard

Example/document for interfacing external evaluatior through file I/O

Open athlonshi opened this issue 6 years ago • 4 comments

If the evaluatior is an external excutable program, platypus may take the objectives from the external program by reading the program output and then generate inputs to a text file for the next batch of evaluation by running the program. It is not clear how to achieve this by defining a new class inheriting the Problem class. An example or detailed documentation will be very helpful. Also, it would be better that the run method allows callback, so one can monitor the progress after each generation. Thanks.

athlonshi avatar May 08 '18 02:05 athlonshi

Hi, thanks for the question and feedback. To call an external program, your evaluation function would look something like:


def call_external(vars):
    # Write vars to input.txt

    # Call the program
    subprocess.call(["extProgram.exe", "-i", "input.txt", "-o", "output.txt"])

    # Read the objectives from output.txt
    objs = ...

    return objs

It gets a little bit more complicated if you want to parallelize the evaluations since you need to ensure the filenames used by each thread/process are unique.

The run method does take a callback argument that is called once per iteration. It takes a single argument, the algorithm, which lets you access the current NFE, population, etc.:


algorithm.run(10000, callback = lambda a : print("Finished iteration. NFE:", a.nfe))

Alternatively, you can use the built-in logger to track progress:


import sys
import logging
from platypus import NSGAII, DTLZ2

logging.basicConfig(stream=sys.stdout, level=logging.INFO)

problem = DTLZ2()

algorithm = NSGAII(problem, log_frequency=100)
algorithm.run(10000)

for solution in algorithm.result:
    print(solution.objectives)

Note that you must both enable the logger by calling logger.basicConfig(...) AND set log_frequency for the log messages to display.

INFO:Platypus:NSGAII starting
INFO:Platypus:NSGAII running; NFE Complete: 100, Elapsed Time: 0:00:00.004999
INFO:Platypus:NSGAII running; NFE Complete: 200, Elapsed Time: 0:00:00.065000
INFO:Platypus:NSGAII running; NFE Complete: 300, Elapsed Time: 0:00:00.114025
INFO:Platypus:NSGAII running; NFE Complete: 400, Elapsed Time: 0:00:00.163500
INFO:Platypus:NSGAII running; NFE Complete: 500, Elapsed Time: 0:00:00.213500
INFO:Platypus:NSGAII running; NFE Complete: 600, Elapsed Time: 0:00:00.260503
INFO:Platypus:NSGAII running; NFE Complete: 700, Elapsed Time: 0:00:00.306002
...

dhadka avatar May 08 '18 18:05 dhadka

Thank you. I made a quick demo and it works.

class Schaffer_external(Problem):

def __init__(self):
    super().__init__(1, 2)
    self.types[:] = Real(-10, 10)

def evaluate(self, solution):
    x = solution.variables[:]
    with open('input.txt', 'w') as f:
        f.write(' '.join([str(s) for s in x]))
    os.system('./Schaffer.exe < input.txt > output.txt')
    with open('output.txt', 'r') as f:
        solution.objectives[:] = [float(obj) for obj in f.readline().strip().split()]

The Fortran code to make the executable Schaffer.exe is here

program schaffer read(5, *)x y1 = x ** 2 y2 = (x - 2) ** 2 write(6, *)y1, y2 end program schaffer gfortran Schaffer.f -o Schaffer.exe to compile

athlonshi avatar May 08 '18 20:05 athlonshi

Now I need to figure out parallel tasks. Does Platypus run population in each generation in parallel? If so, what parameter I can use from the solution object to distinguish each sibling of a generation? Thanks.

athlonshi avatar May 08 '18 20:05 athlonshi

In parallel case, is there anyway I can send the process number (population number) to the problem evaluator? If so, I can create files with different names corresponding to different population. Thanks!

athlonshi avatar May 10 '18 17:05 athlonshi

This issue is stale and will be closed soon. If you feel this issue is still relevant, please comment to keep it active. Please also consider working on a fix and submitting a PR.

github-actions[bot] avatar Nov 13 '22 03:11 github-actions[bot]