python - How to build a strategy to create array of tuples with pairs of identical values?
问题描述
I'd like to generate a strategy for NumPy testing with an output like:
array([[-2, -2],
[-3, -3],
[5, 5],
[-1, -1]], dtype=int16)
What I tried was:
import numpy as np
from hypothesis.strategies import integers
from hypothesis.extra.numpy import arrays
arrays(np.int16, (4,2), elements=integers(-10, 10)).example()
Unfortunately, I can't make values inside tuples identical so the query above returns:
array([[ 5, 5],
[-7, 5],
[ 5, 5],
[ 5, 5]], dtype=int16)
解决方案
I have found that if I need to control content within an existing strategy's structure (e.g. pairs of identical values within an array) I need to skip that strategy for lower level ones with which I can build a "ready-made" value that can seed the type I care to generate.
Let's leverage that numpy.array accepts a list of lists to create an array. Let's also assume you want each row to be unique, as your example does not show duplicate rows. If that is not desired, remove the unique_by=str
from the depth_strategy
definition
- Generate an integer and create a list of that value repeated a number of times to meet the WIDTH.
- Generate a list of a DEPTH length of the kind of lists we created in the first step.
- Combine the two strategies by nesting them.
- Feed the result of the third step into numpy.array, making sure the dtype matches the strategy used to generate values in the first step.
# %%
"""Hypothesis strategy for array of tuples with pairs of identical values."""
from hypothesis import given, settings, strategies as st
import numpy as np
WIDTH = 2
DEPTH = 4
MIN_VALUE = -10
MAX_VALUE = 10
# Build the row - Here for clarification only
width_strategy = st.integers(MIN_VALUE, MAX_VALUE).map(
lambda i: tuple(i for _ in range(WIDTH))
)
# Build the array of rows - Here for clarification only
depth_strategy = st.lists(
width_strategy, min_size=DEPTH, max_size=DEPTH, unique_by=str
).map(lambda lot: np.array(lot, dtype=np.int64))
# All-in-One
complete_strategy = st.lists(
st.integers(MIN_VALUE, MAX_VALUE).map(
lambda i: tuple(i for _ in range(WIDTH))
),
min_size=DEPTH,
max_size=DEPTH,
unique_by=str,
).map(lambda lot: np.array(lot, dtype=np.int64))
@settings(max_examples=10)
@given(an_array=complete_strategy)
def create_numpy_array(an_array):
"""Turn list of lists into numpy array."""
print(f"A numpy array could be:\n{an_array}")
create_numpy_array()
This generates something like:
A numpy array could be:
[[ 3 3]
[ 9 9]
[-5 -5]
[ 0 0]]
A numpy array could be:
[[ 3 3]
[-2 -2]
[ 4 4]
[-5 -5]]
A numpy array could be:
[[ 7 7]
[ 0 0]
[-2 -2]
[-1 -1]]
Note that I set the max_examples to 10 as Hypothesis gives a higher occurrences ratio to values it deems "troublesome", such as zero, NaN, Infinity and such. So example() or a lower number of examples would probably generate a lot of 2x4 arrays of all zeroes. Fortunately the unique_by constraint helps us here.
推荐阅读
- php - 从字符串构造具有可变属性链的对象
- docker - chmod:无法访问“/home/alpine/*.sh”:权限被拒绝
- apache-kafka - Kafka消费者可以暂停一定的时间间隔并在间隔后自动恢复吗
- javascript - 相对于另一个输入框更改输入框的值?
- javascript - 无法成功在数组中动态创建多个 json 对象
- docker - 在 Kubernetes pod 中访问 Docker 映像中的文件?
- skiasharp - 将图像转换为真正的黑白
- regex - 如何使用正则表达式和记事本++将逗号插入文本文件中的多个列?
- c++ - 如何使用 MingW64 从我的 c++ 项目执行对 mysql 的查询
- github - 从 GitHub Enterprise SSO 策略中排除 GitHub 组织