numpy 如何生成一个随机的2D整数数组,使得x,y = y,x?(Python)

jm2pwxwz  于 2023-05-29  发布在  Python
关注(0)|答案(9)|浏览(228)

我正在做一个旅行推销员求解器,我希望能够随机生成表示城市之间距离的矩阵。以下是我目前使用的一个例子:

distances = [[0, 3, 7, 1, 6, 2],
             [3, 0, 9, 2, 8, 7],
             [7, 9, 0, 5, 4, 8],
             [1, 2, 5, 0, 4, 9],
             [6, 8, 4, 4, 0, 4],
             [2, 7, 8, 9, 4, 0]]

我可以用什么来写一个函数来创建一个x * y随机整数矩阵,其中distances[x][y] = distances[y][x]?(如果x = y时元素= 0,则奖励)

14ifxucb

14ifxucb1#

你可以用python来解决这个问题,就像这样:

import random

def generate_symmetric_matrix(n, min_dist=1, max_dist=10):
    matrix = [[0]*n for _ in range(n)]
    for i in range(n):
        for j in range(i+1, n):
            matrix[i][j] = matrix[j][i] = random.randint(min_dist, max_dist)
    return matrix

或者你也可以使用numpy来解决它,如下所示:

def generate_symmetric_matrix(n, min_dist=1, max_dist=10):
    i_upper = np.triu_indices(n, 1) # indices for upper triangle of matrix excluding diagonal
    matrix = np.zeros((n, n)) # create nxn matrix filled with zeros
    random_values = np.random.randint(min_dist, max_dist, size=len(i_upper[0])) # generate random values
    matrix[i_upper] = random_values # assign random values to upper triangle
    matrix.T[i_upper] = random_values # assign same random values to lower triangle using transpose
    return matrix
kq4fsx7k

kq4fsx7k2#

这里有一个简单但有效的解决方案:

import numpy as np

size = 5  # shape of 2d array is (size,size)
array = np.random.randint(0, 10, size=(size, size)) # Generate a random 2D array
array = (array + array.T) // 2 # Make the array symmetric
np.fill_diagonal(array, 0) # Set diagonal elements to 0

print(array)
#     Gives
# [[0 8 5 4 4]
#  [8 0 6 2 5]
#  [5 6 0 3 8]
#  [4 2 3 0 3]
#  [4 5 8 3 0]]
nwnhqdif

nwnhqdif3#

从一系列城市“伪位置”来看,简单地广播绝对值的差异应该可以做到这一点:

import numpy as np

cities = np.random.randint(0,100,(5,))            # 5 cities 0..100 apart
distances = abs(cities-cities[:,None])

print(distances)     #        3   80   28   39   59
[[ 0 77 25 36 56]    #  3 [[  0,  77,  25,  36,  56]
 [77  0 52 41 21]    # 80  [-77,   0, -52, -41, -21]
 [25 52  0 11 31]    # 28  [-25,  52,   0,  11,  31]
 [36 41 11  0 20]    # 39  [-36,  41, -11,   0,  20]
 [56 21 31 20  0]]   # 59  [-56,  21, -31, -20,   0]]
  • 注意,这些不是笛卡尔平面中的“物理”距离。此外,这种方法创建了一个加法模式,其中对于一些A,B,C城市,A->C等于A->B + B->C,这可能是也可能不是你想要/需要的东西。

如果你想避免加法模式,你可以合并(添加)随机距离的转置三角矩阵。每个值将被添加到转置副本中的相应零:

distances = np.triu(np.random.randint(0,100,(5,5)),1) 
distances = distances+distances.T

print(distances)
[[ 0 23 46 76  9]   # [[ 0 23 46 76  9]      [[ 0  0  0  0  0]
 [23  0 48 94 37]   #  [ 0  0 48 94 37]       [23  0  0  0  0]
 [46 48  0 93 71]   #  [ 0  0  0 93 71]   +   [46 48  0  0  0]
 [76 94 93  0 33]   #  [ 0  0  0  0 33]       [76 94 93  0  0] 
 [ 9 37 71 33  0]]  #  [ 0  0  0  0  0]]      [ 9 37 71 33  0]]

如果您只想生成精确数量的随机距离,并且计划在同一矩阵中生成多个测试用例,则可以设置一次索引和计数,并在需要时在一行中执行随机距离生成:
设置:

N = 5

distCount = N*(N-1)//2                 # total number of random distances
iDist     = np.triu_indices(N,1)       # indices of upper part of matrix
distances = np.zeros((N,N),dtype=int)  # will receive random distances

随机矩阵生成:

distances.T[iDist] = distances[iDist] = np.random.randint(0,100,distCount)

print(distances)

[[ 0 41 49 56 49]
 [41  0 22 85 21]
 [49 22  0 12 22]
 [56 85 12  0 21]
 [49 21 22 21  0]]
30byixjq

30byixjq4#

我建议看看triltriu函数,你可以得到下三角形或上三角形,并合并换位,例如。

import numpy as np
arr = np.random.randint(1,100,size=(6,6))
distance = np.where(np.triu(arr)==0,np.triu(arr).T,np.triu(arr))
print(distance)

可能给予输出

[[25 36 22 32 80 33]
 [36  3 19 51 24  8]
 [22 19 47 98  6 46]
 [32 51 98 24 28 40]
 [80 24  6 28 29 12]
 [33  8 46 40 12 66]]

说明:我生成6x6随机数组,然后得到上三角形,三角形之外的所有东西都是零,所以我使用where从转置的上三角形中得到值,那里是零。

免责声明:此解决方案仅提供distances[x][y] == distances[y][x],不尝试使distances[x][x] == 0

7fyelxc5

7fyelxc55#

也可以根据需要生成足够的随机数:

import numpy as np

N = 6     # Number of cities
M = 10    # One more than the maximum distance

# Generate random integers only for one 'half' of the matrix
size = N * (N - 1) // 2
nums = np.random.randint(M, size=size)

distances = np.zeros((N, N), dtype=nums.dtype)
tri = np.tri(N, k=-1, dtype=bool)

distances[tri] = distances.T[tri] = nums

结果

>>> distances
array([[0, 4, 1, 2, 8, 8],
       [4, 0, 6, 7, 5, 7],
       [1, 6, 0, 2, 5, 6],
       [2, 7, 2, 0, 2, 3],
       [8, 5, 5, 2, 0, 3],
       [8, 7, 6, 3, 3, 0]])
>>> np.all(distances == distances.T)
True
tp5buhyn

tp5buhyn6#

这称为对称矩阵。可以通过以下方式生成对称矩阵:

import numpy as np
N=5  # dimension of your matrix
b = np.random.randint(0,3000,size=(N,N))  #0 and 3000 are the range of numbers you want in your matrix
mat = (b + b.T)//2

print(mat)
array([[2510,  684, 1990, 1121, 1710],
      [ 684, 2920, 2245, 2620,  564],
      [1990, 2245,  934, 1439, 1790],
      [1121, 2620, 1439, 2075, 2288],
      [1710,  564, 1790, 2288,   13]])

最后,如果你想填充对角线的元素为0然后:

np.fill_diagonal(mat, 0)

print(mat)

array([[   0,  684, 1990, 1121, 1710],
       [ 684,    0, 2245, 2620,  564],
       [1990, 2245,    0, 1439, 1790],
       [1121, 2620, 1439,    0, 2288],
       [1710,  564, 1790, 2288,    0]])
h43kikqp

h43kikqp7#

可以使用Python中的random模块为距离矩阵生成随机整数。为了确保距离[x][y]等于距离[y][x],可以生成一个下三角矩阵,然后将其反映在对角线上。
示例

import random
from pprint import pprint

def generate_distance_matrix(size):
    """Initialize an empty matrix"""
    distances = [[0] * size for _ in range(size)]

    # Generate random distances for the lower triangular matrix
    for x in range(size):
        for y in range(x):
            # Modify the range as per your requirements
            distances[x][y] = random.randint(1, 10)  # 

    # Reflect the distances across the diagonal
    for x in range(size):
        for y in range(x + 1, size):
            distances[x][y] = distances[y][x]

    return distances

if __name__ == '__main__':
    matrix_size = 6
    distances = generate_distance_matrix(matrix_size)
    pprint(distances)
    # [[0, 5, 8, 10, 7, 2],
    #  [5, 0, 5, 2, 3, 9],
    #  [8, 5, 0, 1, 2, 10],
    #  [10, 2, 1, 0, 5, 8],
    #  [7, 3, 2, 5, 0, 8],
    #  [2, 9, 10, 8, 8, 0]]
00jrzges

00jrzges8#

另一种方法是将random matrix乘以它的转置:

mat= np.random.randint(0,100,(5,5))  # a 5X5 matrix

mat@mat.T

array([[ 9372,  8256,  6821,  8229, 12952],
       [ 8256, 11999, 10977,  7926, 14418],
       [ 6821, 10977, 11115,  8507, 12654],
       [ 8229,  7926,  8507, 11054, 12240],
       [12952, 14418, 12654, 12240, 20680]])

这里的值将大得多,因为我们将元素乘以它们的转置。

5us2dqdw

5us2dqdw9#

一种方法是对下面的三角形及其调整后的转置求和。

mat= np.random.randint(0,100,(5,5))  # a 5X5 matrix
k=np.tril(mat) + np.tril(mat, -1).T

array([[93, 34, 85, 94, 98],
       [34, 73, 57, 75, 98],
       [85, 57, 42, 61, 48],
       [94, 75, 61, 59, 90],
       [98, 98, 48, 90, 41]])

将对角线转换为0

np.fill_diagonal(k, 0)

相关问题