[Python] 코딩으로 연립방정식을 풀어보자!! (2) - Pycharm
안녕하세요!! 코딩으로 연립방정식 풀기 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), 서로 겹쳐지는 부분이 연립 방정식의 해라고 설명드렸습니다.
뒤집어 생각하면, 두 방정식이 서로 겹쳐 있지 않으면, 연립방정식의 해는 존재하지 않습니다.
즉, 연립 방정식의 해찾기 문제는 두 방정식 값(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" 형태 입니다.
따라서, 그래프로 표현할 수 있는 형태인 실수형(float) 으로 data를 얻기 위해, 배열의 첫번째를 뜻하는 "[0]"을 추가 했습니다. 그리고 이 때, 함수 결과 값(y)도 있어야 하기 때문에 두 방정식 중, 아무거나 하나 가져와 "func_1(res.x[0])" 을 입력했습니다. plit.scatter() 함수를 사용했기 때문에 결과는 점으로 나타날 것입니다.
코드를 실행시켜 봤습니다.
첫 번째 결과는 탐색 범위를 " -10 <= x < =0 " 설정 했기 때문에 결과가 좌측에 나타났습니다.
첫번째 해는 -1.303 입니다.
다음은 탐색 범위를 " 0 <= x < =10 " 으로 변경하겠습니다. 결과는 우측에 나타났습니다.
두번째 해는 2.3028 입니다.
이번 컨텐츠를 여기 까지 입니다. 코딩으로 연립 방정식을 풀어 봤습니다.!!
전체 코드는 아래에 있고, 필요하신 분들은 가져가서 사용해 보세요.
#. 전체 코드
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() |