MOEAFramework-3.7.examples.moeaframework.c Maven / Gradle / Ivy
/* Copyright 2009-2023 David Hadka
*
* This file is part of the MOEA Framework.
*
* The MOEA Framework 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, either version 3 of the License, or (at your
* option) any later version.
*
* The MOEA Framework 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 the MOEA Framework. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include "moeaframework.h"
#ifdef MOEA_SOCKETS
# include
# include
# include
# include
#endif
#define MOEA_WHITESPACE " \t"
#define MOEA_INITIAL_BUFFER_SIZE 1024
#define MOEA_DEFAULT_PORT "16801"
FILE* MOEA_Stream_input = NULL;
FILE* MOEA_Stream_output = NULL;
FILE* MOEA_Stream_error = NULL;
int MOEA_Number_objectives;
int MOEA_Number_constraints;
char* MOEA_Line_buffer = NULL;
size_t MOEA_Line_position = 0;
size_t MOEA_Line_limit = 0;
void MOEA_Error_callback_default(const MOEA_Status status) {
MOEA_Debug("%s\n", MOEA_Status_message(status));
MOEA_Terminate();
exit(EXIT_FAILURE);
}
void (*MOEA_Error_callback)(const MOEA_Status) = MOEA_Error_callback_default;
const char* MOEA_Status_message(const MOEA_Status status) {
switch (status) {
case MOEA_SUCCESS:
return "Success";
case MOEA_EOF:
return "Finished";
case MOEA_PARSE_NO_SOLUTION:
return "No solution read, missing call to MOEA_Next_solution()";
case MOEA_PARSE_EOL:
return "Attempted to parse variable but at end-of-line";
case MOEA_PARSE_DOUBLE_ERROR:
return "Unable to parse double variable";
case MOEA_PARSE_BINARY_ERROR:
return "Unable to parse binary variable";
case MOEA_PARSE_PERMUTATION_ERROR:
return "Unable to parse permutation variable";
case MOEA_MALLOC_ERROR:
return "Error while allocating memory";
case MOEA_NULL_POINTER_ERROR:
return "Attempted to dereference NULL pointer";
case MOEA_SOCKET_ERROR:
return "Unable to establish socket connection";
case MOEA_IO_ERROR:
return "Unable to read/write from stream";
default:
return "Unknown error";
}
}
MOEA_Status MOEA_Error(const MOEA_Status status) {
if ((status == MOEA_SUCCESS) || (status == MOEA_EOF)) {
return status;
} else if (MOEA_Error_callback == NULL) {
return status;
} else {
MOEA_Error_callback(status);
return status;
}
}
MOEA_Status MOEA_Init(const int objectives, const int constraints) {
MOEA_Stream_input = stdin;
MOEA_Stream_output = stdout;
MOEA_Stream_error = stderr;
MOEA_Number_objectives = objectives;
MOEA_Number_constraints = constraints;
return MOEA_SUCCESS;
}
#ifdef MOEA_SOCKETS
MOEA_Status MOEA_Init_socket(const int objectives, const int constraints,
const char* service) {
int gai_errno;
int listenfd;
int readfd;
int writefd;
int yes = 1;
struct addrinfo hints;
struct addrinfo *servinfo = NULL;
struct addrinfo *sp = NULL;
struct sockaddr_storage their_addr;
socklen_t addr_size = sizeof(their_addr);
MOEA_Init(objectives, constraints);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if (service == NULL) {
service = MOEA_DEFAULT_PORT;
}
if ((gai_errno = getaddrinfo(NULL, service, &hints, &servinfo)) != 0) {
MOEA_Debug("getaddrinfo: %s\n", gai_strerror(gai_errno));
return MOEA_Error(MOEA_SOCKET_ERROR);
}
for (sp = servinfo; sp != NULL; sp = sp->ai_next) {
if ((listenfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
MOEA_Debug("socket: %s\n", strerror(errno));
continue;
}
/* enable socket reuse to avoid socket already in use errors */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
MOEA_Debug("setsockopt: %s\n", strerror(errno));
}
if (bind(listenfd, servinfo->ai_addr, servinfo->ai_addrlen) == -1) {
MOEA_Debug("bind: %s\n", strerror(errno));
close(listenfd);
continue;
}
break;
}
freeaddrinfo(servinfo);
if (sp == NULL) {
return MOEA_Error(MOEA_SOCKET_ERROR);
}
if (listen(listenfd, 1) == -1) {
MOEA_Debug("listen: %s\n", strerror(errno));
close(listenfd);
return MOEA_Error(MOEA_SOCKET_ERROR);
}
if ((readfd = accept(listenfd, (struct sockaddr*)&their_addr, &addr_size)) == -1) {
MOEA_Debug("accept: %s\n", strerror(errno));
close(listenfd);
return MOEA_Error(MOEA_SOCKET_ERROR);
}
close(listenfd);
if ((writefd = dup(readfd)) == -1) {
MOEA_Debug("dup: %s\n", strerror(errno));
close(readfd);
return MOEA_Error(MOEA_SOCKET_ERROR);
}
if ((MOEA_Stream_input = fdopen(readfd, "r")) == NULL) {
MOEA_Debug("fdopen: %s\n", strerror(errno));
close(readfd);
close(writefd);
return MOEA_Error(MOEA_SOCKET_ERROR);
}
if ((MOEA_Stream_output = fdopen(writefd, "w")) == NULL) {
MOEA_Debug("fdopen: %s\n", strerror(errno));
fclose(MOEA_Stream_input);
close(readfd);
close(writefd);
return MOEA_Error(MOEA_SOCKET_ERROR);
}
return MOEA_SUCCESS;
}
#endif
MOEA_Status MOEA_Debug(const char* format, ...) {
va_list arguments;
va_start(arguments, format);
vfprintf(MOEA_Stream_error, format, arguments);
fflush(MOEA_Stream_error);
va_end(arguments);
return MOEA_SUCCESS;
}
MOEA_Status MOEA_Next_solution() {
size_t position = 0;
int character;
if (feof(MOEA_Stream_input)) {
return MOEA_EOF;
}
while (!feof(MOEA_Stream_input)) {
/* increase line buffer if needed */
if ((MOEA_Line_limit == 0) || (position >= MOEA_Line_limit-1)) {
MOEA_Line_limit += MOEA_INITIAL_BUFFER_SIZE;
MOEA_Line_buffer = (char*)realloc(MOEA_Line_buffer,
MOEA_Line_limit*sizeof(char));
if (MOEA_Line_buffer == NULL) {
return MOEA_Error(MOEA_MALLOC_ERROR);
}
}
/* process next character */
character = fgetc(MOEA_Stream_input);
if ((character == EOF) || (character == '\r') || (character == '\n')) {
if (ferror(MOEA_Stream_input)) {
return MOEA_Error(MOEA_IO_ERROR);
}
MOEA_Line_buffer[position++] = '\0';
/* handle the windows-style \r\n newline */
if (character == '\r') {
character = fgetc(MOEA_Stream_input);
if ((character == EOF) && ferror(MOEA_Stream_input)) {
return MOEA_Error(MOEA_IO_ERROR);
} else if (character != '\n') {
if (ungetc(character, MOEA_Stream_input) != character) {
return MOEA_Error(MOEA_IO_ERROR);
}
}
}
break;
} else {
MOEA_Line_buffer[position++] = character;
}
}
MOEA_Line_position = 0;
if (position == 1) {
return MOEA_EOF;
} else {
return MOEA_SUCCESS;
}
}
MOEA_Status MOEA_Read_token(char** token) {
if (MOEA_Line_buffer == NULL) {
return MOEA_Error(MOEA_PARSE_NO_SOLUTION);
}
/* find start of next token (skipping any leading whitespace) */
MOEA_Line_position += strspn(MOEA_Line_buffer+MOEA_Line_position,
MOEA_WHITESPACE);
/* if this is the end of the line, signal an error */
if (MOEA_Line_buffer[MOEA_Line_position] == '\0') {
return MOEA_Error(MOEA_PARSE_EOL);
}
/* find end of token */
size_t end = strcspn(MOEA_Line_buffer+MOEA_Line_position, MOEA_WHITESPACE);
/* create token */
MOEA_Line_buffer[MOEA_Line_position+end] = '\0';
*token = MOEA_Line_buffer+MOEA_Line_position;
MOEA_Line_position += end + 1;
return MOEA_SUCCESS;
}
MOEA_Status MOEA_Read_binary(const int size, int* values) {
int i = 0;
char* token = NULL;
MOEA_Status status = MOEA_Read_token(&token);
if (status != MOEA_SUCCESS) {
return MOEA_Error(status);
}
while (1) {
if ((i < size) && (token[i] != '\0')) {
if (token[i] == '0') {
values[i] = 0;
} else if (token[i] == '1') {
values[i] = 1;
} else {
return MOEA_Error(MOEA_PARSE_BINARY_ERROR);
}
} else if ((i != size) || (token[i] != '\0')) {
return MOEA_Error(MOEA_PARSE_BINARY_ERROR);
} else {
break;
}
i++;
}
return MOEA_SUCCESS;
}
MOEA_Status MOEA_Read_permutation(const int size, int* values) {
int i;
char* token = NULL;
char* endptr = NULL;
MOEA_Status status = MOEA_Read_token(&token);
if (status != MOEA_SUCCESS) {
return MOEA_Error(status);
}
values[0] = strtol(token, &endptr, 10);
for (i=1; i 0)) ||
((constraints == NULL) && (MOEA_Number_constraints > 0))) {
return MOEA_Error(MOEA_NULL_POINTER_ERROR);
}
/* write objectives to output */
for (i=0; i 0) {
if (fprintf(MOEA_Stream_output, " ") < 0) {
return MOEA_Error(MOEA_IO_ERROR);
}
}
if (fprintf(MOEA_Stream_output, "%.17g", objectives[i]) < 0) {
return MOEA_Error(MOEA_IO_ERROR);
}
}
/* write constraints to output */
for (i=0; i 0) || (i > 0)) {
if (fprintf(MOEA_Stream_output, " ") < 0) {
return MOEA_Error(MOEA_IO_ERROR);
}
}
if (fprintf(MOEA_Stream_output, "%.17g", constraints[i]) < 0) {
return MOEA_Error(MOEA_IO_ERROR);
}
}
/* end line and flush to push data out immediately */
if (fprintf(MOEA_Stream_output, "\n") < 0) {
return MOEA_Error(MOEA_IO_ERROR);
}
if (fflush(MOEA_Stream_output) == EOF) {
return MOEA_Error(MOEA_IO_ERROR);
}
return MOEA_SUCCESS;
}
MOEA_Status MOEA_Terminate() {
if (MOEA_Stream_input != stdin) {
fclose(MOEA_Stream_input);
}
if (MOEA_Stream_output != stdout) {
fclose(MOEA_Stream_output);
}
if (MOEA_Stream_error != stderr) {
fclose(MOEA_Stream_error);
}
return MOEA_SUCCESS;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy