All Downloads are FREE. Search and download functionalities are using the official Maven repository.

MOEAFramework-2.11.examples.moeaframework.c Maven / Gradle / Ivy

There is a newer version: 4.3
Show newest version
/* Copyright 2009-2016 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 - 2024 Weber Informatics LLC | Privacy Policy