From 0c424a5a0fc6e886cfb5d2232af73d9b62b30209 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 09:24:28 +0200 Subject: [PATCH 01/78] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 416391c..6b6d296 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # Duelist-Algorithm-Python A python implementation of the paper : Duelist Algorithm: An Algorithm Inspired by How Duelist Improve Their Capabilities in a Duel https://arxiv.org/abs/1512.00708 + +I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. + From 648fc81cb63eb7c7fba08aa1788c71c33594f10f Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 09:26:47 +0200 Subject: [PATCH 02/78] update structure --- examples/Global_Optimal_example.xlsx | Bin 0 -> 8989 bytes metaheuristics/Duelist_Algorithm.py | 175 +++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 examples/Global_Optimal_example.xlsx create mode 100644 metaheuristics/Duelist_Algorithm.py diff --git a/examples/Global_Optimal_example.xlsx b/examples/Global_Optimal_example.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..08774c7314e4ec86ebe2a0a8f8d684b2dacf3b4b GIT binary patch literal 8989 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 Q>R5mlc+nz5{o~XB0l7Mb+yDRo literal 0 HcmV?d00001 diff --git a/metaheuristics/Duelist_Algorithm.py b/metaheuristics/Duelist_Algorithm.py new file mode 100644 index 0000000..d64c140 --- /dev/null +++ b/metaheuristics/Duelist_Algorithm.py @@ -0,0 +1,175 @@ +'''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) Date: Fri, 26 Apr 2019 09:28:57 +0200 Subject: [PATCH 03/78] Delete __main__.py --- __main__.py | 175 ---------------------------------------------------- 1 file changed, 175 deletions(-) delete mode 100644 __main__.py diff --git a/__main__.py b/__main__.py deleted file mode 100644 index d64c140..0000000 --- a/__main__.py +++ /dev/null @@ -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) Date: Fri, 26 Apr 2019 09:29:05 +0200 Subject: [PATCH 04/78] Delete Global_Optimal_example.xlsx --- Global_Optimal_example.xlsx | Bin 8989 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Global_Optimal_example.xlsx diff --git a/Global_Optimal_example.xlsx b/Global_Optimal_example.xlsx deleted file mode 100644 index 08774c7314e4ec86ebe2a0a8f8d684b2dacf3b4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8989 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 Q>R5mlc+nz5{o~XB0l7Mb+yDRo From 7348bc98da4e43e65aadc170ee9d1d9ff3ba1a22 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 09:44:31 +0200 Subject: [PATCH 05/78] images commit --- images/cham.PNG | Bin 0 -> 7715 bytes images/flowchart.PNG | Bin 0 -> 50949 bytes images/performance.PNG | Bin 0 -> 76212 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 images/cham.PNG create mode 100644 images/flowchart.PNG create mode 100644 images/performance.PNG diff --git a/images/cham.PNG b/images/cham.PNG new file mode 100644 index 0000000000000000000000000000000000000000..55b698abb8315fe0ba17d0a5d8991ddad91ef532 GIT binary patch literal 7715 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 aad;-<3Ypxs7BL&USRhp`l?o+`kpBjvQv%5V literal 0 HcmV?d00001 diff --git a/images/flowchart.PNG b/images/flowchart.PNG new file mode 100644 index 0000000000000000000000000000000000000000..83bb544d6925c4dbce6b894ab2d1e5a11fce28f5 GIT binary patch literal 50949 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 I_0s?U0S%<@4*&oF literal 0 HcmV?d00001 diff --git a/images/performance.PNG b/images/performance.PNG new file mode 100644 index 0000000000000000000000000000000000000000..09f93423ed91415c9801002b5cccb3f2b7fe768e GIT binary patch literal 76212 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 Date: Fri, 26 Apr 2019 09:45:02 +0200 Subject: [PATCH 06/78] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 6b6d296..b4b7f29 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,8 @@ https://arxiv.org/abs/1512.00708 I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. +[images/flowchart.png] + +[images/cham.png] + +[images/performance.png] From f8464808831c9ae65442844caaa3dfd76d9b18ea Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 09:47:01 +0200 Subject: [PATCH 07/78] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b4b7f29..e2a936c 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ https://arxiv.org/abs/1512.00708 I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. -[images/flowchart.png] +![images](flowchart.png) -[images/cham.png] +![images](cham.png) -[images/performance.png] +![images](performance.png) From a513de019efb800a56b73dbfde3e0444a66d0c51 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 09:47:49 +0200 Subject: [PATCH 08/78] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e2a936c..2e866c6 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ https://arxiv.org/abs/1512.00708 I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. -![images](flowchart.png) +![flowchart](images/flowchart.png) -![images](cham.png) +![champion selection and elimination](images/cham.png) -![images](performance.png) +![performance](images/performance.png) From 8dcd3dcda88b703df26355a0b591b9230dcf70a5 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 09:48:27 +0200 Subject: [PATCH 09/78] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2e866c6..6b9c791 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ https://arxiv.org/abs/1512.00708 I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. -![flowchart](images/flowchart.png) +![flowchart](images/flowchart.PNG) -![champion selection and elimination](images/cham.png) +![champion selection and elimination](images/cham.PNG) -![performance](images/performance.png) +![performance](images/performance.PNG) From 46512503afaa8ac5c1c503510e37c842aceb85ef Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 09:50:12 +0200 Subject: [PATCH 10/78] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b9c791..6317287 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,9 @@ https://arxiv.org/abs/1512.00708 I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. -![flowchart](images/flowchart.PNG) +![flowchart](images/flowchart.PNG) ![champion selection and elimination](images/cham.PNG) ![performance](images/performance.PNG) + From b1075b1f9d5c803ea0ecb83477f386af5e0088d0 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 09:50:54 +0200 Subject: [PATCH 11/78] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6317287..c760415 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,10 @@ https://arxiv.org/abs/1512.00708 I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. -![flowchart](images/flowchart.PNG) +

+![flowchart](images/flowchart.PNG) ![champion selection and elimination](images/cham.PNG) ![performance](images/performance.PNG) - +

From 2e8e30e81d4e0f45086fcd5adb78985f9b74c682 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 09:51:20 +0200 Subject: [PATCH 12/78] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c760415..e4e8147 100644 --- a/README.md +++ b/README.md @@ -4,10 +4,10 @@ https://arxiv.org/abs/1512.00708 I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. -

-![flowchart](images/flowchart.PNG) + +![flowchart]

(images/flowchart.PNG)

![champion selection and elimination](images/cham.PNG) ![performance](images/performance.PNG) -

+ From 0bb12a53d0a927f18bf7b99b88a2fb82b4dbbc93 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 10:00:45 +0200 Subject: [PATCH 13/78] Update README.md --- README.md | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e4e8147..9b3ef98 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,25 @@ # Duelist-Algorithm-Python -A python implementation of the paper : Duelist Algorithm: An Algorithm Inspired by How Duelist Improve Their Capabilities in a Duel +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 I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. -![flowchart]

(images/flowchart.PNG)

+# 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. 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) + +In the Duelist Algorithm, the best solutions in a population are chosen as the champions, while worst solutions are eliminated. 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) +In the original paper, Duelist Algorithm was shown to out-perform a few state-of-art metaheuristic algorithm for some specific tasks. Therefore, it is very interesting. + ![performance](images/performance.PNG) From c26229537c8bce134c12e8ffec7e17985ac6fcad Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 10:08:01 +0200 Subject: [PATCH 14/78] Update README.md --- README.md | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9b3ef98..da60645 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Duelist-Algorithm-Python 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 +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 I would like to clarify that various figures of this README.md document is taken from the original artical as shown above. @@ -23,3 +23,18 @@ In the original paper, Duelist Algorithm was shown to out-perform a few state-of ![performance](images/performance.PNG) +#Dependencies +This algorithm is fully implemented in Python. It is recommended to use Python 3.X. +-numpy 1.15.4 +''' +$pip install numpy +''' + + +# How to Use +First download the git repository. You can do this by clicking the download button or using the git command: +''' +git pull https://github.com/tsyet12/Duelist-Algorithm-Python +''' + + From b8d54859f6cdb4c266ea245bba0d4fb4d6eb4b0c Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 10:08:54 +0200 Subject: [PATCH 15/78] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index da60645..a7bdb6d 100644 --- a/README.md +++ b/README.md @@ -26,15 +26,15 @@ In the original paper, Duelist Algorithm was shown to out-perform a few state-of #Dependencies This algorithm is fully implemented in Python. It is recommended to use Python 3.X. -numpy 1.15.4 -''' +``` $pip install numpy -''' +`` # How to Use First download the git repository. You can do this by clicking the download button or using the git command: -''' +``` git pull https://github.com/tsyet12/Duelist-Algorithm-Python -''' +``` From 85956d98b2e4de9c493d3df9a254650fae9d5acc Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 10:09:50 +0200 Subject: [PATCH 16/78] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a7bdb6d..c6fb2ef 100644 --- a/README.md +++ b/README.md @@ -23,18 +23,19 @@ In the original paper, Duelist Algorithm was shown to out-perform a few state-of ![performance](images/performance.PNG) -#Dependencies +# Dependencies This algorithm is fully implemented in Python. It is recommended to use Python 3.X. -numpy 1.15.4 ``` $pip install numpy -`` +``` + # How to Use First download the git repository. You can do this by clicking the download button or using the git command: ``` git pull https://github.com/tsyet12/Duelist-Algorithm-Python ``` - + From 3284d5d76fc2f240d1ff156b1e380feb677ead24 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 10:10:31 +0200 Subject: [PATCH 17/78] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c6fb2ef..b75cb84 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ In the original paper, Duelist Algorithm was shown to out-perform a few state-of ![performance](images/performance.PNG) # Dependencies -This algorithm is fully implemented in Python. It is recommended to use Python 3.X. --numpy 1.15.4 +This algorithm is fully implemented in Python. It is recommended to use Python 3.X. Library dependencies: +- numpy 1.15.4 ``` $pip install numpy ``` From 959738c71af5001701af28142b1a04c32bc2218f Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 10:13:33 +0200 Subject: [PATCH 18/78] Update README.md --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b75cb84..b4089d4 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,21 @@ I would like to clarify that various figures of this README.md document is taken # 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. Quoting from the authors: +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. Winner mutates themselves and attempts to improve, while losers learns from winner (has a chance to copy traits of winner). +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. Therefore, it is very interesting. +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: From 37a3d4e01fa5b6f61d6f53de4f4f4fba0c07723c Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 10:14:03 +0200 Subject: [PATCH 19/78] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b4089d4..e5e9da9 100644 --- a/README.md +++ b/README.md @@ -13,17 +13,17 @@ Duelist Algorithm is a metaheuristic for mathematical optimization problems. Met 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) +![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) +![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) +![performance](images/performance.PNG) *Fig 3. Performance of Duelist Algorithm from original paper* # Dependencies From a1133ae6ae169c863a5f44d6ca0a3f2b2fd250b5 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 10:14:55 +0200 Subject: [PATCH 20/78] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e5e9da9..2fcae68 100644 --- a/README.md +++ b/README.md @@ -14,16 +14,19 @@ The procedure of Duelist Algorithm is shown in the figure below (see Fig 1). Quo >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 From cc6669e9938fedddb9ecb314a1345f126f87f0a5 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 10:16:29 +0200 Subject: [PATCH 21/78] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2fcae68..b6ae159 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ In the original paper, Duelist Algorithm was shown to out-perform a few state-of This algorithm is fully implemented in Python. It is recommended to use Python 3.X. Library dependencies: - numpy 1.15.4 ``` -$pip install numpy +$ pip install numpy ``` @@ -41,7 +41,7 @@ $pip install numpy # How to Use First download the git repository. You can do this by clicking the download button or using the git command: ``` -git pull https://github.com/tsyet12/Duelist-Algorithm-Python +$ git pull https://github.com/tsyet12/Duelist-Algorithm-Python ``` From 4de083d83a57190819037c085eb9c44f010629d0 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 12:40:35 +0200 Subject: [PATCH 22/78] examples and setup --- DuelistAlgorithmPython.egg-info/PKG-INFO | 10 + DuelistAlgorithmPython.egg-info/SOURCES.txt | 9 + .../dependency_links.txt | 1 + DuelistAlgorithmPython.egg-info/top_level.txt | 2 + __main__.py | 0 examples/1_solve_simple.py | 70 +++++++ examples/2_solve_multivariate.py | 72 ++++++++ examples/3_solve_stochastic.py | 78 ++++++++ examples/Global_Optimal_example.xlsx | Bin 8989 -> 0 bytes examples/__init__.py | 0 setup.py | 10 + solve_simple.py | 61 ++++++ solver/Duelist_Algorithm.py | 173 ++++++++++++++++++ solver/__init__.py | 0 solver/__init__.pyc | Bin 0 -> 137 bytes .../Duelist_Algorithm.cpython-36.pyc | Bin 0 -> 5780 bytes solver/__pycache__/__init__.cpython-36.pyc | Bin 0 -> 133 bytes 17 files changed, 486 insertions(+) create mode 100644 DuelistAlgorithmPython.egg-info/PKG-INFO create mode 100644 DuelistAlgorithmPython.egg-info/SOURCES.txt create mode 100644 DuelistAlgorithmPython.egg-info/dependency_links.txt create mode 100644 DuelistAlgorithmPython.egg-info/top_level.txt create mode 100644 __main__.py create mode 100644 examples/1_solve_simple.py create mode 100644 examples/2_solve_multivariate.py create mode 100644 examples/3_solve_stochastic.py delete mode 100644 examples/Global_Optimal_example.xlsx create mode 100644 examples/__init__.py create mode 100644 setup.py create mode 100644 solve_simple.py create mode 100644 solver/Duelist_Algorithm.py create mode 100644 solver/__init__.py create mode 100644 solver/__init__.pyc create mode 100644 solver/__pycache__/Duelist_Algorithm.cpython-36.pyc create mode 100644 solver/__pycache__/__init__.cpython-36.pyc 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/__main__.py b/__main__.py new file mode 100644 index 0000000..e69de29 diff --git a/examples/1_solve_simple.py b/examples/1_solve_simple.py new file mode 100644 index 0000000..48bb8b7 --- /dev/null +++ b/examples/1_solve_simple.py @@ -0,0 +1,70 @@ +from solver.Duelist_Algorithm import DuelistAlgorithm + +''' +Example 1 + +Solving single variable optimization problem + +''' + + + + + +''' +Here we have a simple squared equation that we want to optimize (minimize). +The equation is y=(x1)^2+2 + x1 is bounded from -2 to 10 (-2 is min value of x1 and 10 is max value of x1) +''' + + +''' +First we define the function: +The equation is f=(x1,x2) = y = (x1)^2+(x2)^2 +''' +def f(x1,x2): + return x1*x1+2 + +''' +Secondly, we name the optimization variables and tell the solver how many variables to optimize. +We can do this by putting in the names of the variables as strings in an array. +''' +x=["x1"] + +''' +The thirds step is to specify the boundary for x1 + x1 is bounded from -2 to 10 (-2 is min value of x1 and 10 is max value of x1) +''' + +xmin=[-2] +xmax=[10] + +''' +DA.DuelistAlgorithm(function output=f, + names of manipulated variables= x, + lower limit of manipulated variables= xmin, + upper limit of manipulated variables = xmax, + population size=pop (default=200), + luck factor=luck (default=0.01), + innovative/mutation factor= mut (default=0.1), + learning probability= learn (default=0.8), + maximum generation= max_gen (default=500), + number of champions per selection=nc (default=5), + is shuffling required before duel?=shuffle (default=False) + ) + +You do not need to fill in variables with default values. They are for fine tuning the algorithm. +''' + +#Increase the maximum generation for more precise answer +DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=100) +DA.solve() + +''' +You should see the answer, it should look something like the following: + +Optimized using Duelist Algorithm. Answer is: [1.70085713e-03 5.00016813e+00] with fitness of 25.00168420123805 + +The analytical answer is [0,5] with fitness of 25.00 +Duelist Algorithm performs well. +''' \ No newline at end of file diff --git a/examples/2_solve_multivariate.py b/examples/2_solve_multivariate.py new file mode 100644 index 0000000..2b5a861 --- /dev/null +++ b/examples/2_solve_multivariate.py @@ -0,0 +1,72 @@ +from solver.Duelist_Algorithm import DuelistAlgorithm + +''' +EXAMPLE 2 + +Multivariate optimization is demonstrated by using a squared equation with two variables + +''' + + +''' +Here we have a simple squared equation that we want to optimize (minimize). +The equation is y=(x1)^2+(x2)^2 + 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) +''' + + +''' +First we define the function: +The equation is f=(x1,x2) = y = (x1)^2+(x2)^2 +''' +def f(x1,x2): + return x1*x1+x2*x2 + +''' +Secondly, we name the optimization variables and tell the solver how many variables to optimize. +We can do this by putting in the names of the variables as strings in an array. +''' +x=["x1","x2"] + +''' +The thirds step is to specify the boundary for each variables + "x1" "x2" +min -2 5 +max 10 15 + +This xmin and xmax array follows the position of the array you define at second step. +''' + +xmin=[-2,5] +xmax=[10,15] + +''' +DA.DuelistAlgorithm(function output=f, + names of manipulated variables= x, + lower limit of manipulated variables= xmin, + upper limit of manipulated variables = xmax, + population size=pop (default=200), + luck factor=luck (default=0.01), + innovative/mutation factor= mut (default=0.1), + learning probability= learn (default=0.8), + maximum generation= max_gen (default=500), + number of champions per selection=nc (default=5), + is shuffling required before duel?=shuffle (default=False) + ) + +You do not need to fill in variables with default values. They are for fine tuning the algorithm. +''' + +#Increase the maximum generation for more precise answer +DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=1000) +DA.solve() + +''' +You should see the answer, it should look something like the following: + +Optimized using Duelist Algorithm. Answer is: [1.70085713e-03 5.00016813e+00] with fitness of 25.00168420123805 + +The analytical answer is [0,5] with fitness of 25.00 +Duelist Algorithm performs well. +''' \ No newline at end of file diff --git a/examples/3_solve_stochastic.py b/examples/3_solve_stochastic.py new file mode 100644 index 0000000..260733c --- /dev/null +++ b/examples/3_solve_stochastic.py @@ -0,0 +1,78 @@ +from solver.Duelist_Algorithm import DuelistAlgorithm +import random + + +''' +EXAMPLE 3 + +For stochastic problems, we demonstrate this by adding probability distributions or random noises to the equation. + +Random Uniform Noise is added to the previous example +''' + + + + + +''' +Here we have a simple squared equation that we want to optimize (minimize). +The equation is y=(x1)^2+(x2)^2+ RandomUniformNoise(0,20) + 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) +''' + + +''' +First we define the function: +The equation is f=(x1,x2) = y = (x1)^2+(x2)^2 + RandomUniformNoise(0,20) +''' +def f(x1,x2): + return x1*x1+x2*x2+random.uniform(0,20) + +''' +Secondly, we name the optimization variables and tell the solver how many variables to optimize. +We can do this by putting in the names of the variables as strings in an array. +''' +x=["x1","x2"] + +''' +The thirds step is to specify the boundary for each variables + "x1" "x2" +min -2 5 +max 10 15 + +This xmin and xmax array follows the position of the array you define at second step. +''' + +xmin=[-2,5] +xmax=[10,15] + +''' +DA.DuelistAlgorithm(function output=f, + names of manipulated variables= x, + lower limit of manipulated variables= xmin, + upper limit of manipulated variables = xmax, + population size=pop (default=200), + luck factor=luck (default=0.01), + innovative/mutation factor= mut (default=0.1), + learning probability= learn (default=0.8), + maximum generation= max_gen (default=500), + number of champions per selection=nc (default=5), + is shuffling required before duel?=shuffle (default=False) + ) + +You do not need to fill in variables with default values. They are for fine tuning the algorithm. +''' + +#Increase the maximum generation for more precise answer +DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=1000) +DA.solve() + +''' +You should see the answer, it should look something like the following: + +Optimized using Duelist Algorithm. Answer is: [1.70085713e-03 5.00016813e+00] with fitness of 25.00168420123805 + +The analytical answer is [0,5] with fitness of 25.00 +Duelist Algorithm performs well. +''' \ No newline at end of file diff --git a/examples/Global_Optimal_example.xlsx b/examples/Global_Optimal_example.xlsx deleted file mode 100644 index 08774c7314e4ec86ebe2a0a8f8d684b2dacf3b4b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8989 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 Q>R5mlc+nz5{o~XB0l7Mb+yDRo diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..6e3ff90 --- /dev/null +++ b/setup.py @@ -0,0 +1,10 @@ +from setuptools import setup, find_packages + + +setup(name='DuelistAlgorithmPython', +version='1.0', +description="Implementation of Duelist Algorithm in Python by Sin Yong Teng", +author='Sin Yong Teng', +author_email='tsyet12@gmail.com', +packages=find_packages(), +setup_requires=['numpy']) diff --git a/solve_simple.py b/solve_simple.py new file mode 100644 index 0000000..5104eb1 --- /dev/null +++ b/solve_simple.py @@ -0,0 +1,61 @@ +from solver.Duelist_Algorithm import DuelistAlgorithm + +''' +Here we have a simple squared equation that we want to optimize (minimize). +The equation is y=(x1)^2+(x2)^2 + 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) +''' + + +''' +First we define the function: +The equation is f=(x1,x2) = y = (x1)^2+(x2)^2 +''' +def f(x1,x2): + return x1*x1+x2*x2 + +''' +Secondly, we name the optimization variables and tell the solver how many variables to optimize. +We can do this by putting in the names of the variables as strings in an array. +''' +x=["x1","x2"] + +''' +The thirds step is to specify the boundary for each variables + "x1" "x2" +min -2 5 +max 10 15 + +This xmin and xmax array follows the position of the array you define at second step. +''' + +xmin=[-2,5] +xmax=[10,15] + +''' +DA.DuelistAlgorithm(function output=f, + names of manipulated variables= x, + lower limit of manipulated variables= xmin, + upper limit of manipulated variables = xmax, + population size=pop (default=200), + luck factor=luck (default=0.01), + innovative/mutation factor= mut (default=0.1), + learning probability= learn (default=0.8), + maximum generation= max_gen (default=500), + number of champions per selection=nc (default=5), + is shuffling required before duel?=shuffle (default=False) + ) + +You do not need to fill in variables with default values. They are for fine tuning the algorithm. +''' + +#Increase the maximum generation for more precise answer +DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=1000) +DA.solve() + +''' +You should see the answer, it should look something like the following: + +Optimized using Duelist Algorithm. Answer is: [1.70085713e-03 5.00016813e+00] with fitness of 25.00168420123805 +''' \ No newline at end of file diff --git a/solver/Duelist_Algorithm.py b/solver/Duelist_Algorithm.py new file mode 100644 index 0000000..3021072 --- /dev/null +++ b/solver/Duelist_Algorithm.py @@ -0,0 +1,173 @@ +'''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,shuffle=False): + #setup class variables + self.f=f + self.x=x + self.xmin=xmin + self.xmax=xmax + 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) + self.gen=0 + self.shuffle=shuffle + + #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() + while self.gen > 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,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 TY+g-{agB^Bq;nd2a*g^Q$2?sJ literal 0 HcmV?d00001 diff --git a/solver/__pycache__/__init__.cpython-36.pyc b/solver/__pycache__/__init__.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0760f34b8a3369ecf7625db29a59b83575189792 GIT binary patch literal 133 zcmXr!<>flQ?@$Z_5IhDEFu(|8H~?`m3y?@*2xib^^jpbL1QJFNzl@x%V%#%J0*dmp zQj<%HV_Zs8b25ud9COn1i!w_xa$}0~bIMYSV&da7^D;}~ Date: Fri, 26 Apr 2019 12:46:32 +0200 Subject: [PATCH 23/78] tests --- requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 requirements.txt diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b01e669 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +numpy==1.15.4 \ No newline at end of file From 45c228737e9d6ce94e0e225bf0c6e8b13c0610ea Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 12:49:40 +0200 Subject: [PATCH 24/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b6ae159..b143e56 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Duelist-Algorithm-Python +# Duelist-Algorithm-Python [[![Build Status](https://travis-ci.com/tsyet12/Duelist-Algorithm-Python.svg?branch=master)](https://travis-ci.com/tsyet12/Duelist-Algorithm-Python)] 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 From 3c154ea022ae8b37a7d0950f4116ec28cc1464fa Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 12:49:55 +0200 Subject: [PATCH 25/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b143e56..3e360ad 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Duelist-Algorithm-Python [[![Build Status](https://travis-ci.com/tsyet12/Duelist-Algorithm-Python.svg?branch=master)](https://travis-ci.com/tsyet12/Duelist-Algorithm-Python)] +# Duelist-Algorithm-Python [![Build Status](https://travis-ci.com/tsyet12/Duelist-Algorithm-Python.svg?branch=master)](https://travis-ci.com/tsyet12/Duelist-Algorithm-Python) 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 From d0cd1f9153606bdc0e0bc911166d758d4aa5569b Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 12:53:28 +0200 Subject: [PATCH 26/78] Update README.md --- README.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/README.md b/README.md index 3e360ad..c0045b7 100644 --- a/README.md +++ b/README.md @@ -44,4 +44,23 @@ First download the git repository. You can do this by clicking the download butt $ git pull https://github.com/tsyet12/Duelist-Algorithm-Python ``` + +Move to the directory: + +``` +$ cd (directory of Duelist-Algorithm-Python) +``` + +Run setup. The following command installs all files in directory: + +``` +$ pip install -e . +``` + +Move to examples and run the examples + +``` +$ cd examples +``` + From 623cec1a4e488efa1c01c3b2ca37cd027dc2a1a0 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 12:54:36 +0200 Subject: [PATCH 27/78] Delete Duelist_Algorithm.py --- metaheuristics/Duelist_Algorithm.py | 175 ---------------------------- 1 file changed, 175 deletions(-) delete mode 100644 metaheuristics/Duelist_Algorithm.py diff --git a/metaheuristics/Duelist_Algorithm.py b/metaheuristics/Duelist_Algorithm.py deleted file mode 100644 index d64c140..0000000 --- a/metaheuristics/Duelist_Algorithm.py +++ /dev/null @@ -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) Date: Fri, 26 Apr 2019 13:08:11 +0200 Subject: [PATCH 28/78] Update README.md --- README.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/README.md b/README.md index c0045b7..ddb21cf 100644 --- a/README.md +++ b/README.md @@ -63,4 +63,56 @@ Move to examples and run the examples $ cd examples ``` +# Short Tutorial + +**There are four simple steps to run an optimization problem using Duelist Algorithm** + +(Example 2 from example folder) +> Prerequisites + +``` +from solver.Duelist_Algorithm import DuelistAlgorithm +``` + +> 1. Define your function. Say you want to minimize the equation f=(x1,x2) = (x1)^2+(x2)^2 + +``` +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. + +``` +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 this in a table that can be easily read: +> -------------------- +> Variables | "x1" | "x2" | +> -------------------- +> Min. bound | -2 | 5 | +> Max. bound | 10 | 15 | +> -------------------- + +``` +xmin=[-2,5] +xmax=[10,15] +``` + +> 4. Setup the solver and start the solve procedure. + +``` +DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=1000) +DA.solve() +``` + +# Version + +Currently Version 1.0 + From bb8feac9ffdf8393af44619a6d967d06de666706 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:10:00 +0200 Subject: [PATCH 29/78] Update README.md --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index ddb21cf..3a19e06 100644 --- a/README.md +++ b/README.md @@ -88,15 +88,25 @@ 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 this in a table that can be easily read: + > -------------------- + > Variables | "x1" | "x2" | + > -------------------- + > Min. bound | -2 | 5 | + > Max. bound | 10 | 15 | + > -------------------- ``` @@ -115,4 +125,8 @@ DA.solve() Currently Version 1.0 +# To-do +[] Add plot functions +[] Add a modified feature for faster convergence +[] Add result loging From 621e4f54f7b79c6078ef2770be5cd1ed5d8e7a8b Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:11:05 +0200 Subject: [PATCH 30/78] Update README.md --- README.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3a19e06..da3447f 100644 --- a/README.md +++ b/README.md @@ -97,17 +97,12 @@ x=["x1","x2"] > We can arrange this in a table that can be easily read: -> -------------------- - > Variables | "x1" | "x2" | -> -------------------- - > Min. bound | -2 | 5 | > Max. bound | 10 | 15 | -> -------------------- ``` xmin=[-2,5] @@ -127,6 +122,8 @@ Currently Version 1.0 # To-do -[] Add plot functions -[] Add a modified feature for faster convergence -[] Add result loging +[ ] Add plot functions + +[ ] Add a modified feature for faster convergence + +[ ] Add result loging From bdb1ed3f76e2f021c651d8a0b5eb4db72b3af78d Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:12:12 +0200 Subject: [PATCH 31/78] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index da3447f..0e0dd64 100644 --- a/README.md +++ b/README.md @@ -121,9 +121,10 @@ DA.solve() Currently Version 1.0 # To-do +- [X] Setup algorithm and show optimized solution -[ ] Add plot functions +- [ ] Add plot functions -[ ] Add a modified feature for faster convergence +- [ ] Add a modified feature for faster convergence -[ ] Add result loging +- [ ] Add result loging From 52383e9d42dc3cb555c0cfd0089162d4445bac77 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:13:03 +0200 Subject: [PATCH 32/78] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0e0dd64..5b6509b 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,10 @@ Currently Version 1.0 # To-do - [X] Setup algorithm and show optimized solution +- [X] Create Tutorials + +- [X] Update ReadMe + - [ ] Add plot functions - [ ] Add a modified feature for faster convergence From 99942dada7e6dd7434a871a37809cf92c9a389f3 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:17:16 +0200 Subject: [PATCH 33/78] Update README.md --- README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 5b6509b..2b1bd53 100644 --- a/README.md +++ b/README.md @@ -68,45 +68,46 @@ $ cd examples **There are four simple steps to run an optimization problem using Duelist Algorithm** (Example 2 from example folder) -> Prerequisites + +** Prerequisites ** ``` from solver.Duelist_Algorithm import DuelistAlgorithm ``` -> 1. Define your function. Say you want to minimize the equation f=(x1,x2) = (x1)^2+(x2)^2 +** 1. Define your function. Say you want to minimize the equation f=(x1,x2) = (x1)^2+(x2)^2 ** ``` 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. +** 2. Define the variables that can be *manipulated* for optimization. Define their names as string and put them in an array. ** ``` x=["x1","x2"] ``` -> 3. Define the boundaries for the manipulated variables: +** 3. Define the boundaries for the manipulated variables:** -> Say: + Say: -> x1 is bounded from -2 to 10 (-2 is min value of x1 and 10 is max value of x1) + 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) + x2 is bounded from 10 to 15 (10 is min value of x2 and 15 is max value of x2) -> We can arrange this in a table that can be easily read: + We can arrange this in a table that can be easily read: -> Variables | "x1" | "x2" | + Variables | "x1" | "x2" | -> Min. bound | -2 | 5 | + Min. bound | -2 | 5 | -> Max. bound | 10 | 15 | + Max. bound | 10 | 15 | ``` -xmin=[-2,5] -xmax=[10,15] +> xmin=[-2,5] +> xmax=[10,15] ``` > 4. Setup the solver and start the solve procedure. From 9d7362e87a089d7c54897e91c23efceb87059857 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:19:05 +0200 Subject: [PATCH 34/78] Update README.md --- README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2b1bd53..fd5755f 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,8 @@ In the original paper, Duelist Algorithm was shown to out-perform a few state-of # Dependencies This algorithm is fully implemented in Python. It is recommended to use Python 3.X. Library dependencies: - numpy 1.15.4 -``` + +```BASH $ pip install numpy ``` @@ -40,26 +41,26 @@ $ pip install numpy # How to Use 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 ``` @@ -71,20 +72,20 @@ $ cd examples ** 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"] ``` @@ -105,14 +106,14 @@ x=["x1","x2"] Max. bound | 10 | 15 | -``` -> xmin=[-2,5] -> xmax=[10,15] +```python + xmin=[-2,5] + xmax=[10,15] ``` -> 4. Setup the solver and start the solve procedure. +** 4. Setup the solver and start the solve procedure. ** -``` +```python DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=1000) DA.solve() ``` From c72a4fb8ddf149a862ff4cb2567bfb281dc5c874 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:20:23 +0200 Subject: [PATCH 35/78] Update README.md --- README.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/README.md b/README.md index fd5755f..a1d82fb 100644 --- a/README.md +++ b/README.md @@ -97,14 +97,7 @@ x=["x1","x2"] x2 is bounded from 10 to 15 (10 is min value of x2 and 15 is max value of x2) - We can arrange this in a table that can be easily read: - - Variables | "x1" | "x2" | - - Min. bound | -2 | 5 | - - Max. bound | 10 | 15 | - + We can arrange these boundaries according to the definition array in step 2. ```python xmin=[-2,5] From dff53c7ef768b5415ba25086e6940ef77db03713 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:20:53 +0200 Subject: [PATCH 36/78] Delete solve_simple.py --- solve_simple.py | 61 ------------------------------------------------- 1 file changed, 61 deletions(-) delete mode 100644 solve_simple.py diff --git a/solve_simple.py b/solve_simple.py deleted file mode 100644 index 5104eb1..0000000 --- a/solve_simple.py +++ /dev/null @@ -1,61 +0,0 @@ -from solver.Duelist_Algorithm import DuelistAlgorithm - -''' -Here we have a simple squared equation that we want to optimize (minimize). -The equation is y=(x1)^2+(x2)^2 - 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) -''' - - -''' -First we define the function: -The equation is f=(x1,x2) = y = (x1)^2+(x2)^2 -''' -def f(x1,x2): - return x1*x1+x2*x2 - -''' -Secondly, we name the optimization variables and tell the solver how many variables to optimize. -We can do this by putting in the names of the variables as strings in an array. -''' -x=["x1","x2"] - -''' -The thirds step is to specify the boundary for each variables - "x1" "x2" -min -2 5 -max 10 15 - -This xmin and xmax array follows the position of the array you define at second step. -''' - -xmin=[-2,5] -xmax=[10,15] - -''' -DA.DuelistAlgorithm(function output=f, - names of manipulated variables= x, - lower limit of manipulated variables= xmin, - upper limit of manipulated variables = xmax, - population size=pop (default=200), - luck factor=luck (default=0.01), - innovative/mutation factor= mut (default=0.1), - learning probability= learn (default=0.8), - maximum generation= max_gen (default=500), - number of champions per selection=nc (default=5), - is shuffling required before duel?=shuffle (default=False) - ) - -You do not need to fill in variables with default values. They are for fine tuning the algorithm. -''' - -#Increase the maximum generation for more precise answer -DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=1000) -DA.solve() - -''' -You should see the answer, it should look something like the following: - -Optimized using Duelist Algorithm. Answer is: [1.70085713e-03 5.00016813e+00] with fitness of 25.00168420123805 -''' \ No newline at end of file From ebfdeda487b02e7d31b32c8ae3dd0699c3820082 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:22:42 +0200 Subject: [PATCH 37/78] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index a1d82fb..73f17dc 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,9 @@ DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=1000) DA.solve() ``` +For more examples refer to the python scripts in "examples" folder. [https://github.com/tsyet12/Duelist-Algorithm-Python/tree/master/examples] + + # Version Currently Version 1.0 From e4a40634abd65551bbb9696411226661cb87ee51 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:56:09 +0200 Subject: [PATCH 38/78] Update README.md --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 73f17dc..3f5f5ce 100644 --- a/README.md +++ b/README.md @@ -108,9 +108,19 @@ x=["x1","x2"] ```python DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=1000) -DA.solve() +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. So Duelist Algorithm performs well. +![result1](images/results.PNG) +*Fig 4. Optimal Results in Console* + +We can see that the algorithm quickly converges to the optimal point (see Fig. 5) as reported by the original article. +![result2](images/results2.PNG) + + For more examples refer to the python scripts in "examples" folder. [https://github.com/tsyet12/Duelist-Algorithm-Python/tree/master/examples] From 191fe90b0ff662c8773ac5513b7c03053525a037 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:56:21 +0200 Subject: [PATCH 39/78] added plot --- examples/2_solve_multivariate.py | 2 +- images/results.PNG | Bin 0 -> 12613 bytes images/results2.png | Bin 0 -> 23818 bytes solver/Duelist_Algorithm.py | 27 ++++++++++++++++-- .../Duelist_Algorithm.cpython-36.pyc | Bin 5780 -> 6454 bytes 5 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 images/results.PNG create mode 100644 images/results2.png diff --git a/examples/2_solve_multivariate.py b/examples/2_solve_multivariate.py index 2b5a861..a45c7ed 100644 --- a/examples/2_solve_multivariate.py +++ b/examples/2_solve_multivariate.py @@ -60,7 +60,7 @@ def f(x1,x2): #Increase the maximum generation for more precise answer DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=1000) -DA.solve() +DA.solve(plot=True) ''' You should see the answer, it should look something like the following: diff --git a/images/results.PNG b/images/results.PNG new file mode 100644 index 0000000000000000000000000000000000000000..8c910320934de5979f5ac956a98b833b43756b9e GIT binary patch literal 12613 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 literal 0 HcmV?d00001 diff --git a/images/results2.png b/images/results2.png new file mode 100644 index 0000000000000000000000000000000000000000..4dd76cd11ae7145ca72fa443f4bbf209603ff506 GIT binary patch literal 23818 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 H0sa01Ktmzk From 46faabbfd04bc449d09ef72a8415d9ac9622ed63 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:57:40 +0200 Subject: [PATCH 40/78] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3f5f5ce..b053f36 100644 --- a/README.md +++ b/README.md @@ -113,12 +113,12 @@ 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. So Duelist Algorithm performs well. +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. So Duelist Algorithm performs well. ![result1](images/results.PNG) *Fig 4. Optimal Results in Console* We can see that the algorithm quickly converges to the optimal point (see Fig. 5) as reported by the original article. -![result2](images/results2.PNG) +![result2](images/results2.png) For more examples refer to the python scripts in "examples" folder. [https://github.com/tsyet12/Duelist-Algorithm-Python/tree/master/examples] From 2117a6c26078e6f3c9777c430eb193b62eca17ef Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:58:29 +0200 Subject: [PATCH 41/78] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b053f36..ad49996 100644 --- a/README.md +++ b/README.md @@ -135,8 +135,8 @@ Currently Version 1.0 - [X] Update ReadMe -- [ ] Add plot functions +- [X] Add plot functions - [ ] Add a modified feature for faster convergence -- [ ] Add result loging +- [ ] Add result loging and export to csv From e3704bedbcc51da5db987dd34439242f976a1fff Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 13:59:53 +0200 Subject: [PATCH 42/78] Update README.md --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index ad49996..77f8d3b 100644 --- a/README.md +++ b/README.md @@ -140,3 +140,10 @@ Currently Version 1.0 - [ ] Add a modified feature for faster convergence - [ ] Add result loging 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 From 3e9882ed80b3c5cbbf8d1e8f1f087c1a3bc86a0c Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 14:08:30 +0200 Subject: [PATCH 43/78] Update README.md --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 77f8d3b..a673c1b 100644 --- a/README.md +++ b/README.md @@ -113,13 +113,15 @@ 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. So Duelist Algorithm performs well. +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* We can see that the algorithm quickly converges to the optimal point (see Fig. 5) as reported by the original article. -![result2](images/results2.png) +![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] From b60191038a0e51d50e782d22f9e2a69f2d8c3e6f Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 14:09:04 +0200 Subject: [PATCH 44/78] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a673c1b..d37d942 100644 --- a/README.md +++ b/README.md @@ -116,11 +116,13 @@ DA.solve(plot=True) 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* We can see that the algorithm quickly converges to the optimal point (see Fig. 5) as reported by the original article. ![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] From fbf013e25ba24d335e2e1802a48f6b7794d9322a Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 14:10:39 +0200 Subject: [PATCH 45/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d37d942..9bc724d 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ From the console we can deduce the optimal result (see Fig. 4) . The global opti *Fig 4. Optimal Results in Console* -We can see that the algorithm quickly converges to the optimal point (see Fig. 5) as reported by the original article. +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) From caaab84eb45fe05186aa0f6587798f61c89b9ef5 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Fri, 26 Apr 2019 14:11:26 +0200 Subject: [PATCH 46/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9bc724d..3de22ab 100644 --- a/README.md +++ b/README.md @@ -143,7 +143,7 @@ Currently Version 1.0 - [ ] Add a modified feature for faster convergence -- [ ] Add result loging and export to csv +- [ ] Add result logging and export to csv # Contact Me From 5746c6694ed2806d6b81d131b43df971546b5bec Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 09:46:03 +0200 Subject: [PATCH 47/78] travis --- pytest.py | 8 ++++++++ requirements.txt | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 pytest.py diff --git a/pytest.py b/pytest.py new file mode 100644 index 0000000..c80366c --- /dev/null +++ b/pytest.py @@ -0,0 +1,8 @@ +from solver.Duelist_Algorithm import DuelistAlgorithm +def f(x): + return x*0.5 +x=["x1"] +xmin=[-2] +xmax=[10] +DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=100) +DA.solve() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index b01e669..72baa0b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ -numpy==1.15.4 \ No newline at end of file +numpy==1.15.4 +matplotlib==3.0.2 \ No newline at end of file From b7f0186a0e7fee859583220985dbd904cbad9b03 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 09:52:02 +0200 Subject: [PATCH 48/78] travis --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..dc4d4b7 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: python +python: + - "3.4" + - "3.5" + - "3.6" +# command to install dependencies +install: + - pip install -r requirements.txt +# command to run tests +script: + - pytest \ No newline at end of file From 57b88aa329f911bf692794996e2a7d9e515b33bc Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 09:57:24 +0200 Subject: [PATCH 49/78] travis2 --- tests/auth_test.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tests/auth_test.py diff --git a/tests/auth_test.py b/tests/auth_test.py new file mode 100644 index 0000000..c80366c --- /dev/null +++ b/tests/auth_test.py @@ -0,0 +1,8 @@ +from solver.Duelist_Algorithm import DuelistAlgorithm +def f(x): + return x*0.5 +x=["x1"] +xmin=[-2] +xmax=[10] +DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=100) +DA.solve() \ No newline at end of file From 58dc671c20ab5d10cb54a623d883aa26634aa524 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 10:14:22 +0200 Subject: [PATCH 50/78] requirement --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 72baa0b..3e566f4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ numpy==1.15.4 -matplotlib==3.0.2 \ No newline at end of file +matplotlib \ No newline at end of file From 84aebbd7b84b2619744499a9e25c4cfce7e798fc Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 10:20:50 +0200 Subject: [PATCH 51/78] test --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dc4d4b7..d0cd79e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,4 @@ install: - pip install -r requirements.txt # command to run tests script: - - pytest \ No newline at end of file + - python setup.py test \ No newline at end of file From aefd694a034909c17f9c2789a1e7c22e11807e7a Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 10:22:11 +0200 Subject: [PATCH 52/78] tests --- tests/auth_test.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/auth_test.py b/tests/auth_test.py index c80366c..782de1c 100644 --- a/tests/auth_test.py +++ b/tests/auth_test.py @@ -5,4 +5,6 @@ def f(x): xmin=[-2] xmax=[10] DA=DuelistAlgorithm(f,x,xmin,xmax,max_gen=100) -DA.solve() \ No newline at end of file +DA.solve() + +print("test sucessful") \ No newline at end of file From ade87e2cdc86d071ff04f7fbbfe0b443045a0acf Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 10:29:22 +0200 Subject: [PATCH 53/78] travis --- tests/{auth_test.py => solve_test.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename tests/{auth_test.py => solve_test.py} (100%) diff --git a/tests/auth_test.py b/tests/solve_test.py similarity index 100% rename from tests/auth_test.py rename to tests/solve_test.py From ee2ea1faac43a6b38316a8e9f811618490e401cc Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 10:31:43 +0200 Subject: [PATCH 54/78] travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d0cd79e..f11d8d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,4 @@ install: - pip install -r requirements.txt # command to run tests script: - - python setup.py test \ No newline at end of file + - python setup.py tests/solve_test.py \ No newline at end of file From c5ccd6eae11ea4321d081aedf3c6ba61d1c8d0ed Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 10:35:10 +0200 Subject: [PATCH 55/78] treavis1 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f11d8d6..b5734cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,4 @@ install: - pip install -r requirements.txt # command to run tests script: - - python setup.py tests/solve_test.py \ No newline at end of file + - python setup.py pytest \ No newline at end of file From e49b04a5f4bffcbb92eba74882bfcfaca6dfd4af Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 10:37:35 +0200 Subject: [PATCH 56/78] treavis1 --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b5734cb..8f0bb1b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,5 @@ install: - pip install -r requirements.txt # command to run tests script: - - python setup.py pytest \ No newline at end of file + - python setup.py + - pytest \ No newline at end of file From f8ae4d6b1314d6c5f28dd6eb79970d7e321f01e6 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 10:42:43 +0200 Subject: [PATCH 57/78] travis2 --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8f0bb1b..240d17c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,4 +9,4 @@ install: # command to run tests script: - python setup.py - - pytest \ No newline at end of file + - python tests/solve_test.py \ No newline at end of file From 945a37891b01367c13ea1a854715413aae56db47 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 10:49:49 +0200 Subject: [PATCH 58/78] travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 240d17c..b34a7e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,5 +8,5 @@ install: - pip install -r requirements.txt # command to run tests script: - - python setup.py + - python setup.py install - python tests/solve_test.py \ No newline at end of file From d363eaa72ebb3db0f7ba27cdca0e7e129f8cd0f9 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 11:05:03 +0200 Subject: [PATCH 59/78] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 3de22ab..f62e4ed 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,15 @@ x=["x1","x2"] 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 | - We can arrange these boundaries according to the definition array in step 2. +The corresponding code is: ```python xmin=[-2,5] From d0bf3d046260cef3dbb21632c6ca0f9983d8edbc Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 12:01:35 +0200 Subject: [PATCH 60/78] Update README.md --- README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.md b/README.md index f62e4ed..3a87908 100644 --- a/README.md +++ b/README.md @@ -135,6 +135,18 @@ We can see that the algorithm quickly converges to the optimal point (see Fig. 5 For more examples refer to the python scripts in "examples" folder. [https://github.com/tsyet12/Duelist-Algorithm-Python/tree/master/examples] +# Small Tutorial on Complex Constraint using Karush-Kuhn-Tucker (KKT) conditions + +There will be some problems that have complex constraints. For example, constraints which depends on two or more manipulated variables. + +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 + +Using KKT conditions, we can put this constraint in the objective function: + +f=(x1,x2) = (x1)^2+(x2)^2 + ( + + # Version Currently Version 1.0 From da9429012dc891313640538a757363d0f0c8203a Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 12:33:09 +0200 Subject: [PATCH 61/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3a87908..999f542 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Duelist-Algorithm-Python [![Build Status](https://travis-ci.com/tsyet12/Duelist-Algorithm-Python.svg?branch=master)](https://travis-ci.com/tsyet12/Duelist-Algorithm-Python) +# 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) 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 From 1af451b4b5699f58fa2b1ba6db230440e52b9580 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 12:35:03 +0200 Subject: [PATCH 62/78] Create CODE_OF_CONDUCT.md --- CODE_OF_CONDUCT.md | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 CODE_OF_CONDUCT.md 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 From c2e7d6507d9b04a0279813293a83d0c69d62957c Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 12:52:19 +0200 Subject: [PATCH 63/78] Update README.md --- README.md | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 999f542..486c4b7 100644 --- a/README.md +++ b/README.md @@ -135,16 +135,45 @@ We can see that the algorithm quickly converges to the optimal point (see Fig. 5 For more examples refer to the python scripts in "examples" folder. [https://github.com/tsyet12/Duelist-Algorithm-Python/tree/master/examples] -# Small Tutorial on Complex Constraint using Karush-Kuhn-Tucker (KKT) conditions +# Dealing with Complex Constraint using Karush-Kuhn-Tucker (KKT) conditions There will be some problems that have complex constraints. For example, constraints which depends on two or more manipulated variables. -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: +*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 Using KKT conditions, we can put this constraint in the objective function: -f=(x1,x2) = (x1)^2+(x2)^2 + ( +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: + +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 From f21946ab25270e88b437d5752a0d3df0d21a1cc2 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 13:06:48 +0200 Subject: [PATCH 64/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 486c4b7..79a4121 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 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) +# 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) (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 From 37568498cc1eedfda02a5b643c4f446ef3c6277a Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 13:07:04 +0200 Subject: [PATCH 65/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 79a4121..62bf503 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 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) (https://img.shields.io/badge/Python-3.4%20%7C%203.5%20%7C%203.6%20%7C%203.7-brightgreen.svg) +# 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) [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 From a584b6acd600b14c4a27abcdf6aa3e301aef6979 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 13:07:56 +0200 Subject: [PATCH 66/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 62bf503..0694bda 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 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) [https://img.shields.io/badge/Python-3.4%20%7C%203.5%20%7C%203.6%20%7C%203.7-brightgreen.svg] +# 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 From 8404e4e76d8e4f2d55306207d6ed3418156ef600 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 13:10:59 +0200 Subject: [PATCH 67/78] Update README.md --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index 0694bda..ee85d46 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,11 @@ $ pip install numpy # How to Use + +You can use two methods for installation: + +**1. From here (recommended as this will update faster)** + 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 @@ -64,6 +69,22 @@ Move to examples and run the examples $ cd examples ``` +**1. From pip ** +You can try installing 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** From 9c5afc2ec8e34b23bbc8b0fb0e58546ae45b2526 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 29 Apr 2019 13:28:24 +0200 Subject: [PATCH 68/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ee85d46..7521e95 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ This algorithm is fully implemented in Python. It is recommended to use Python 3 - numpy 1.15.4 ```BASH -$ pip install numpy +$ pip install numpy matplotlib ``` From 10880fb4acfd94e2d4dafbd5342e697bc3665367 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Tue, 30 Apr 2019 10:09:38 +0200 Subject: [PATCH 69/78] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 7521e95..1417ad7 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,9 @@ 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 + +Using KKT conditions, we can put this constraint in the objective function: f=(x1,x2) = (x1)^2+(x2)^2 + (x2-x1)^2 From 338b13e627e30f6784788af9357108be212cdd7f Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Tue, 30 Apr 2019 10:10:31 +0200 Subject: [PATCH 70/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1417ad7..7193ef5 100644 --- a/README.md +++ b/README.md @@ -145,7 +145,7 @@ From the console we can deduce the optimal result (see Fig. 4) . The global opti ![result1](images/results.PNG) -*Fig 4. Optimal Results in Console* +*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. From a0b250028c28eeba0a406b8c275fce49013adf0a Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Tue, 30 Apr 2019 10:12:26 +0200 Subject: [PATCH 71/78] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 7193ef5..21489e1 100644 --- a/README.md +++ b/README.md @@ -182,8 +182,10 @@ 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 Using KKT conditions, we can put this constraint in the objective function: From a80dac0981d83a17fdf2ebf121c0435b069adf71 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 13 May 2019 09:56:12 +0200 Subject: [PATCH 72/78] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 21489e1..63fc7d2 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ In the original paper, Duelist Algorithm was shown to out-perform a few state-of # 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 From 94889d06c34c9722aef9598b360c417a1724cebb Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 13 May 2019 10:06:48 +0200 Subject: [PATCH 73/78] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 63fc7d2..f930635 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ $ pip install numpy matplotlib You can use two methods for installation: -**1. From here (recommended as this will update faster)** +***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 @@ -70,7 +70,7 @@ Move to examples and run the examples $ cd examples ``` -**1. From pip ** +***1. Install from pip *** You can try installing this package from pip. Linux: From 12228e46ce1a14237c04ead9f69378baf00025ff Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 13 May 2019 10:07:52 +0200 Subject: [PATCH 74/78] Update README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f930635..328dce2 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ $ pip install numpy matplotlib You can use two methods for installation: -***1. Install from github (recommended as this will download the newest version)*** +**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 @@ -70,8 +70,9 @@ Move to examples and run the examples $ cd examples ``` -***1. Install from pip *** -You can try installing this package from pip. +**1. Install from pip ** + +You can install this package from pip. Linux: From 3119664061bac504e3b58b33eadf19ef02031a16 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Thu, 16 May 2019 09:46:00 +0200 Subject: [PATCH 75/78] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 328dce2..bfd0dd5 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,11 @@ 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. From 69b1e16a578f4cbeb3b5deeec5e04434c6f95a52 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 18 Jan 2021 16:09:52 +0100 Subject: [PATCH 76/78] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bfd0dd5..9e4ab3b 100644 --- a/README.md +++ b/README.md @@ -163,7 +163,7 @@ We can see that the algorithm quickly converges to the optimal point (see Fig. 5 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 using Karush-Kuhn-Tucker (KKT) conditions +# 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. From ac716c05ed9dfa07ffe4388c1b9ec9f425422aa9 Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Mon, 18 Jan 2021 16:11:20 +0100 Subject: [PATCH 77/78] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9e4ab3b..1297373 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ We take the same problem from the **Short Tutorial**, and now we have an extra c > x1>x2 -Using KKT conditions, we can put this constraint in the objective function: +We can put this constraint in the objective function: f=(x1,x2) = (x1)^2+(x2)^2 + max(0,x2-x1) @@ -195,7 +195,7 @@ We take the same problem from the **Short Tutorial**, and now the extra constrai > x1=x2 -Using KKT conditions, we can put this constraint in the objective function: +We can put this constraint in the objective function: f=(x1,x2) = (x1)^2+(x2)^2 + (x2-x1)^2 From f32038a572472890f40159b170f8b48050bb349c Mon Sep 17 00:00:00 2001 From: Sin Yong Teng Date: Wed, 29 Jun 2022 12:32:30 +0200 Subject: [PATCH 78/78] Update requirements.txt --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 3e566f4..aa094d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -numpy==1.15.4 -matplotlib \ No newline at end of file +numpy +matplotlib