설명

영화 별점을 메기는 사람마다 quality level을 결정하고 평균 값을 score로 사용한다.

알고리즘은 사람의 신뢰도가 수렴할때까지 수행된다.

신뢰도에대한 알고리즘의 수식은 다음과 같다.

rating score는 다음과 같다.

코드

{.cpp}
// ConsoleApplication24.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//

#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include<string.h>
#include<cmath>
using namespace std;

//main함수로부터의 도표를 읽어들여 값을 대입해주는 함수 readChart.
void readChart(int** pDataset, int voter, int election)
{
    //초기화된 배열에 원하는값을 넣어준다.
    for (int i = 0; i < election; i++)
    {
        for (int j = 0; j < voter; j++)
        {
            cin >> pDataset[i][j];

            //chart[i] = new int[voter];
            //memset(chart[i], 0, 4 * voter);
        }
    }

}

//정답만 바로 궁금하다면 사용해줄 함수 readmacro.
void readmacro(int** pDataset)
{
    //초기화된 배열에 원하는값을 넣어준다.
    pDataset[0][0] = 1;
    pDataset[0][1] = 1;
    pDataset[0][2] = 1;
    pDataset[0][3] = 2;
    pDataset[0][4] = 2;
    pDataset[1][0] = 1;
    pDataset[1][1] = 2;
    pDataset[1][2] = 2;
    pDataset[1][3] = 3;
    pDataset[1][4] = 2;
    pDataset[2][0] = 3;
    pDataset[2][1] = 4;
    pDataset[2][2] = 4;
    pDataset[2][3] = 4;
    pDataset[2][4] = 2;
    pDataset[3][0] = 1;
    pDataset[3][1] = 3;
    pDataset[3][2] = 3;
    pDataset[3][3] = 3;
    pDataset[3][4] = 1;
    pDataset[4][0] = 2;
    pDataset[4][1] = 2;
    pDataset[4][2] = 2;
    pDataset[4][3] = 1;
    pDataset[4][4] = 1;
    pDataset[5][0] = 1;
    pDataset[5][1] = 2;
    pDataset[5][2] = 2;
    pDataset[5][3] = 1;
    pDataset[5][4] = 1;
}

//*T를 초기화하는 함수를 통하여 초기화. 일단 모든사람의 신뢰값으로 1을 준다.
void firstinitial(double* T, int voter)
{
    for (int i = 0; i < voter; i++)
        T[i] = 1;
}
//식2를 구현하는 함수 만들기
void modify2(double **rho, int** pDataset, int election, int item, int voter)
{
    //해당작품의 해당점수를 선택한 사람들의 신뢰도의 합 구하기
    //voter의값을 이용하기 위해 voter2 정의
    int voter2 = voter;
    for (int a = 0; a < election; a++)
    {
        //여기서부터 rho의 j열 i행에 어떠한 수가 들어갈지를 계산하여 준다.즉 식 (2)의 구현을 나타낸다.
        //일단 식 2에서 분모의 계산을 해보겠다.
        //1점을 고른 사람들의 신뢰도의 합을 c[1],2점을 고른 사람들의 신뢰도합을 c[2]...이런식으로 알고리즘을 구성하겠다.
        //점수n의 사람에대한 신뢰도의합 c[n]으로 나타냄.
        int squresum = 0;
        double squreroot = 0;
        int c[5];
        c[0] = 0; c[1] = 0; c[2] = 0; c[3] = 0; c[4] = 0;
        for (int l = 0; l < voter; l++)
        {

            for (int m = 0; m < 5; m++)
            {
                if (pDataset[a][l] == m + 1)
                    c[m] = c[m] + 1;
            }

        }
        //제곱의 합을 더한후에 루트를 씌운다.
        for (int n = 0; n < item; n++)
            squresum = squresum + c[n] * c[n];
        squreroot = sqrt(squresum);
        for (int o = 0; o < item; o++)
        {
            rho[o][a] = c[o] / squreroot;
        }
    }
    cout << endl << "<2nd answer>" << endl;
    for (int a = 0; a < item; a++)
    {
        for (int j = 0; j < election; j++)
        {
            //소수점 두자리까지만 출력하여 간편히 보기위하여 다음과같은 설정을 만족하자.
            cout.setf(ios::fixed);
            cout.setf(ios::showpoint);
            cout.precision(2);
            cout << rho[a][j] << "\t";
            //chart[i] = new int[voter];
            //memset(chart[i], 0, 4 * voter);
        }
        cout << endl;
    }
}

int main()
{
    cout << "<Iterative Method for Calculating Robust Rating Scores>\n*press keybord <anything+enter> ->answer of work.\n*press keybord <0+enter> ->change election and voter\n";
    long double epsil;
    long double ee;
    int voter = 5;
    int election = 6;
    int sel;
    cin >> sel;
    int item = 5;
    //동적할당 방식을 이용.new int[n] n숫자만큼의 배열을 할당시켜줌.
    //pDataset 라는 포인터로 이중배열을 가리킴

    int** pDataset = new int*[election];
    //메모리 공간을 memset이라는 함수를 이용하여초기화
    //루프를 지날수록 차트의행이 증가
    for (int i = 0; i < election; i++)
    {
        pDataset[i] = new int[voter];
        memset(pDataset[i], 0, 4 * voter);
    }
    //readchart에 voter와 election값을 같이 달아주는 이유는 도표를 읽는함수를 main함수로 return하기 위해서이다.(이차원은 길이가 동일해야한다.)

    readmacro(pDataset);

    if (sel == 0)
    {
        cout << "<number of voter>" << endl;
        cin >> voter;

        cout << "<number of election>" << endl;
        cin >> election;
        cout << "<item for election>" << endl;
        readChart(pDataset, voter, election);
    }
    cout << endl << "<1st answer>" << endl;
    for (int i = 0; i < election; i++)
    {
        for (int j = 0; j < voter; j++)
        {
            cout << pDataset[i][j] << "\t";
            if (pDataset[i][j] > 5)
            {
                cout << endl << "You can have score maximum 5!!!";
                return 0;
            }
            //chart[i] = new int[voter];
            //memset(chart[i], 0, 4 * voter);
        }
        cout << endl;
    }

    double* T = new double[voter];
    //*T를 초기화하는 함수를 통하여 초기화
    firstinitial(T, voter);
    //2차원 로우li를 담는 함수 rho 선언및  초기화
    double** rho = new double*[item];
    for (int i = 0; i < item; i++)
    {
        rho[i] = new double[election];
        memset(rho[i], 0, 8 * election);
    }
    double** rho2 = new double*[item];
    for (int i = 0; i < item; i++)
    {
        rho2[i] = new double[election];
        memset(rho[i], 0, 8 * election);
    }

    //수식2를 계산하는 함수에 rho를 대입
    modify2(rho, pDataset, election, item, voter);
    epsil = 0;
    ee = 0;
    long double epsil2;

    cout << endl;
    ///////////////////////////////////////////////////////////////////////////////

    for (int p = 0; p < 20; p++)
    {

        for (int i = 0; i < voter; i++)
        {
            T[i] = 0;
        }
        //main함수에서 수식 3번함수 구현하기.
        for (int i = 0; i < voter; i++)
        {
            for (int j = 0; j < election; j++)
            {
                //작품에 대하여 voter가 선택한 점수를 selectitem으로 선언
                int selectitem = pDataset[j][i] - 1;
                //T[i]에는 작품에 해당하는 점수의 신뢰도의 합이 들어있다.
                T[i] = T[i] + rho[selectitem][j];
            }
        }
        for (int a = 0; a < election; a++)
        {
            //여기서부터 rho의 j열 i행에 어떠한 수가 들어갈지를 계산하여 준다.즉 식 (2)의 구현을 나타낸다.
            //일단 식 2에서 분모의 계산을 해보겠다.
            //1점을 고른 사람들의 신뢰도의 합의제곱을 c[0],2점을 고른 사람들의 신뢰도합을 c[1]...이런식으로 알고리즘을 구성하겠다.
            //점수n의 사람에대한 신뢰도의합 c[n]으로 나타냄. 즉 4번식의 분자에서 제곱안에 있는수를 의미한다.
            double squresum = 0;
            double squreroot = 0;
            int c[5];
            c[0] = 0; c[1] = 0; c[2] = 0; c[3] = 0; c[4] = 0;
            //a가 작품,l은 사람, m 은 점수를 의미한다.
            for (int l = 0; l < voter; l++)
            {

                for (int m = 0; m < 5; m++)
                {
                    //a번째 작품에서 l번째 사람의 점수가 내가 구하고자하는점수일때 그사람의 신뢰도의 제곱을 c[m]에 제곱하여 더해준다.
                    if (pDataset[a][l] == m + 1)
                        c[m] = c[m] + T[l] * T[l];
                }

            }
            //제곱의 합을 더한후에 루트를 씌운다.
            for (int n = 0; n < item; n++)
            {
                squresum = squresum + c[n] * c[n];
            }
            squreroot = sqrt(squresum);

            for (int o = 0; o < item; o++)
            {
                rho2[o][a] = c[o] / squreroot;
            }
        }

        //입실론값을 구하기위하여 차의 제곱의 합의 루트을 구해준다.
        epsil2 = epsil;
        for (int a = 0; a < item; a++)
        {
            for (int j = 0; j < election; j++)
            {
                ee = rho2[a][j] - rho[a][j];
                ee = ee*ee;
                epsil = epsil + ee;
            }
        }
        epsil = sqrt(epsil);

        for (int a = 0; a < item; a++)
        {
            for (int j = 0; j < election; j++)
            {
                rho[a][j] = rho2[a][j];
            }

        }
        //epsil - epsil2를 해준 이유는 epsil의 값에 대한 0의 초기화가 함수 4에대한 loop밖에 있으므로 그때그때 빼주어야한다.
        if (epsil - epsil2 < 0.0001)
        {
            cout << endl << "<3rd answer>" << endl;
            for (int a = 0; a < item; a++)
            {
                for (int j = 0; j < election; j++)
                {
                    //소수점 두자리까지만 출력하여 간편히 보기위하여 다음과같은 설정을 만족하자.
                    cout << rho[a][j] << "\t";
                    //chart[i] = new int[voter];
                    //memset(chart[i], 0, 4 * voter);
                }
                cout << endl;
            }
            cout.precision(10);
            cout << endl << "epsilon : " << epsil - epsil2 << endl << "counted loop:" << p;
            break;
        }

    }//chart[i] = new int[voter];
     //memset(chart[i], 0, 4 * voter);
     //listpi 함수를 정의하겠다.

    double* listpi = new double[election];

    for (int l = 0; l < election; l++)
    {
        double denom = 0;        //분모값을 denom으로 선언
        double numer = 0;
        listpi[l] = 0;
        //분모
        for (int i = 0; i < 5; i++)
        {//squreroot변수*변수 가 변수^1.5임을 이용

            double result1 = sqrt(rho[i][l])*rho[i][l];
            denom = denom + result1;

        }
        //분자
        for (int i = 0; i < 5; i++)
        {
            double result2 = sqrt(rho[i][l])*rho[i][l] * (i + 1);
            numer = numer + result2;
        }
        listpi[l] = numer / denom;

    }
    cout << endl << endl << "<4th answer>\n";
    cout.precision(5);
    for (int i = 0; i < election; i++)
    {
        cout << "Rating score " << i + 1 << " election is:" << listpi[i] << endl;
    }
}

결과

+ Recent posts