Skip to content

Commit

Permalink
Add C++ API
Browse files Browse the repository at this point in the history
  • Loading branch information
PytLab committed Dec 3, 2018
1 parent db374c2 commit 7a4867e
Show file tree
Hide file tree
Showing 335 changed files with 131,741 additions and 0 deletions.
42 changes: 42 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,45 @@ ENV/
.DS_Store

*.prof
# Prerequisites
*.d

# Compiled Object files
*.slo
*.lo
*.o
*.obj

# Precompiled Headers
*.gch
*.pch

# Compiled Dynamic libraries
*.so
*.dylib
*.dll

# Fortran module files
*.mod
*.smod

# Compiled Static libraries
*.lai
*.la
*.a
*.lib

# Executables
*.exe
*.out
*.app

/build
/parallel_build
/serial_build

# Vim temp files
*.swp

mpiflag.h

46 changes: 46 additions & 0 deletions gasol/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# CMake script to build GASol

cmake_minimum_required(VERSION 3.0)

project(GASol)

# Enable verbose output.
#set(CMAKE_VERBOSE_MAKEFILE ON)

# Use C++11 standard.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Find OpenMP.
find_package(OpenMP)
if (OPENMP_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} -fPIC -Wall -Wextra -Werror -pedantic")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wextra -Werror -pedantic")
endif()

if (COV)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --coverage")
endif()

# MPI.
if (MPI)
message(STATUS "-- This is a parallel MPI build --")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MPI_CXX_COMPILER_FLAGS}")
include_directories(${MPI_CXX_INCLUDE_DIRS})
file(WRITE ${PROJECT_SOURCE_DIR}/src/mpiflag.h "#define RUNMPI true\n")
else()
message(STATUS "-- This is a serial build --")
file(WRITE ${PROJECT_SOURCE_DIR}/src/mpiflag.h "#define RUNMPI false\n")
endif()

# GASol source dir.
add_subdirectory(src)

# GASol test dir.
add_subdirectory(unittest)

# GASol run dir.
add_subdirectory(example)

108 changes: 108 additions & 0 deletions gasol/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# GASol

A general **G**enetic **A**lgorithm **Sol**ver in C++

[![Build Status](https://api.travis-ci.org/PytLab/GASol.svg?branch=master)](https://travis-ci.org/PytLab/GASol)
[![codecov](https://img.shields.io/codecov/c/github/PytLab/GASol/master.svg)](https://codecov.io/gh/PytLab/GASol)
[![License](https://img.shields.io/badge/license-GPLv3-blue.svg)](https://github.com/PytLab/GASol/blob/master/LICENSE)

## Build

#### Clone GASol

``` shell
git clone --recursive [email protected]:PytLab/GASol.git
```

#### Create dir for building.

``` shell
cd GASol
mkdir build
cd build
```
#### Build GASol

- Serial version
``` shell
cmake ..
make
```

- MPI parallel version
```
export CXX=/<mpi_path>/mpicxx
cmake -DMPI=true ..
make
```

#### Run test
``` shell
make unittest
./unittest/unittest
```
#### Run example

``` shell
make example
./example/example
```

## Quick start

#### Find the maxima of f(x) = x + 10sin(5x) + 7cos(4x)

``` cpp
#include "mpiutils.h"
#include "engine.h"

#include <cmath>
#include <vector>
#include <utility>

using namespace gasol;

// Define fitness function.
double fitness(const Individual & indv)
{
double x = indv.solution()[0];
return x + 10*std::sin(5*x) + 7*std::cos(4*x);
}

int main()
{
// Initialize MPI environment.
MPIUtils::init();
// Variable range.
std::vector<std::pair<double, double>> ranges {{0.0, 10.0}};
// Decrete precision.
std::vector<double> precisions {0.001};

// Create population.
size_t size = 50;
std::vector<Individual> individuals;
for (size_t i = 0; i < size; i++)
{
gasol::Individual indv(ranges, precisions);
individuals.push_back(indv);
}
Population population(individuals, &fitness);

// Genetic operators.
RouletteWheelSelection selection;
UniformCrossover crossover(0.8, 0.5);
FlipBitMutation mutation(0.1);

// Create engine.
Engine engine(population, selection, crossover, mutation);

// Run 1000 generations.
engine.run(1000);

// Finalize MPI env.
MPIUtils::finalize();

return 0;
}
```
71 changes: 71 additions & 0 deletions gasol/example/1d_search.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*! \brief GASol example for searching the maxima of f(x) = x + 10sin(5x) + 7cos(4x)
*/

#include "mpiutils.h"
#include "engine.h"

#include <iostream>
#include <cmath>
#include <vector>
#include <utility>
#include <ctime>

using namespace gasol;

// Define fitness function.
double fitness(const Individual & indv)
{
double x = indv.solution()[0];
return x + 10*std::sin(5*x) + 7*std::cos(4*x);
}

int main()
{
MPIUtils::init();
if (MPIUtils::isMaster())
{
std::cout << "Process number: " << MPIUtils::size() << std::endl;
}
// Variable range.
std::vector<std::pair<double, double>> ranges {{0.0, 100.0}};
// Decrete precision.
std::vector<double> precisions {0.001};

// Create population.
size_t size = 1000;
std::vector<Individual> individuals;
for (size_t i = 0; i < size; i++)
{
gasol::Individual indv(ranges, precisions);
individuals.push_back(indv);
}
Population population(individuals, &fitness);

// Genetic operators.
RouletteWheelSelection selection;
UniformCrossover crossover(0.8, 0.5);
FlipBitMutation mutation(0.1);

// Create engine.
Engine engine(population, selection, crossover, mutation);

// Run 100 generations.
time_t start = time(NULL);
engine.run(100);
time_t end = time(NULL);

const Individual & best_indv = engine.population().bestIndv();
double best_fitness = engine.population().fitness()(best_indv);
double solution = best_indv.solution()[0];

if (MPIUtils::isMaster())
{
std::cout << "Solution: " << solution << ", fitness: " << best_fitness << std::endl;
std::cout << "Time used: " << end - start << "s" << std::endl;
}

MPIUtils::finalize();

return 0;
}

8 changes: 8 additions & 0 deletions gasol/example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# CMake script for gasol run executable program building.

include_directories(${PROJECT_SOURCE_DIR}/src)
link_directories(${CMAKE_BINARY_DIR}/../src/)
file(GLOB RUN_SRC *.cpp)
add_executable(example EXCLUDE_FROM_ALL ${RUN_SRC})
target_link_libraries(example GASol)

3 changes: 3 additions & 0 deletions gasol/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
file(GLOB GASol_SRC *.cpp)
add_library(GASol STATIC ${GASol_SRC})

46 changes: 46 additions & 0 deletions gasol/src/crossover.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*! \brief Implementations of uniform crossover operator.
*/

#include "individual.h"
#include "crossover.h"

#include <random>
#include <cstddef>

namespace gasol {

//--------------------------------------------------------------------------
//
std::pair<Individual, Individual> UniformCrossover::cross(Parents & parents) const
{
const Individual *father = parents.first;
const Individual *mother = parents.second;

// Children to return.
Individual child1(*father);
Individual child2(*mother);

// Create a random number generator.
std::mt19937 gen(seed());
std::uniform_real_distribution<double> dis(0.0, 1.0);

double rnd = dis(gen);
if (rnd > pc())
{
return std::pair<Individual, Individual>(child1, child2);
}
else
{
for (size_t i = 0; i < child1.chromsome().size(); i++)
{
if (child1.chromsome()[i] != child2.chromsome()[i])
{
child1.flipGeneBit(i);
child2.flipGeneBit(i);
}
}
return std::pair<Individual, Individual>(child1, child2);
}
}
}

Loading

0 comments on commit 7a4867e

Please sign in to comment.