2

Let's say I have an array like this:

from skopt.space import Space
from skopt.sampler import Lhs
import numpy as np

np.random.seed(42)

rows = 5
cols = 3

dummy = np.zeros((rows, cols))

array([[0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.]])

and I now would like to use skopt.Lhs.generate to fill certain positions of this array with a 1 whereby I would like to exclude certain positions stored in ignore:

ignore = np.array([
    [3, 1],
    [4, 1]
])

How would I do this best?

I can do

space = Space([(0, rows - 1), (0, cols - 1)])

lhs = Lhs(criterion="maximin", iterations=1000)
lh = np.array(lhs.generate(space.dimensions, 3))

dummy[lh[:, 0], lh[:, 1]] = 1

which gives

array([[0., 0., 1.],
       [1., 0., 0.],
       [0., 0., 0.],
       [0., 0., 0.],
       [0., 1., 0.]])

but as one can see the position 4, 1 is occupied but it shouldn't.

One way could be to put the lhs.generate call inside a while loop and then always checks whether any element is in ignore but I am wondering whether there is a more straightforward solution to this.

Cleb
  • 25,102
  • 20
  • 116
  • 151
  • [`skopt.sampler.Lhs`](https://scikit-optimize.github.io/stable/modules/generated/skopt.sampler.Lhs.html) doesn't seem to support any kind of constraints. I think that the best bet is to take [source code of lhs](https://scikit-optimize.github.io/stable/_modules/skopt/sampler/lhs.html) and modify it by adding the restrictions. – fdermishin Feb 09 '21 at 09:57
  • @fdermishin: that would be an option, but I guess I would then better go for such a `while` loop as shown in my answer. Just wondering whether there is anything smarter than this out there (I also checked `pyDOE` but that doe snot seem to work with discrete values). – Cleb Feb 09 '21 at 14:57

1 Answers1

0

Just for completeness, a solution using a while loop could look like this:

from skopt.space import Space
from skopt.sampler import Lhs
import numpy as np

def contains_element(a, b):
    return any(li in a for li in b)

np.random.seed(42)

rows = 5
cols = 3

dummy = np.zeros((rows, cols))

ignore = [
    [3, 1],
    [4, 1]
]

space = Space([(0, rows - 1), (0, cols - 1)])

contains_row = True
while contains_row:

    lhs = Lhs(criterion="maximin", iterations=1000)
    lh = lhs.generate(space.dimensions, 3)
    contains_row = contains_element(lh, ignore)
    print(lh)
    print(contains_row)
    print('-----------------------\n')

lh = np.array(lh)
dummy[lh[:, 0], lh[:, 1]] = 1

print(dummy)

which prints

[[2, 0], [0, 2], [4, 1]]
True
-----------------------

[[2, 0], [1, 2], [4, 1]]
True
-----------------------

[[4, 2], [0, 1], [2, 0]]
False
-----------------------

[[0. 1. 0.]
 [0. 0. 0.]
 [1. 0. 0.]
 [0. 0. 0.]
 [0. 0. 1.]]

So, here it takes 3 iterations until positions are found which are not in ignore. If anyone knows a more straightforward solution, please let me know!

Cleb
  • 25,102
  • 20
  • 116
  • 151