Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ scenic = "^2.1.0b4"
progressbar2 = "^3.53.1"
networkx = "^2.6.3"
statsmodels = "^0.13.2"
glis = ">=2"

GPy = {version = "^1.9.9", optional = true}
GPyOpt = {version = "^1.2.6", optional = true}
Expand Down
17 changes: 17 additions & 0 deletions src/verifai/samplers/feature_sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from verifai.samplers.bayesian_optimization import BayesOptSampler
from verifai.samplers.simulated_annealing import SimulatedAnnealingSampler
from verifai.samplers.grid_sampler import GridSampler
from verifai.samplers.glis_optimization import GLISSampler

### Samplers defined over FeatureSpaces

Expand Down Expand Up @@ -149,6 +150,22 @@ def makeDomainSampler(domain):
makeRandomSampler)
return LateFeatureSampler(space, RandomSampler, makeDomainSampler)

def glisSamplerFor(space, params):
"""Creates a GLIS Optimization sampler for a given space.
Uses random sampling for lengths of feature lists and any
Domains that are not continous and standardizable.
"""

def makeDomainSampler(domain):
return SplitSampler.fromPredicate(
domain,
lambda d: d.standardizedDimension > 0,
lambda domain: GLISSampler(domain=domain,
params=params),
makeRandomSampler)

return LateFeatureSampler(space, RandomSampler, makeDomainSampler)

def getSample(self):
"""Generate a sample, along with any sampler-specific info.

Expand Down
39 changes: 39 additions & 0 deletions src/verifai/samplers/glis_optimization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""GLIS Optimization sampler : Defined only for continuous domains.
For discrete inputs define another sampler"""

from glis.solvers import GLIS
from verifai.samplers.domain_sampler import BoxSampler

class GLISSampler(BoxSampler):
'''
Integrates the GLIS sampler with VerifAI
---
Parameters:
domain : FeatureSpace
params : DotMap
---
Note: see the definition of the GLIS class for the available parameters or the GLIS documentation
https://pypi.org/project/glis/
'''
def __init__(self, domain, params):
super().__init__(domain)
from numpy import zeros, ones

self.rho = None

dim = domain.flattenedDimension
self.lb = zeros(dim)
self.ub = ones(dim)
self.sampler = GLIS(bounds=(self.lb, self.ub), **params)


def getVector(self):
if self.rho is None:
self.x = self.sampler.initialize()
elif not self.rho == int(1):
self.x = self.sampler.update(self.rho)

return tuple(self.x), None

def updateVector(self, vector, info, rho):
self.rho = rho
5 changes: 5 additions & 0 deletions src/verifai/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ def choose_sampler(sample_space, sampler_type,
sample_space, BO_params=bo_params)
return 'bo', sampler

if sampler_type == 'glis':
sampler = FeatureSampler.glisSamplerFor(
sample_space, sampler_params)
return 'glis', sampler

raise ValueError(f'unknown sampler type "{sampler_type}"')

class Server:
Expand Down
92 changes: 92 additions & 0 deletions tests/test_glisOptimization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from glis.solvers import GLIS
from verifai.features import *
from verifai.samplers import *
from dotmap import DotMap
from numpy import random as rdm

import pytest
from tests.utils import sampleWithFeedback, checkSaveRestore


def test_glisOptimization():
carDomain = Struct({
'position': Box([-10,10], [-10,10], [0,1]),
'heading': Box([0, math.pi]),
})

space = FeatureSpace({
'cars': Feature(Array(carDomain, [2]))
})

def f(sample):
sample = sample.cars[0].heading[0]
return abs(sample - 0.75)

params = DotMap()
params.n_initial_random=10
sampler = FeatureSampler.glisSamplerFor(space, params)

sampleWithFeedback(sampler, 10, f)

def test_save_restore(tmpdir):
space = FeatureSpace({
'a': Feature(DiscreteBox([0, 12])),
'b': Feature(Box((0, 1)), lengthDomain=DiscreteBox((1, 2)))
})
params = DotMap()
params.n_initial_random=3
sampler = FeatureSampler.glisSamplerFor(space, params)

checkSaveRestore(sampler, tmpdir)

def test_direct_vs_verifai():
fun = lambda x: ((4.0 - 2.1 * x[0] ** 2 + x[0] ** 4 / 3.0) *
x[0] ** 2 + x[0] * x[1] + (4.0 * x[1] ** 2 - 4.0) * x[1] ** 2)

p = {'display': 0, 'n_initial_random': 3}

# Direct GLIS approach
rdm.seed(0)
random.seed(0)

lb = np.array([-2.0, -1.0])
ub = np.array([2.0, 1.0])

prob = GLIS(bounds=(lb, ub), **p)

X = []
F = []
for i in range(6):
if i == 0:
x = prob.initialize()
X.append(x.tolist())
else:
f = fun(x)
x = prob.update(f)
X.append(x.tolist())
F.append(f)

# VerifAI approach
rdm.seed(0)
random.seed(0)
space = FeatureSpace({
'a': Feature(Box([-2.0, 2.0])),
'b': Feature(Box([-1.0, 1.0]))
})

sampler = FeatureSampler.glisSamplerFor(space, p)

X_prime = []
F_prime = []
for i in range(6):
if i == 0:
x_prime = sampler.nextSample(int(1))
X_prime.append([x_prime[0][0], x_prime[1][0]])
else:
f_prime = fun([x_prime[0][0], x_prime[1][0]])
x_prime = sampler.nextSample(feedback=f_prime)
X_prime.append([x_prime[0][0], x_prime[1][0]])
F_prime.append(f_prime)

assert X == X_prime
assert F == F_prime