diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b34a7e0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: python +python: + - "3.4" + - "3.5" + - "3.6" +# command to install dependencies +install: + - pip install -r requirements.txt +# command to run tests +script: + - python setup.py install + - python tests/solve_test.py \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..89cd231 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,76 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at tsyet12@gmail.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see +https://www.contributor-covenant.org/faq diff --git a/DuelistAlgorithmPython.egg-info/PKG-INFO b/DuelistAlgorithmPython.egg-info/PKG-INFO new file mode 100644 index 0000000..3fdb570 --- /dev/null +++ b/DuelistAlgorithmPython.egg-info/PKG-INFO @@ -0,0 +1,10 @@ +Metadata-Version: 1.0 +Name: DuelistAlgorithmPython +Version: 1.0 +Summary: Implementation of Duelist Algorithm in Python by Sin Yong Teng +Home-page: UNKNOWN +Author: Sin Yong Teng +Author-email: tsyet12@gmail.com +License: UNKNOWN +Description: UNKNOWN +Platform: UNKNOWN diff --git a/DuelistAlgorithmPython.egg-info/SOURCES.txt b/DuelistAlgorithmPython.egg-info/SOURCES.txt new file mode 100644 index 0000000..1833897 --- /dev/null +++ b/DuelistAlgorithmPython.egg-info/SOURCES.txt @@ -0,0 +1,9 @@ +README.md +DuelistAlgorithmPython.egg-info/PKG-INFO +DuelistAlgorithmPython.egg-info/SOURCES.txt +DuelistAlgorithmPython.egg-info/dependency_links.txt +DuelistAlgorithmPython.egg-info/top_level.txt +examples/__init__.py +examples/solve_simple.py +solver/Duelist_Algorithm.py +solver/__init__.py \ No newline at end of file diff --git a/DuelistAlgorithmPython.egg-info/dependency_links.txt b/DuelistAlgorithmPython.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/DuelistAlgorithmPython.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/DuelistAlgorithmPython.egg-info/top_level.txt b/DuelistAlgorithmPython.egg-info/top_level.txt new file mode 100644 index 0000000..062fe46 --- /dev/null +++ b/DuelistAlgorithmPython.egg-info/top_level.txt @@ -0,0 +1,2 @@ +examples +solver diff --git a/Global_Optimal_example.xlsx b/Global_Optimal_example.xlsx deleted file mode 100644 index 08774c7..0000000 Binary files a/Global_Optimal_example.xlsx and /dev/null differ diff --git a/README.md b/README.md index 416391c..1297373 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,234 @@ -# Duelist-Algorithm-Python -A python implementation of the paper : Duelist Algorithm: An Algorithm Inspired by How Duelist Improve Their Capabilities in a Duel +# Duelist-Algorithm-Python [![Build Status](https://travis-ci.com/tsyet12/Duelist-Algorithm-Python.svg?branch=master)](https://travis-ci.com/tsyet12/Duelist-Algorithm-Python) ![PyPI](https://img.shields.io/pypi/v/DuelistAlgorithmPython.svg) ![Python Version](https://img.shields.io/badge/Python-3.4%20%7C%203.5%20%7C%203.6%20%7C%203.7-brightgreen.svg) +A Python implementation of the paper : +Duelist Algorithm: An Algorithm Inspired by How Duelist Improve Their Capabilities in a Duel (2015) +Totok Ruki Biyanto, Henokh Yernias Fibrianto, Gunawan Nugroho, Erny Listijorini, Titik Budiati, Hairul Huda https://arxiv.org/abs/1512.00708 + + + +This implementation only uses numpy, which is mainly written in C for fast computational speed. + + +I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. + + +# Theory (From Biyanto et al., 2015) +Duelist Algorithm is a metaheuristic for mathematical optimization problems. Metaheuristic are a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity. Examples for metaheuristics include genetic algorithm, particle swarm optimization, etc. Many of these metaheuristics rely on population-based search, which utilizes many "searchers" (also refered to as "particles" or "swarms") to simultaneously search the solution space. + +The procedure of Duelist Algorithm is shown in the figure below (see Fig 1). Quoting from the authors: +>The Duelist Algorithm starts with an initial set of duelists. The duel is to determine the winner and loser. The loser learns from the winner, while the winner try their new skill or technique that may improve their fighting capabilities. A few duelists with highest fighting capabilities are called as champion. The champion train a new duelists such as their capabilities. The new duelist will join the tournament as a representative of each champion. All duelist are re-evaluated, and the duelists with worst fighting capabilities is eliminated to maintain the amount of duelists. + +![flowchart](images/flowchart.PNG) + +*Fig 1. Flowchart of Duelist Algorithm* + +In the Duelist Algorithm, the best solutions in a population are chosen as the champions, while worst solutions are eliminated (see Fig 2). Winner mutates themselves and attempts to improve, while losers learns from winner (has a chance to copy traits of winner). + +![champion selection and elimination](images/cham.PNG) + +*Fig 2. Champion selection and worst elimination* + +In the original paper, Duelist Algorithm was shown to out-perform a few state-of-art metaheuristic algorithm for some specific tasks (see Fig 3). Therefore, it is very interesting. + +![performance](images/performance.PNG) + +*Fig 3. Performance of Duelist Algorithm from original paper* + +# Dependencies +This algorithm is fully implemented in Python. It is recommended to use Python 3.X. Library dependencies: +- numpy 1.15.4 +- matplotlib + +```BASH +$ pip install numpy matplotlib +``` + + + +# How to Use + +You can use two methods for installation: + +**1. Install from github (recommended as this will download the newest version)** + +First download the git repository. You can do this by clicking the download button or using the git command: +```BASH +$ git pull https://github.com/tsyet12/Duelist-Algorithm-Python +``` + + +Move to the directory: + +```BASH +$ cd (directory of Duelist-Algorithm-Python) +``` + +Run setup. The following command installs all files in directory: + +```BASH +$ pip install -e . +``` + +Move to examples and run the examples + +```BASH +$ cd examples +``` + +**1. Install from pip ** + +You can install this package from pip. + +Linux: + +```BASH +$ pip install DuelistAlgorithmPython +``` + +Windows: + +```BASH +$ python -m pip install DuelistAlgorithmPython +``` + + +# Short Tutorial + +**There are four simple steps to run an optimization problem using Duelist Algorithm** + +(Example 2 from example folder) + +** Prerequisites ** + +```python +from solver.Duelist_Algorithm import DuelistAlgorithm +``` + +** 1. Define your function. Say you want to minimize the equation f=(x1,x2) = (x1)^2+(x2)^2 ** + +```python +def f(x1,x2): + return x1*x1+x2*x2 +``` + +** 2. Define the variables that can be *manipulated* for optimization. Define their names as string and put them in an array. ** + +```python +x=["x1","x2"] +``` + +** 3. Define the boundaries for the manipulated variables:** + + Say: + + x1 is bounded from -2 to 10 (-2 is min value of x1 and 10 is max value of x1) + + x2 is bounded from 10 to 15 (10 is min value of x2 and 15 is max value of x2) + + We can arrange these boundaries according to the definition array in step 2. + + | Variables | x1 | x2 | + | :---: | :---: | :---: | + | Min | -2 | 5 | + | Max | 10 | 15 | + +The corresponding code is: + +```python + xmin=[-2,5] + xmax=[10,15] +``` + +** 4. Setup the solver and start the solve procedure. ** + +```python +DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=1000) +DA.solve(plot=True) +``` + +***RESULTS*** + +From the console we can deduce the optimal result (see Fig. 4) . The global optimal has a fitness of 25, while duelist algorithm found 25.01. Error of 0.01 can be reduced by putting more maximum generations in solver. + +![result1](images/results.PNG) + +*Fig 4. Optimal Results in Console (Colour may vary according to your environment)* + +We can see that the algorithm quickly converges to the optimal point (see Fig. 5) as reported by the original article. Note that graph is decreasing instead of increasing (in the case of original paper) because our objective is to MINIMIZE instead of maximizing. You can just add a negative sign in the function to get maximization. + +![result2](images/results2.png) + +*Fig 5. Quick convergence of Duelist Algorithm* + +For more examples refer to the python scripts in "examples" folder. [https://github.com/tsyet12/Duelist-Algorithm-Python/tree/master/examples] + + +# Dealing with Complex Constraint conditions + +There will be some problems that have complex constraints. For example, constraints which depends on two or more manipulated variables. + +*Example 1: Inequality* + +Say: +We take the same problem from the **Short Tutorial**, and now we have an extra constraint, which is x1 must be larger than x2: + +> x1>x2 + +We can put this constraint in the objective function: + +f=(x1,x2) = (x1)^2+(x2)^2 + max(0,x2-x1) + +Implementation: + +```python +def f(x1,x2): + return x1*x1+x2*x2+max(0,x2-x1) +``` +Continue from Step 2 of **Short Tutorial**. + + + +*Example 2: Equality* + +Say: +We take the same problem from the **Short Tutorial**, and now the extra constraint is x1 equal to x2: + +> x1=x2 + +We can put this constraint in the objective function: + +f=(x1,x2) = (x1)^2+(x2)^2 + (x2-x1)^2 + +Implementation: + +```python +def f(x1,x2): + return x1*x1+x2*x2+(x2-x1)*(x2-x1) +``` + +Continue from Step 2 of **Short Tutorial**. + + +# Version + +Currently Version 1.0 + +# To-do +- [X] Setup algorithm and show optimized solution + +- [X] Create Tutorials + +- [X] Update ReadMe + +- [X] Add plot functions + +- [ ] Add a modified feature for faster convergence + +- [ ] Add result logging and export to csv + + +# Contact Me + +If you have ideas or some opportunities for collaboration, feel free to send me an email. I will respond quickly. + +My email: tsyet12@gmail.com diff --git a/__main__.py b/__main__.py index d64c140..e69de29 100644 --- a/__main__.py +++ b/__main__.py @@ -1,175 +0,0 @@ -'''Duelist Algorithm -### -###Code and Implementation by Sin Yong, Teng -### -### Duelist Algorithm is a metaheuristic (just like genetic algorithm) that performs optimization procedure by mimicing high-level procedure in our world. -### In the original paper, Duelist Algorithm is able to outperform various state-of-art metaheuristic algorithms for stochastic problems. -### I implemented this algorithm in Python to allow for integrative use of this algorithm in other software and works. -### -###Original Paper: -### 1. Biyanto, T.R., Fibrianto, H.Y., Nugroho, G., Hatta, A.M., Listijorini, E., Budiati, T. and Huda, H., 2016, June. Duelist algorithm: an algorithm inspired by how duelist improve their capabilities in a duel. In International Conference on Swarm Intelligence (pp. 39-47). Springer, Cham. -### https://arxiv.org/abs/1512.00708 -### -###Implemented on 25/04/2019 -''' - - -import numpy as np -import random -import time -class DuelistAlgorithm(): - def __init__(self,f,x,xmin,xmax,pop=200,luck=0.01,mut=0.1,learn=0.8,max_gen=500,nc=5): - #setup class variables - self.f=f - self.x=x - self.pop=pop - self.luck=luck - self.mut=mut - self.learn=learn - self.max_gen=max_gen - self.nc=nc - self.champion=np.empty((x.__len__()+1,nc),dtype=np.float64) - self.winloss=np.empty((pop,1),dtype=np.float64) - self.battlescore=np.empty((pop,1),dtype=np.float64) - - - #check if multivariate optimization should be turned on. - if type(x) is list: - self.mult=1 - assert x.__len__()==xmin.__len__()==xmax.__len__() , "Constraint error, check xmin and xmax" - else: - self.mult=0 - - #initialize calculation matrix - if self.mult==1: - shape=(x.__len__(),pop) - else: - shape=(1,pop) - self.matrix=np.empty(shape,dtype=np.float64) - self.train=np.empty(shape,dtype=np.float64) - self.score=np.empty(pop,dtype=np.float64) - self.tmat=np.empty((x.__len__()+1,pop),dtype=np.float64) - self.bestlog=np.empty((0,x.__len__()+1),dtype=np.float64) - - def solve(self): - #steps for duelist algorithm - self.registration() - self.qualification() - for i in range(0,self.max_gen+1): - self.champion_select_train() - self.duel() - self.duelist_improvement() - self.post_qualification() - self.eliminate() - self.announce_answer() - - def registration(self): - for i in range(0,self.x.__len__()): - #pseudo-random generator for initializing population - t = int( time.time() * 1000.0 ) - np.random.seed( ((t & 0xff000000) >> 24) + - ((t & 0x00ff0000) >> 8) + - ((t & 0x0000ff00) << 8) + - ((t & 0x000000ff) << 24) ) - #randomize input such that it can be bounded by specified constraints - self.matrix[i,:]=np.random.uniform(size=self.pop,low=xmin[i],high=xmax[i]) - - - def qualification(self): - #this part only works for post-qualification when population is doubled - if self.score.shape[0]self.battlescore[i+1]): - self.winloss[i]=1 - self.winloss[i+1]=0 - else: - self.winloss[i]=0 - self.winloss[i+1]=1 - i=i+2 - - def duelist_improvement(self): - #duelist improvement splits for winner and loser - self.train=np.copy(self.matrix) - for j in range(0,self.x.__len__()): - for i in range(0,self.pop): - if self.winloss[i]==1: - #winner improves itself by mutating - if random.uniform(0,1)> 24) + + ((t & 0x00ff0000) >> 8) + + ((t & 0x0000ff00) << 8) + + ((t & 0x000000ff) << 24) ) + #randomize input such that it can be bounded by specified constraints + self.matrix[i,:]=np.random.uniform(size=self.pop,low=self.xmin[i],high=self.xmax[i]) + + + def qualification(self): + #this part only works for post-qualification when population is doubled + if self.score.shape[0]self.battlescore[i+1]): + self.winloss[i]=1 + self.winloss[i+1]=0 + else: + self.winloss[i]=0 + self.winloss[i+1]=1 + i=i+2 + + def duelist_improvement(self): + #duelist improvement splits for winner and loser + self.train=np.copy(self.matrix) + for j in range(0,self.x.__len__()): + for i in range(0,self.pop): + if self.winloss[i]==1: + #winner improves itself by mutating + if random.uniform(0,1)