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

huangapple go评论63阅读模式
英文:

How to generate a random 2D array of integers, such that x,y = y,x? (Python)

问题

我正在开发一个旅行推销员问题的解决方案,我想能够随机生成表示城市之间距离的矩阵。以下是迄今为止我一直在使用的示例:

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,则为奖励):

import random

def generate_random_distances_matrix(size):
    matrix = [[0] * size for _ in range(size)]

    for x in range(size):
        for y in range(x + 1, size):
            random_distance = random.randint(1, 10)  # You can adjust the range of random distances as needed
            matrix[x][y] = random_distance
            matrix[y][x] = random_distance

    return matrix

# Example usage:
x, y = 6, 6  # Replace with your desired matrix size
random_distances = generate_random_distances_matrix(x)

请注意,上述示例中,我使用了1到10之间的随机整数作为距离值,您可以根据需要调整这个范围。

英文:

I'm working on a travelling salesman solver, and I'd like to be able to randomly generate the matrix that represents the distances between cities. Here's an example of what I've been using so far:

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

What can I use to write a function that creates an x*y matrix of random integers where distances[x][y] = distances[y][x]? (Bonus if the element = 0 when x=y)

答案1

得分: 2

这被称为对称矩阵。
您可以通过以下方式创建对称矩阵:

import numpy as np
N=5  # 您的矩阵的维度
b = np.random.randint(0,3000,size=(N,N))  # 0和3000是您希望在矩阵中的数字范围
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]])
英文:

This is called a symmetric matrix.
You can make symmetric matrices by:

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

Finally, If you want to fill the elements of diagonal to 0 then:

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

答案2

得分: 2

我建议查看 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

英文:

I suggest taking look at tril or triu function, you might getter lower or upper triangle and combine with transposition e.g.

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)

might give output

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

Explanation: I generate 6x6 random array, then get upper triangle, everything outside that triangle is zero, so I use where to get value from transposed upper triangle where there is zero.

Disclaimer: this solution provides just that distances[x][y] == distances[y][x], no attempt is done to make distances[x][x] == 0

答案3

得分: 1

以下是翻译好的部分:

"Also possible by generating only enough random numbers as necessary:":
"也可以通过仅生成足够数量的随机数来实现:"

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

"results":
"结果"

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

请注意,翻译中保留了代码中的注释和变量名。

英文:

Also possible by generating only enough random numbers as necessary:

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

results

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

答案4

得分: 0

你可以在Python中使用random模块来生成随机整数以创建距离矩阵。为了确保distances[x][y]等于distances[y][x],你可以生成一个下三角矩阵,然后将其沿对角线进行反射。

示例:

import random
from pprint import pprint

def generate_distance_matrix(size):
    """初始化一个空矩阵"""
    distances = [[0] * size for _ in range(size)]

    # 为下三角矩阵生成随机距离
    for x in range(size):
        for y in range(x):
            # 根据需要修改范围
            distances[x][y] = random.randint(1, 10)  

    # 沿对角线反射距离
    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]]
英文:

You can use the random module in Python to generate random integers for your distance matrix. To ensure that distances[x][y] is equal to distances[y][x], you can generate a lower triangular matrix and then reflect it across the diagonal.

Example

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

答案5

得分: 0

从一个包含城市“伪位置”的数组中,通过绝对值的简单广播可以解决问题:

import numpy as np

cities = np.random.randint(0, 100, (5,))  # 5座城市,相距0到100
distances = abs(cities - cities[:, None])

print(distances)  #        3   80   28   39   59
# 3 [[  0,  77,  25,  36,  56]
# 80  [-77,   0, -52, -41, -21]
# 28  [-25,  52,   0,  11,  31]
# 39  [-36,  41, -11,   0,  20]
# 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                 # 随机距离的总数
iDist     = np.triu_indices(N, 1)           # 矩阵上半部分的索引
distances = np.zeros((N, N), dtype=int)      # 将接收随机距离

随机矩阵生成:

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]]
英文:

From an array of city "pseudo-positions", a simple broadcast of differences in absolute value should do the trick:

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

Note that those are not "physical" distances in a Cartesian plane. Also, this approach creates an additive pattern where for some A,B,C cities A->C is equal to A->B + B->C which may or may not be something you want/need.

If you want to avoid the additive pattern, you can combine (add) transposed triangular matrices of random distances. Each value will be added to a corresponding zero in the transposed copy:

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

If you want to only generate the exact number of random distances and you plan to produce multiple test cases in the same matrix, you could setup the indices and counts once and perform the random distance generations in one line when you need it:

Setup:

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

Random matrix generation:

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

答案6

得分: 0

您可以使用纯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来解决它,如下所示:

import numpy as np

def generate_symmetric_matrix(n, min_dist=1, max_dist=10):
    i_upper = np.triu_indices(n, 1) # 获取上三角矩阵的索引,不包括对角线
    matrix = np.zeros((n, n)) # 创建一个填充零的nxn矩阵
    random_values = np.random.randint(min_dist, max_dist, size=len(i_upper[0])) # 生成随机值
    matrix[i_upper] = random_values # 将随机值分配给上三角
    matrix.T[i_upper] = random_values # 使用转置将相同的随机值分配给下三角
    return matrix
英文:

you can solve this problem using pure python like this:

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

or you can also solve it using numpy like so:

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

答案7

得分: 0

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

import numpy as np

size = 5  # 2D数组的形状为(size,size)
array = np.random.randint(0, 10, size=(size, size)) # 生成一个随机的2D数组
array = (array + array.T) // 2 # 使数组对称
np.fill_diagonal(array, 0) # 将对角线元素设为0

print(array)
# 输出结果
# [[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]]
英文:

Here is a simple, yet working solution:

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

huangapple
  • 本文由 发表于 2023年5月28日 16:52:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76350685.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定