Skip to content

Commit

Permalink
example of irace for optframe on linux
Browse files Browse the repository at this point in the history
  • Loading branch information
igormcoelho committed Dec 19, 2023
1 parent 538699d commit 4ef702f
Show file tree
Hide file tree
Showing 18 changed files with 1,245 additions and 0 deletions.
5 changes: 5 additions & 0 deletions demo/05_QuickstartTSP_IRACE/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
demo_*
*.stdout
*.stderr
*.Rdata

6 changes: 6 additions & 0 deletions demo/05_QuickstartTSP_IRACE/InstancesTest/tsp-example.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
5
1 10 10
2 20 20
3 30 30
4 40 40
5 50 50
6 changes: 6 additions & 0 deletions demo/05_QuickstartTSP_IRACE/InstancesTraining/tsp-example.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
5
1 10 10
2 20 20
3 30 30
4 40 40
5 50 50
15 changes: 15 additions & 0 deletions demo/05_QuickstartTSP_IRACE/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## 05_QuickstartTSP_IRACE

This example demonstrates how to integrate irace with optframe python (in linux).

Just run:

```
make vendor
make run
```


### Acknowledgements

Thanks Henrique @henriqueborgesv for the advices on irace for optframe.
158 changes: 158 additions & 0 deletions demo/05_QuickstartTSP_IRACE/TSP-fcore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# OptFrame Python Demo TSP - Traveling Salesman Problem

from typing import List
import random

from optframe import *
from optframe.protocols import *


class SolutionTSP(object):
def __init__(self):
# number of cities in solution
self.n : int = 0
# visited cities as a list
self.cities : List[int] = []

# MUST provide some printing mechanism
def __str__(self):
return f"SolutionTSP(n={self.n};cities={self.cities})"

class ProblemContextTSP(object):
def __init__(self):
# float engine for OptFrame
self.engine = Engine(APILevel.API1d)
# number of cities
self.n = 0
# x coordinates
self.vx = []
# y coordinates
self.vy = []
# distance matrix
self.dist = []

# Example: "3\n1 10 10\n2 20 20\n3 30 30\n"

def load(self, filename: str):
with open(filename, 'r') as f:
lines = f.readlines()
self.n = int(lines[0])
for i in range(self.n):
id_x_y = lines[i+1].split()
# ignore id_x_y[0]
self.vx.append(int(id_x_y[1]))
self.vy.append(int(id_x_y[2]))
#
self.dist = [[0 for col in range(self.n)] for row in range(self.n)]
for i in range(self.n):
for j in range(self.n):
self.dist[i][j] = round(self.euclidean(self.vx[i], self.vy[i], self.vx[j], self.vy[j]))

def euclidean(self, x1, y1, x2, y2):
import math
return math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))

def __str__(self):
return f"ProblemContextTSP(n={self.n};vx={self.vx};vy={self.vy};dist={self.dist})"
# continuation of ProblemContextTSP class...
@staticmethod
def minimize(pTSP: 'ProblemContextTSP', s: SolutionTSP) -> float:
assert (s.n == pTSP.n)
assert (len(s.cities) == s.n)
# remember this is an API1d method
f = 0.0
for i in range(pTSP.n-1):
f += pTSP.dist[s.cities[i]][s.cities[i + 1]];
f += pTSP.dist[s.cities[int(pTSP.n) - 1]][s.cities[0]];
return f
# continuation of ProblemContextTSP class...
@staticmethod
def generateSolution(problemCtx: 'ProblemContextTSP') -> SolutionTSP:
sol = SolutionTSP()
for i in range(problemCtx.n):
sol.cities.append(i)
random.shuffle(sol.cities)
sol.n = problemCtx.n
return sol

# optional tests...
assert isinstance(SolutionTSP, XSolution) # composition tests
assert isinstance(ProblemContextTSP, XProblem) # composition tests
assert isinstance(ProblemContextTSP, XConstructive) # composition tests
assert isinstance(ProblemContextTSP, XMinimize) # composition tests

from optframe.components import Move

class MoveSwapClass(Move):
def __init__(self, _i: int = 0, _j: int = 0):
self.i = _i
self.j = _j
def __str__(self):
return "MoveSwapClass(i="+str(self.i)+";j="+str(self.j)+")"
def apply(self, problemCtx, sol: SolutionTSP) -> 'MoveSwapClass':
aux = sol.cities[self.j]
sol.cities[self.j] = sol.cities[self.i]
sol.cities[self.i] = aux
# must create reverse move (j,i)
return MoveSwapClass(self.j, self.i)
def canBeApplied(self, problemCtx, sol: SolutionTSP) -> bool:
return True
def eq(self, problemCtx, m2: 'MoveSwapClass') -> bool:
return (self.i == m2.i) and (self.j == m2.j)

assert isinstance(MoveSwapClass, XMove) # composition tests
assert MoveSwapClass in Move.__subclasses__() # classmethod style

#from optframe.components import NS

class NSSwap(object):
@staticmethod
def randomMove(pTSP, sol: SolutionTSP) -> MoveSwapClass:
import random
n = sol.n
i = random.randint(0, n - 1)
j = i
while j <= i:
i = random.randint(0, n - 1)
j = random.randint(0, n - 1)
# return MoveSwap(i, j)
return MoveSwapClass(i, j)

#assert NSSwap in NS.__subclasses__() # optional test

#from optframe.components import NSSeq
from optframe.components import NSIterator

# For NSSeq, one must provide a Move Iterator
# A Move Iterator has five actions: Init, First, Next, IsDone and Current

class IteratorSwap(NSIterator):
def __init__(self, _i: int, _j: int):
self.i = _i
self.j = _j
def first(self, pTSP: ProblemContextTSP):
self.i = 0
self.j = 1
def next(self, pTSP: ProblemContextTSP):
if self.j < pTSP.n - 1:
self.j = self.j+1
else:
self.i = self.i + 1
self.j = self.i + 1
def isDone(self, pTSP: ProblemContextTSP):
return self.i >= pTSP.n - 1
def current(self, pTSP: ProblemContextTSP):
return MoveSwapClass(self.i, self.j)

assert IteratorSwap in NSIterator.__subclasses__() # optional test

class NSSeqSwap(object):
@staticmethod
def randomMove(pTSP: ProblemContextTSP, sol: SolutionTSP) -> MoveSwapClass:
return NSSwap.randomMove(pTSP, sol) # composition

@staticmethod
def getIterator(pTSP: ProblemContextTSP, sol: SolutionTSP) -> IteratorSwap:
return IteratorSwap(-1, -1)

#assert NSSeqSwap in NSSeq.__subclasses__() # optional test
15 changes: 15 additions & 0 deletions demo/05_QuickstartTSP_IRACE/configurations.txt.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Template for specifying initial parameter configurations, for
## example, the default configuration, in irace.
##
## This filename must be specified via the --candidates-file command-line option
## (or candidatesFile in scenario.txt).
##
## The format is one parameter configuration per line, and one parameter per
## column. The first line gives the parameter name corresponding to
## each column (names must match those given in the parameters
## file). Each configuration must satisfy the
## parameter conditions (NA should be used for those parameters that
## are not enabled for a given configuration) and, if given, the
## constraints that describe forbidden configurations.
param1 param2 mode real mutation
5 NA "x2" 2.0 "low"
14 changes: 14 additions & 0 deletions demo/05_QuickstartTSP_IRACE/forbidden.txt.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## Template for specifying forbidden parameter configurations in irace.
##
## This filename must be specified via the --forbidden-file command-line option
## (or forbiddenFile in scenario.txt).
##
## The format is one constraint per line. Each constraint is a logical
## expression (in R syntax). If a parameter configuration
## is generated that makes the logical expression evaluate to TRUE,
## then the configuration is discarded.
##
## Examples of valid logical operators are: == != >= <= > < & | ! %in%
param1 < 5 & mode == "x1"
(param2 > 6 & mode == "x1") | (param2 <= 6 & mode == "x2")
real < 4 & mode %in% c("x2", "x3")
12 changes: 12 additions & 0 deletions demo/05_QuickstartTSP_IRACE/instances-list.txt.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## This is an example of specifying a list of instances.

# Each line is an instance relative to trainInstancesDir/testInstancesdir
# unless set to "" (see scenario.txt.tmpl) and an optional sequence of
# instance-specific parameters that will be passed to target-runner when
# invoked on that instance.

# Empty lines and comments are ignored.

100/100-1_100-2.tsp --time 1
100/100-1_100-3.tsp --time 2
100/100-1_100-4.tsp --time 3
Loading

0 comments on commit 4ef702f

Please sign in to comment.