Skip to content

Commit

Permalink
Merge branch 'dme'
Browse files Browse the repository at this point in the history
  • Loading branch information
dme65 committed Apr 27, 2017
2 parents 43c25d7 + 58ab3f7 commit f3c1b30
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 4 deletions.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
v.0.1.35, 2017-04-29
--------------------

- Added support for termination based on elapsed time
- Added the Hartman6 test problem

v.0.1.34, 2017-03-28
--------------------

Expand Down
19 changes: 16 additions & 3 deletions pySOT/sot_sync_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from pySOT.rbf import *
from pySOT.utils import *
from pySOT.rs_wrappers import *
import time

# Get module-level logger
logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -50,7 +51,9 @@ class SyncStrategyNoConstraints(BaseStrategy):
:type data: Object
:param response_surface: Surrogate model object
:type response_surface: Object
:param maxeval: Function evaluation budget
:param maxeval: Stopping criterion. If positive, this is an
evaluation budget. If negative, this is a time
budget in seconds.
:type maxeval: int
:param nsamples: Number of simultaneous fevals allowed
:type nsamples: int
Expand All @@ -68,14 +71,23 @@ class SyncStrategyNoConstraints(BaseStrategy):
def __init__(self, worker_id, data, response_surface, maxeval, nsamples,
exp_design=None, sampling_method=None, extra=None, extra_vals=None):

# Check stopping criterion
self.start_time = time.time()
if maxeval < 0: # Time budget
self.maxeval = np.inf
self.time_budget = np.abs(maxeval)
else:
self.maxeval = maxeval
self.time_budget = np.inf

# Import problem information
self.worker_id = worker_id
self.data = data
self.fhat = response_surface
if self.fhat is None:
self.fhat = RBFInterpolant(kernel=CubicKernel, tail=LinearTail, maxp=maxeval)
self.fhat.reset() # Just to be sure!

self.maxeval = maxeval
self.nsamples = nsamples
self.extra = extra
self.extra_vals = extra_vals
Expand Down Expand Up @@ -287,7 +299,8 @@ def start_batch(self):
def propose_action(self):
"""Propose an action"""

if self.numeval == self.maxeval:
current_time = time.time()
if self.numeval >= self.maxeval or (current_time - self.start_time) >= self.time_budget:
return self.propose_terminate()
elif self.resubmitter.num_eval_outstanding == 0:
self.start_batch()
Expand Down
1 change: 1 addition & 0 deletions pySOT/test/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ all:
.PHONY: test
test: sphere_ext sphere_ext_files sumfun_ext
python test_simple.py
python test_simple_time.py
python test_rbf.py
python test_penalty.py
python test_projection.py
Expand Down
66 changes: 66 additions & 0 deletions pySOT/test/test_simple_time.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
.. module:: test_simple_time
:synopsis: Test Simple with time budget
.. moduleauthor:: David Eriksson <[email protected]>
"""

from pySOT import Ackley, SyncStrategyNoConstraints, \
SymmetricLatinHypercube, RBFInterpolant, CubicKernel, \
LinearTail, CandidateDYCORS
from poap.controller import ThreadController, BasicWorkerThread
import numpy as np
import os.path
import logging
import time


def main():
if not os.path.exists("./logfiles"):
os.makedirs("logfiles")
if os.path.exists("./logfiles/test_simple_time.log"):
os.remove("./logfiles/test_simple_time.log")
logging.basicConfig(filename="./logfiles/test_simple_time.log",
level=logging.INFO)

print("\nNumber of threads: 4")
print("Time budget: 30 seconds")
print("Sampling method: CandidateDYCORS")
print("Experimental design: Symmetric Latin Hypercube")
print("Surrogate: Cubic RBF")

nthreads = 4
maxeval = -30
nsamples = nthreads

data = Ackley(dim=10)
print(data.info)

# Create a strategy and a controller
controller = ThreadController()
controller.strategy = \
SyncStrategyNoConstraints(
worker_id=0, data=data,
maxeval=maxeval, nsamples=nsamples,
exp_design=SymmetricLatinHypercube(dim=data.dim, npts=2*(data.dim+1)),
response_surface=RBFInterpolant(kernel=CubicKernel, tail=LinearTail,
maxp=1000),
sampling_method=CandidateDYCORS(data=data, numcand=100*data.dim))

# Launch the threads and give them access to the objective function
for _ in range(nthreads):
worker = BasicWorkerThread(controller, data.objfunction)
controller.launch_worker(worker)

# Run the optimization strategy
start_time = time.time()
result = controller.run()
end_time = time.time()

print('Run time: {0} seconds'.format(end_time - start_time))
print('Best value found: {0}'.format(result.value))
print('Best solution found: {0}\n'.format(
np.array_str(result.params[0], max_line_width=np.inf,
precision=5, suppress_small=True)))

if __name__ == '__main__':
main()
66 changes: 66 additions & 0 deletions pySOT/test_problems.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,72 @@ def objfunction(self, x):
outer += alpha[ii] * np.exp(-inner)
return -outer


class Hartman6:
"""Hartman 6 function
Details: http://www.sfu.ca/~ssurjano/hart6.html
Global optimum: :math:`f(0.20169,0.150011,0.476874,0.275332,0.311652,0.6573)=-3.32237`
:param dim: Number of dimensions (has to be = 6)
:type dim: int
:ivar dim: Number of dimensions
:type dim: int
:ivar xlow: Lower bound constraints
:type xlow: numpy.array
:ivar xup: Upper bound constraints
:type xup: numpy.array
:ivar info: Problem information
:type info: string
:ivar min: Global optimum
:type min: float
:ivar integer: Integer variables
:type integer: numpy.array
:ivar continuous: Continuous variables
:type continuous: numpy.array
"""

def __init__(self, dim=6):
self.xlow = np.zeros(6)
self.xup = np.ones(6)
self.dim = 6
self.info = "6-dimensional Hartman function \nGlobal optimum: " + \
"f(0.20169,0.150011,0.476874,0.275332,0.311652,0.6573) = -3.32237"
self.min = -3.32237
self.integer = []
self.continuous = np.arange(0, 6)
check_opt_prob(self)

def objfunction(self, x):
"""Evaluate the Hartman 3 function at x
:param x: Data point
:return: Value at x
"""
if len(x) != self.dim:
raise ValueError('Dimension mismatch')
alpha = np.array([1.0, 1.2, 3.0, 3.2])
A = np.matrix([[10.0, 3.0, 17.0, 3.5, 1.7, 8.0 ],
[0.05, 10.0, 17.0, 0.1, 8.0, 14.0],
[3.0, 3.5, 1.7, 10.0, 17.0, 8.0 ],
[17.0, 8.0, 0.05, 10.0, 0.1, 14.0]])
P = 1E-4 * np.matrix([[1312.0, 1696.0, 5569.0, 124.0, 8283.0, 5886.0],
[2329.0, 4135.0, 8307.0, 3736.0, 1004.0, 9991.0],
[2348.0, 1451.0, 3522.0, 2883.0, 3047.0, 6650.0],
[4047.0, 8828.0, 8732.0, 5743.0, 1091.0, 381.0]])
outer = 0
for ii in range(4):
inner = 0
for jj in range(6):
xj = x[jj]
Aij = A[ii, jj]
Pij = P[ii, jj]
inner += Aij * ((xj - Pij) ** 2)
outer += alpha[ii] * np.exp(-inner)
return -outer

# ========================= n-dimensional =======================


Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

setup(
name='pySOT',
version='0.1.34',
version='0.1.35',
packages=['pySOT', 'pySOT.test'],
url='https://github.com/dme65/pySOT',
license='LICENSE.rst',
Expand Down

0 comments on commit f3c1b30

Please sign in to comment.