add eoEvalNamedPipe
- a class to connect an external objective function through file(s) - fix doc error in eoEvalCmd
This commit is contained in:
parent
9623f4d1f8
commit
6232ff2f21
3 changed files with 122 additions and 3 deletions
|
|
@ -74,6 +74,7 @@
|
|||
|
||||
// Evaluation functions (all include eoEvalFunc.h)
|
||||
#include "eoPopEvalFunc.h"
|
||||
#include "eoEvalNamedPipe.h"
|
||||
#include "eoEvalCmd.h"
|
||||
#include "eoEvalCounterThrowException.h"
|
||||
#include "eoEvalDump.h"
|
||||
|
|
|
|||
|
|
@ -38,9 +38,7 @@ Johann Dréo <johann.dreo@thalesgroup.com>
|
|||
* Use the default string serialization of the EOT
|
||||
* and pass it as command line arguments of the command.
|
||||
* The command is expected to output on stdout a string
|
||||
* that can be interpreted as a float by `atof`.
|
||||
*
|
||||
* @todo Use the serialization of fitness instead of atof.
|
||||
* that can be deserialized as a fitness.
|
||||
*
|
||||
* For example, an eoReal would lead to a call like:
|
||||
* ```>&2 cmd INVALID 3 1.0 2.1 3.2```
|
||||
|
|
|
|||
120
eo/src/eoEvalNamedPipe.h
Normal file
120
eo/src/eoEvalNamedPipe.h
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
(c) Thales group, 2020
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation;
|
||||
version 2 of the License.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Contact: http://eodev.sourceforge.net
|
||||
|
||||
Authors:
|
||||
Johann Dréo <johann.dreo@thalesgroup.com>
|
||||
*/
|
||||
|
||||
#ifndef eoEvalNamedPipe_H
|
||||
#define eoEvalNamedPipe_H
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <cstdlib>
|
||||
#include <array>
|
||||
|
||||
#include "eoEvalFunc.h"
|
||||
#include "eoExceptions.h"
|
||||
|
||||
/** Communicate through a named pipe FIFO to evaluate an individual.
|
||||
*
|
||||
* With this class, you can plug an external process computing the fitness
|
||||
* of a serialized solution with a process hosting the EO algorithm.
|
||||
* Both processes just have to read/write solutions/fitness in files.
|
||||
*
|
||||
* The code would work with any file, but it is actually only useful with
|
||||
* FIFO pipes, which are blocking on I/O.
|
||||
* Thus, the process actually computing the fitness will ait for the solution to be wrote,
|
||||
* then compute and write the fitness back, waiting it to be read.
|
||||
* Conversely, the EO process will wait after having wrote the solution, that the other process
|
||||
* actually read it, then wait itself for the fitness to be read in the pipe.
|
||||
* With pipes, the synchronization of the two processes is guaranteed.
|
||||
*
|
||||
* To create a named FIFO pipe under Linux, see the command `mkfifo`.
|
||||
*
|
||||
* @note: if you use a single pipe for input/output, take care
|
||||
* of the synchronization with the process handling the fitness computation.
|
||||
* In particular, the first call of eoEvalNamedPipe
|
||||
* is to write the solution, THEN to read the fitness.
|
||||
*
|
||||
* @note Tested only under Unix systems, may not be portable as is.
|
||||
*
|
||||
* Use the default string serialization of the EOT and
|
||||
* the default deserialization of the fitness.
|
||||
*
|
||||
*@ingroup Evaluation
|
||||
*/
|
||||
template<class EOT>
|
||||
class eoEvalNamedPipe : public eoEvalFunc< EOT >
|
||||
{
|
||||
public:
|
||||
using Fitness = typename EOT::Fitness;
|
||||
|
||||
/** Constructor
|
||||
*
|
||||
* @param output_pipe_name The named pipe in which to write the serialized solution.
|
||||
* @param input_pipe_name The named pipe in which to read the serialized fitness. If it is "", use the output pipe.
|
||||
*/
|
||||
eoEvalNamedPipe(
|
||||
const std::string output_pipe_name,
|
||||
const std::string input_pipe_name = ""
|
||||
) :
|
||||
_output_pipe_name(output_pipe_name),
|
||||
_input_pipe_name(input_pipe_name)
|
||||
{
|
||||
if( _input_pipe_name == "") {
|
||||
_input_pipe_name = _output_pipe_name;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void operator()( EOT& sol )
|
||||
{
|
||||
// Any modification to sol would makes it invalid,
|
||||
// it is thus useless to evaluate it, if it is not invalid.
|
||||
if(not sol.invalid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
sol.fitness( call( sol ) );
|
||||
}
|
||||
|
||||
private:
|
||||
const std::string _output_pipe_name;
|
||||
std::string _input_pipe_name;
|
||||
|
||||
Fitness call( EOT& sol )
|
||||
{
|
||||
// Write the passed solution.
|
||||
std::ofstream out(_output_pipe_name);
|
||||
out << sol << std::endl;
|
||||
out.close();
|
||||
|
||||
// Read the output string in a valid fitness object.
|
||||
Fitness fit;
|
||||
std::ifstream if_fit(_input_pipe_name);
|
||||
std::stringstream ss_fit;
|
||||
ss_fit << if_fit.rdbuf();
|
||||
if_fit.close();
|
||||
ss_fit >> fit;
|
||||
|
||||
return fit;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // eoEvalNamedPipe_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue