본문 바로가기
ETC

[수치해석] [c++,python] 가우스 소거법(Gaussian Elimination) 구현하기

by dkswnkk 2021. 10. 20.

 

Gaussian Elimination(가우스 소거법)

  1. Pivoting(피보팅)을 통해 방정식의 순서를 바꾸어 Gauss Elimination을 적용할 수 있도록 바꿔준다.
  2. 행렬을 가우스 소거법을 사용해서 Row Echelon Form(=REF,행사다리꼴) 형태로 변경한다.
  3. 후진 대입법을 이용해 해를 구한다.
  4. C++ 으로는 단순 구현, PYTHON으로는 GUI까지 구현하였다.

screenshot안주형_1724572

 

Github로 보기

 

 

GitHub - dkswnkk/DongA-Univ: 🍊 DongA-Univ. 동아대학교 코딩 과제

🍊 DongA-Univ. 동아대학교 코딩 과제. Contribute to dkswnkk/DongA-Univ development by creating an account on GitHub.

github.com

c++

#include <iostream>
#include <iomanip>
#include <vector>
#pragma warning (disable:4996)

using namespace std;

float maxV, num;
int w;
vector<vector<float>>matrix;

/* 
input:
3
-2 -5 2 -3
1 3 0 4
0 1 3 6
output:
최종 결과 행렬:
 -2  -5   2     -3
  0 0.5   1    2.5
  0   0   1      1
x[1] =-5
x[2] =3
x[3] =1
*/
int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);


    freopen("Gauss_Input.txt", "r", stdin);
    freopen("Gauss_Output.txt", "w", stdout);


    int n; cin >> n;    //n*n행렬

    matrix.resize(n, vector<float>(n + 1));    //벡터 크기 재할당

    for (int i = 0; i < n; i++) {    //행렬 삽입
        for (int k = 0; k < n + 1; k++) {
            cin >> matrix[i][k];
        }
    }

    for (int i = 0; i < n; i++) { //피봇
        maxV = abs(matrix[i][i]);
        for (int q = i; q < n; q++) {
            num = abs(matrix[q][i]);
            if (num > maxV) {
                maxV = abs(matrix[q][i]);
                w = q;
            }
        }
        if (abs(matrix[i][i]) != maxV) {        //더 큰 것이 있다면 변환
            for (int c = 0; c < n + 1; c++) {
                float temp = matrix[i][c];
                matrix[i][c] = matrix[w][c];
                matrix[w][c] = temp;
            }
        }
    }


    for (int i = 0; i < n; i++) {    //가우스 소거법
        if (matrix[i][i] == 0) {
            cout << "정칙행렬이 아닙니다.";
            exit(0);
        }
        for (int j = i + 1; j < n; j++) {
            float temp = matrix[j][i] / matrix[i][i];
            for (int k = 0; k < n + 1; k++) {
                matrix[j][k] = matrix[j][k] - (temp * matrix[i][k]);
            }
        }
    }

    cout << "\n" << "최종 결과 행렬:" << "\n";
    for (int a = 0; a < n; a++) {    //출력
        for (int b = 0; b < n + 1; b++) {
            if (b == n) cout << right << setw(3) << ' ';
            cout << right << setw(3) << matrix[a][b] << ' ';
        }
        cout << "\n";
    }
    cout << "\n";


    for (int i = n - 1; i >= 0; i--) {    //해 구하기
        for (int k = i + 1; k < n; k++) {
            matrix[i][n] = matrix[i][n] - matrix[i][k] * matrix[k][n];
        }
        matrix[i][n] = matrix[i][n] / matrix[i][i];
    }
    for (int i = 0; i < n; i++) {    //해 출력
        cout << "x[" << i + 1 << "] =" << matrix[i][n]<<"\n";
    }
}

python

import tkinter.messagebox as msgbox
import tkinter as tk
from numpy import array
from tkinter import *
from tkinter import filedialog
from tkinter import ttk

'''
input:
3
-2 -5 2 -3
1 3 0 4
0 1 3 6
'''

maxV, num,  n,w = 0.0, 0.0, 0,0
matrix = []

root=Tk()
root.title("가우스소거법_1724572_안주형")
root.geometry("640x480+300+100") #가로*세로+x좌표+y좌표
root.resizable(False,False) #x,y너비 변경불가 (창크기 변경불가)

def result(): #결과 버튼 눌렸을때 동작하는 함수
    n = len(matrix)
    w=0
    for i in range(n):  # 피봇
        maxV = abs(matrix[i][i])
        for q in range(i, n):
            num = abs(matrix[q][i])
            if num > maxV:
                maxV = abs(matrix[q][i])
                w = q

        if abs(matrix[i][i] != maxV):  # 더 큰것이 있다면 변환
            for c in range(n + 1):
                temp: float = matrix[i][c]
                matrix[i][c] = matrix[w][c]
                matrix[w][c] = temp

    for i in range(n):  # 가우스 소거법
        if matrix[i][i] == 0:
            print('정칙행렬이 아닙니다.')
            exit(0)

        for j in range(i + 1, n):
            temp: float = matrix[j][i] / matrix[i][i]
            for k in range(n + 1):
                matrix[j][k] -= temp * matrix[i][k]
    msgbox.showinfo("알림","정상적으로 출력했습니다")

    a = array(matrix)
    root.text = Text(root)
    root.text.insert(END,str('--------가우스 소거법 진행한 행렬 출력-------- \n'))
    root.text.insert(END,'\n')
    for i in range(n):  #  행렬 저장
        for k in range(n + 1):
            root.text.insert(END,'%6s' % str(matrix[i][k]) + ' ')
        root.text.insert(END,'\n')

    for i in range(n - 1, -1, -1):  # 해 구하기
        for k in range(i + 1, n):
            matrix[i][n] = matrix[i][n] - matrix[i][k] * matrix[k][n]
        matrix[i][n] /= matrix[i][i]

    root.text.insert(END,'\n --------해 출력--------\n')
    root.text.insert(END, '\n')

    for i in range(n):  # 해 저장
      root.text.insert(END,f'x[{i + 1}] = {matrix[i][n]}\n')
    root.text.configure(state='disabled')
    root.text.pack()


def open_file(): #파일 불러오기 함수 
        file=filedialog.askopenfile(parent=root,mode='rb',title="파일을 불러오세요")
        lines = file.readlines()
        for idx, line in enumerate(lines):
            if idx > 0:
              matrix.append(list(map(float, line.strip().split())))
        file.close()

def save_file(): #파일 저장하기 함수
    file= filedialog.asksaveasfile(mode='w', defaultextension=".txt")
    text2save = str(root.text.get(0.0, END))
    file.write(text2save)
    file.close

#메뉴 영역
menu=Menu(root)
menu_file=Menu(menu,tearoff=0)
menu_file.add_command(label="파일 불러오기",command=open_file)
menu_file.add_command(label="파일 저장하기",command=save_file)
menu_file.add_separator()
menu_file.add_command(label="끝내기",command=root.quit)
menu.add_cascade(label="파일",menu=menu_file)

#본문 영역
btn1=Button(root,command=result,padx=5,pady=15,text="가우스 소거법 진행하기").pack()
label=ttk.Label(root, text="1.파일을 불러온다.",font=("Times",14)).pack()
label=ttk.Label(root, text="2.위 가우스 소거법 진행하기 버튼을 누른다.",font=("Times",14)).pack()
label=ttk.Label(root, text="3.저장은 자동으로 .txt 형식으로 저장되므로 파일이름만 정해준다.",font=("Times",14)).pack()
root.config(menu=menu)
root.mainloop()

댓글