행렬 내적을 통해 생태계 먹이 그물 표현하기

우빈·2024년 4월 2일
2
post-thumbnail



첫 번째 문제

직접 피식자만 나타내고 있는 행렬을 활용하여 어떻게 하면 2단계 직간접 피식자 수가 쉽게 파악되는 행렬을 만들 수 있을까?

import copy
from collections import deque
length = 10

names = {
    0: '독수리',
    1: '뱀',
    2: '쥐',
    3: '휘파람새',
    4: '개구리',
    5: '나방',
    6: '메뚜기',
    7: '다람쥐',
    8: '과실',
    9: '나무'
}

matrix = [
    [0, 1, 1, 1, 1, 0, 0, 1, 0, 0],
    [0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
    [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]

p = dict()

for i in range(10):
    for j in range(10):
        if matrix[i][j] == 1:
            if i in p: p[i].append(j)
            else: p[i] = [j]

s = copy.deepcopy(p)
for k, v in p.items():
    for i in v:
        if i in p: s[k] += s[i]
    
for i in range(len(matrix)):
    if i in s: print(f"{names[i]}: {len(s[i])}")
    else: print(f"{names[i]}: 0")

출력결과

독수리: 13
뱀: 6
쥐: 3
휘파람새: 2
개구리: 4
나방: 1
메뚜기: 1
다람쥐: 1
과실: 0
나무: 0

두 번째 문제

나무와 과실이 모두 타버리고 나서 먹이 그물에서의 각각 생물이 직간접적으로 먹이로 삼는 생물의 수는?

import copy
from collections import deque
length = 10

names = {
    0: '독수리',
    1: '뱀',
    2: '쥐',
    3: '휘파람새',
    4: '개구리',
    5: '나방',
    6: '메뚜기',
    7: '다람쥐',
    8: '과실',
    9: '나무'
}

matrix = [
    [0, 1, 1, 1, 1, 0, 0, 1, 0, 0],
    [0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
    [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    # [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    # [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]

p = dict()

for i in range(8):
    for j in range(8):
        if matrix[i][j] == 1:
            if i in p: p[i].append(j)
            else: p[i] = [j]

s = copy.deepcopy(p)
for k, v in p.items():
    for i in v:
        if i in p: s[k] += s[i]
    
for i in range(len(matrix)):
    if i in s: print(f"{names[i]}: {len(s[i])}")
    else: print(f"{names[i]}: 0")

딥다이브 (코드 리팩토링)

for i in range(10): print(f"{names[i]}: {sum((matrix@matrix+matrix)[i])}")

와 아니이게 말이되냐

딥다이브 설명

일단 내적에 대해서 알아야 한다. 내적은 행렬을 곱하는 거라고 보면 되는데

이런게 있으면
matrix랑 matrix를 행렬곱한다고 가정하면 행렬곱 원리가

대충 이런식으로 포함한 행,열 다곱해서 더하는건데
이걸 내적을 취하면 값은

이렇게 나옴.

우리가 내적을 한 이유는 간단한데, 아까 그 처음 배열과 내적값을 비교하면


본인 값을 제외하고 자기 행 밑에 있는 값들을 더해서 그 값으로 만들어줌.
이걸 하기 위해서 행과 열을 곱해서 더하는 내적을 취한 것..!!!!

말한대로 그럼 "본인 값을 제외하고"이기 때문에 여기서 본인 값만 더해주면됨.

그러면 원래 내적하면 matrix@matrix였는데 matrix@matrix+matrix가 되는거

그렇게 계산하면


이렇게 잘나오고 그럼 열을 sum한 값이 index번째 동물이 먹을 수 있는 먹이 개수.

names = {
    0: '독수리',
    1: '뱀',
    2: '쥐',
    3: '휘파람새',
    4: '개구리',
    5: '나방',
    6: '메뚜기',
    7: '다람쥐',
    8: '과실',
    9: '나무'
}


matrix = np.array([
    [0, 1, 1, 1, 1, 0, 0, 1, 0, 0],
    [0, 0, 1, 0, 1, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 1, 0, 1, 0],
    [0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 1, 1, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
])

matrix = matrix@matrix+matrix
for i in range(10): print(f"{names[i]}: {sum(matrix[i])}")

profile
프론트엔드 공부중

0개의 댓글