Python

[Python] 코딩으로 연립방정식을 풀어보자!! (2) - Pycharm

CallmeJames 2022. 8. 16. 13:28
반응형

안녕하세요!! 코딩으로 연립방정식 풀기 2편입니다. 

오늘은 지난편에 이어서, 연립 방정식의 해를 찾아 보겠습니다.

 

지난편을 못 보셨다면 아래 링크로 보고 오시면 좋을 것 같습니다.

2022.08.12 - [Python] - [Python] 코딩으로 연립방정식을 풀어보자!! (1) - Pycharm

 

[Python] 코딩으로 연립방정식을 풀어보자!! (1) - Pycharm

안녕하세요, 오늘은 코딩으로 연립 방정식을 풀어보려고 합니다. 우리는 중학교 정도되면 연립방정식을 배웁니다. 방정식의 해를 찾는 방법을 공부하는데요, 여기서 저는 코딩으로 방정식의 해

all-knowledge-of-the-world.tistory.com

 

바로 시작 합니다.!!!

 

1. 문제

     y1 = x2 +2

     y2 = x+5

 

문제는 "두 가지 방정식의 값(y1과 y2)이 같아지는 x를 찾아라" 였습니다. 연립방정식의 해를 찾는 문제입니다.

 

Fig. 1 방정식 그래프 (1)

지난편에서, 두 방정식을 그래프로 확인했고 (Fig. 1), 서로 겹쳐지는 부분이 연립 방정식의 해라고 설명드렸습니다.

뒤집어 생각하면, 두 방정식이 서로 겹쳐 있지 않으면, 연립방정식의 해는 존재하지 않습니다.

 

즉,  연립 방정식의 해찾기 문제는 두 방정식 값(y)이 동일한 x 값을 찾는 것이 됩니다.

이러한 관점으로 코딩을 통해 방정식의 해(x)를 찾아 보겠습니다.

 

먼저, 방정식을 'def' 문으로 코딩하겠습니다. 이유는 이 정의된 함수를 반복적으로 사용하기 위해서 입니다. 'def' 는 'define' 이라 생각할 수 있습니다. 


def  func_1(x):
       y1 = (x ** 2) + 2

       return y1


def  func_2(x):
       y2 = x + 5

       return y2

"return" 은 계산된 함수값(y)을 되돌려 준다는 뜻입니다. 즉, "return 사용해 계산된 함수값을 볼 수 있다" 라고 이해하면 좋을 것 같습니다.

 

 

다음은 서로 동일한 값을 가지는 경우를 검출하기 위한 함수를 코딩하겠습니다.


def  LossFuction(x):
       tol = abs(func_1(x) - func_2(x))

       return tol

두 방정식의 차이를 함수로 표현한 것입니다. "abs" 는 "절대값 (absolute value)" 으로 무조건 (+) 값입니다. 만약, 이 함수의 결과값이 0이라면, 두 방정식의 값(y)은 같다는 의미입니다. 이때 대입된 x값이 바로 연립 방정식의 '해' 입니다.

 

다음 단계는, 찾을 해의 범위를 지정하는 일입니다. 코딩의 특성상 한번에 두 가지 해를 동시에 찾는 것은 매우 어려운 일이기 때문에, 해를 탐색할 범위를 지정해서 한번에 한개씩만 찾도록 코딩하겠습니다.

 

 

Fig.1 그래프를 참고해서, x=0을 기준으로 찾고자 하는 해는 좌측과 우측으로 구분할 수 있습니다.

 

좌측 노랑색 부분을 찾을 때,


#--- -10<= x <=0 --
x0 = -1.0
bounds = Bounds([-10], [0])

 

우측 빨강색 부분을 찾을 때,


#---- 0<= x <=10 --
x0 = 2.0
bounds = Bounds([0], [10])

그리고 최적화 알고리즘의 특성상 초기값이 필요하기 때문에 각 탐색 범위 내의 값으로 초기값 x0를 정의해 줬습니다.

 

다음은 최적화 실행문을 코딩하겠습니다. 매우 간단한 한줄 코딩입니다. 

"minimize()" 함수 안에 우리가 정의한 함수 (LossFuction) 와 초기값(x0), 그리고 옵션을 설정해 주면 끝납니다. 여기서 "SLSQP"는 "Sequential Least SQuares Programming" 이라는 최적화 알고리즘으로, 복잡하지 않은 수식화 된 최적화 문제를 풀기위한 알고리즘으로 적당하다고 할 수 있습니다. 최적화 알고리즘은 매우 어렵기 때문에 자세한 설명은 생략하도록 하겠습니다.


res = minimize(LossFuction, x0, method="SLSQP", callback=print, options = {'xatol':1e-8, 'disp':True}, bounds=bounds)

 

마지막으로, 결과(해)를 그래프로 확인하기 위한 코딩을 해보겠습니다.


plt.scatter(res.x[0], func_1(res.x[0]), s = 100, c = 'g', alpha = 0.5)
plt.legend()
plt.show()

최적해의 결과는 "res" 에 저장되는데 "res.x" 를 보면 아래와 같이 "array" 형태 입니다. 

Fig.2. 최적해 결과 (1)
Fig. 3 최적해 결과 (2)

따라서, 그래프로 표현할 수 있는 형태인 실수형(float) 으로 data를 얻기 위해, 배열의 첫번째를 뜻하는 "[0]"을 추가 했습니다. 그리고 이 때, 함수 결과 값(y)도 있어야 하기 때문에 두 방정식 중, 아무거나 하나 가져와  "func_1(res.x[0])" 을 입력했습니다. plit.scatter() 함수를 사용했기 때문에 결과는 점으로 나타날 것입니다.

 

 

코드를 실행시켜 봤습니다. 

Fig. 4. Run 'main'

첫 번째 결과는 탐색 범위를 " -10 <= x < =0 "  설정 했기 때문에 결과가 좌측에 나타났습니다.

Fig. 5 최적해 그래프 (1)

 

첫번째 해는 -1.303 입니다.

 

Fig. 6 최적화 결과 (1)

 

 

다음은 탐색 범위를  " 0 <= x < =10 " 으로 변경하겠습니다. 결과는 우측에 나타났습니다.

 

Fig. 7 최적해 그래프 (2)

 

두번째 해는 2.3028 입니다.

Fig. 6 최적화 결과 (2)

 

 

이번 컨텐츠를 여기 까지 입니다. 코딩으로 연립 방정식을 풀어 봤습니다.!!

전체 코드는 아래에 있고, 필요하신 분들은 가져가서 사용해 보세요.

 

 

#. 전체 코드

import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import minimize
from scipy.optimize import Bounds

def func_1(x):
      y1 = (x ** 2) + 2

      return y1


def func_2(x):
      y2 = x + 5

      return y2


def LossFuction(x):
      tol = abs(func_1(x) - func_2(x))

      return tol



x = np.array(range(-5,6))

#----- 그래프 설정 -------
# 축 이름
plt.xlabel ('x axis')
plt.ylabel ('y axis')

# 그래프 스타일
plt.grid(color = "gray", alpha=.5, linestyle='--')


# 방정식 추가하기
y1 = (x**2) + 2
y2 = x + 5
plt.plot(x, y1, label='y1')
plt.plot(x, y2, label='y2')


#-- 범례 작성
"""
#--- 0<= x <=10
x0= 2.0
bounds = Bounds([0], [10])
"""

#--- -10<= x <=0
x0= -1.0
bounds = Bounds([-10], [0])


#--- 최적화 알고리즘 연결
res = minimize(LossFuction, x0, method="SLSQP", callback=print, options = {'xatol':1e-8, 'disp':True}, bounds=bounds)


#--- 최적화 결과 그래프 추가
plt.scatter(res.x[0],func_1(res.x[0]), s = 100, c = 'g', alpha = 0.5)

#--- 그래프 출력
plt.legend()
plt.show()


 

 

반응형