如何构建一个策略来创建具有相同值对的元组数组?

2024-06-16 13:21:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我想为NumPy测试生成一个策略,输出如下:

array([[-2, -2],
       [-3, -3],
       [5,  5],
       [-1, -1]], dtype=int16)

我尝试的是:

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()

不幸的是,我无法使元组中的值相同,因此上面的查询返回:

array([[ 5,  5],
       [-7,  5],
       [ 5,  5],
       [ 5,  5]], dtype=int16)

Tags: integersfromimportnumpyasnparrayextra
3条回答

不确定这是您想要的,但是来自hypothesis.extra.numpyarrays似乎没有复制值的选项

您可以这样构造所需的阵列:

import numpy as np
from hypothesis.strategies import integers
strat = integers(10, -10)
np.array([[x, x] for x in [strat.example() for _ in range(4)]], np.int16)

示例结果:

array([[-9, -9],
       [ 0,  0],
       [-2, -2],
       [ 0,  0]], dtype=int16)

如果您不喜欢2维度被烘焙,您可以使用如下两个参数:

def get_array(rows, cols, strat):
    np.array([[x]*cols for x in [strat.example() for _ in range(rows)]], np.int16)


get_array(4, 2, integers(-10, 10))

我发现,如果我需要在现有策略的结构中控制内容(例如数组中相同值的对),我需要跳过该策略,以获得较低级别的策略,我可以使用该策略构建一个“现成”值,该值可以为我想要生成的类型播种

让我们利用numpy.array接受列表列表来创建数组。我们还假设您希望每一行都是唯一的,因为您的示例没有显示重复的行。如果不需要,请从depth_strategy定义中删除unique_by=str

  1. 生成一个整数并创建该值的列表,重复多次以满足宽度要求
  2. 生成一个列表,其深度长度与我们在第一步中创建的列表相同
  3. 通过嵌套将这两种策略结合起来
  4. 将第三步的结果馈送到numpy.array中,确保数据类型与第一步生成值时使用的策略相匹配
# %%
"""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()

这会产生如下结果:

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]]

请注意,我将max_examples设置为10,因为假设给出了一个更高的出现率,与它认为“麻烦”的值相比,例如零、NaN、无穷大等等。因此,example()或更少数量的示例可能会生成大量全零的2x4数组。幸运的是,独特的_by约束在这里帮助了我们

无需过多研究np提供的功能,您只需使用生成器生成元组即可:

tuple_list = [tuple(a) for a in arrays(np.int16, (4,2), elements=integers(-10,10)).example()]

相关问题 更多 >