Greedy Searchのプログラムについて

このQ&Aのポイント
  • Greedy SearchについてのプログラムをLinuxで実行しているが、セグメントエラーが発生する。
  • 配列数を増やしても結果は変わらず、原因が分からない。
  • ヒントやアドバイスをいただけると助かります。
回答を見る
  • ベストアンサー

Greedy Searchのプログラムについて

現在、Greedy Searchについてプログラムを組み、Linuxで実行をしていますが、セグメントエラーが発生します。 配列数の不足によるものかと思い、配列の数を1000に増やして宣言したりしましたが、結果は同じになります。 何度か見直しても原因が発見できないので、ヒント、アドバイスをいただけたら幸いです。 #define SRC_X_SIZE 352 入力画像縦サイズ  #define SRC_Y_SIZE 288 入力画像横サイズ #define MB_SIZE 16 マクロブロックサイズ #define MB_X_NUM 22 TB number (SRC_X_SIZE/TB_X_SIZE) #define MB_Y_NUM 18 TB number (SRC_Y_SIZE/TB_Y_SIZE) #define SW_SIZE 7 探索窓サイズ #include "includes.h" /*=============================================================== routine : FullSearch return val : int input par : float *premap float *crtmap float *vecy float *vecx function : full search ===============================================================*/ int fullSearch(float *premap, float *crtmap, float *vecy, float *vecx) { double sum; double min[100]; register int i, j, k, m, n, x, y, xx, yy; int ma[100],na[100],check[1000][1000]; for (y = 0, yy = 0; y < SRC_Y_SIZE; y += MB_SIZE, yy++) { for (x = 0, xx = 0; x < SRC_X_SIZE; x += MB_SIZE, xx++) { ma[k],na[k]=0; min[k] = DBL_MAX; k=0; check[m][n]=0; do{ k++; /*探索範囲*/ for (n = -SW_SIZE + 6 + na[k]; n <= SW_SIZE - 6 + na[k]; n += 1) for (m = -SW_SIZE + 6 + ma[k]; m <= SW_SIZE - 6 + ma[k]; m += 1) { /*既にチェックした座標かどうかの確認*/ if(check[m][n]==0) { /*画像端部の処理*/ if ((y + n < 0) || (x + m < 0) || (SRC_Y_SIZE < y + n + MB_SIZE - 1) || (SRC_X_SIZE < x + m + MB_SIZE - 1)) continue; /*誤差の計算*/ sum = 0.0; for (j = 0; j < MB_SIZE; j++) for (i = 0; i < MB_SIZE; i++) { sum += fabs(crtmap[(y + j)*SRC_X_SIZE + (x + i)] - premap[(y + n + j)*SRC_X_SIZE + (x + m + i)]); } /*動きベクトルの更新*/ if (sum < min[k]) { min[k] = sum; na[k] = n; ma[k] = m; } check[m][n] = 1; } } /*前段階の最小値と比較*/ if(min[k-1] <= min[k]){ na[k] = na[k-1]; ma[k] = ma[k-1]; } }while((na[k] != na[k-1]) && (ma[k] != ma[k-1])); /*前段階の座標と一致するまで処 理を繰り返す*/ vecy[yy*MB_X_NUM + xx] = na[k]; vecx[yy*MB_X_NUM + xx] = ma[k]; } } return 0; }

質問者が選んだベストアンサー

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

C言語は ・基本的に書いてある順番に実行されます。 ・初期化していない変数には何が入っているか不定です。 ・配列の添字が宣言の範囲内かどうかのチェックはしません。 等の特徴があります。 > ma[k],na[k]=0; > min[k] = DBL_MAX; > k=0; 数学ではよく見かける表現ですが、プログラムとしては問題です。 この「k=0」以前にkの値を設定している箇所がありません。そのため、これ以前のkには何が入っているか不定です。 -7かもしれないし573474かもしれない。 記述した順番に実行されるので、「ma[k],na[k]=0;」「min[k] = DBL_MAX;」のkはその不定な値がそのまま使われます。上の-7だった場合は「ma[-7],na[-7]=0;」「min[-7] = DBL_MAX;」です。 ここで「配列の範囲外」とエラーになればまだわかりやすいのですが、Cではそのチェックをしません。なにくわぬ顔で実行しようとします。そしてたまたま動作してしまうこともありますが、大抵はSegmentation Faultが発生します。 > check[m][n]=0; も同様。この時点でmもnも値が入っていません。 それから、 > ma[k],na[k]=0; ですが、C言語には「カンマ演算子」というのがあります。これは、カンマで区切られた式を順番に評価する(そして、最後に評価した値を返す)というものです。上の式は ・ma[k] を評価 ・na[k] =0 を評価(して、式の値である0を返す) となります。 ma[k]=0の意味はありません。 > do{ > k++; ここでも、場合によっては k>=100となる可能性があります。na[k],ma[k],min[k]の範囲外です。自前でエラーチェックするべきです。 /* もっとも、中を見ると、直前の値を使うだけですから、添字を工夫すれば na[2],ma[2],min[2] で十分です。 */ 思ったのですが na[k]=0 check[m][n]=0 って na[k]=0 (すべてのkについて) check[m][n]=0(すべての m,nについて) の意味でつかってませんか?だとしたら、Cにはそんな機能はありません。ループを使って一つずつ代入してください。

hatouiru
質問者

お礼

自己解決できました。回答ありがとうございました。

その他の回答 (3)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

あと、既に指摘のある#defineですが > #define SRC_X_SIZE 352 入力画像縦サイズ  「他から持ってきた」とありますが、そのファイルでもこうなっているのですか? それとも、ここに書いたときにコメントを付けたしたのですか? 前者なら「352 入力画像縦サイズ」がSRC_X_SIZEマクロの値になります。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「#includeの部分から25行下の部分」? #include から 25行下は「/*探索範囲*/」の次の for (n = -SW_SIZE + 6 + na[k]; n <= SW_SIZE - 6 + na[k]; n += 1) だけど, ここで k を初期化してる? for (x = 0, xx = 0; x < SRC_X_SIZE; x += MB_SIZE, xx++) { の次の行, ma[k],na[k]=0; の時点では k は初期化されてないよね. あと, この文で ma[k] って何か意味あるの?

hatouiru
質問者

補足

ma[k],na[k]=0; の次の次の行でk=0;としました。 もしかしたらそれ以前にkを初期化しないといけないのでしょうか・・・? ma[k],na[k]は一回の探索ごとに、探索範囲の最小値であった部分の座標を格納し、次の探索範囲の決定のために使用しています。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

#define は変. あと, fullSearch の中で k はいつ初期化してるの? greedy search なのに「fullSearch」というのも謎だが....

hatouiru
質問者

お礼

自己解決できました。回答ありがとうございました。

hatouiru
質問者

補足

#defineですが、本文中の固有値の説明のため、他の関数部分から引っ張ってきたものです。無視してください。 また、フルサーチとなっている部分はもともとフルサーチのプログラムだったものを直したものなので、そう記述してあります。 ややこしくなってしまい、申し訳ないです。 kは一応#includeの部分から25行下の部分で初期化しているつもりです。

関連するQ&A

  • 次式のような解像度変換のプログラムを作りたいのですが・・・

    以下のような低解像度作成の式があり それをプログラム化してみたのですがいまいちうまくいきません。 先生に式が誤りでないか聞いてみたのですが正しいと言われました。 どなたかプログラムのどの部分が間違っているかご指摘お願いします。 解像度変換の式は以下の通りです。 現画像{Xm,n}とし低解像度画像を{X'm,n}としたとき X'm,n=1/W^2 * Σ[k=0.W-1]Σ[l=0.W-1]    * X[(m+m0)/W]*W+k,[(n+n0)/W]*W+l となり、 式の添字mは縦方向nは横方向を表し、Wは解像度を何分の1にするかという値です(例えばW=5であれば解像度は5*5の25分の1になります) また、Σの中の[(m-m0)/W]と[(n-n0)/W]はガウス記号で少数以下切捨てです。 m0とn0の値は0~W-1の任意の値で これを変化させることで同じ解像度で異なる画像が作成できます。 現画像のサイズ256*256の濃淡画像、 読み込んだ現画像をoriginal[x][y]、 解像度変化後をhenka[x][y]として、 上式の部分の私の作ったプログラムは   int W = 34;//任意の値 int m0 =0;//任意の値 int n0 =0;//任意の値 int x,y; x = y = 0; float sum = 0f; float pixel = 0f; for(int m = 0; m < 256; m++){ for(int n = 0; n < 256; n++) { sum=0; for(int k = 0; k<W ; k++){ for(int l = 0; l<W ; l++){ x = (m+m0)/W; y = (n+n0)/W; x = x * W + k; y = y * W + l; pixel = original[x][y];// sum = sum + (pixel/W/W); } } henka[m][n] = sum; }   } となりました。 しかし実行してみると解像度は確かに変わるのですが W=10,m0=0,n0=0とした場合の結果と W=10,m0=10,n0=10とした場合を比べると 単に前者の結果画像が縦横に10画素ずつずれただけ という結果になりました。 長文になりましたがよろしくお願いしますm(__)m

    • ベストアンサー
    • Java
  • Cのプログラムに変換

    どなたかこのプログラムをCに変化してくれる方いませんか? なんで変換するのとかの質問はいらないです。 ただ純粋に変換してくれる方いませんか? #include <stdio.h> #include <stdlib.h> #include <math.h> #include <complex.h> #define NREPEAT 1000 int sweepout(float complex **a, int size) { int n,m,k; // 前進消去 for(n=0; n<size; n++) { // 軸の選択 { float amax = cabs(a[n][n]);; float aabs; int npivot = n; for(m=n+1; m<size; m++) { if((aabs = cabs(a[m][n]))>amax) { npivot = m; amax = aabs; } } if(aabs == 0.0) return n; if(npivot != n) { // 軸の交換 float complex t; for(k=n; k<=size; k++) { t = a[n][k]; a[n][k] = a[npivot][k]; a[npivot][k] = t; } } } // 消去 { float complex t; t = 1.0/a[n][n]; // 対角要素 a[n][n] <-- 1 for(k=n+1; k<=size; k++) a[n][k] *= t; // 非対角要素 a[m][n] <-- 0 for(m=n+1; m<size; m++) { for(k=n+1; k<=size; k++) a[m][k] -= a[m][n]*a[n][k]; } } } // 後退代入 { float t; for(n=size-1; n>0; n--) { for(m=0; m<n; m++) a[m][size] -= a[n][size]*a[m][n]; } } return -1; } // 乱数を発生する double drand() { double rn; rn = (2*((double)random()))/((double)(RAND_MAX))-1.0; return rn; } main(int argc, char **argv) { int n, m, k, ncount; double complex **a0; float complex **a; double complex t; double d, r; if(argc>1) n = atoi(argv[1]); if(n <=0) n = 3; srandom((argc>2)?atoi(argv[2]):0); a0 = (double complex **)malloc(n*sizeof(double complex *)); for(m=0; m<n; m++) a0[m] = (double complex *)malloc((n+1)*sizeof(double complex)); a = (float complex **)malloc(n*sizeof(float complex *)); for(m=0; m<n; m++) a[m] = (float complex *)malloc((n+1)*sizeof(float complex)); for(ncount=0; ncount<NREPEAT; ncount++) { // 乱数により、配列の係数を決める(double型) for(m=0; m<n; m++) for(k=0; k<=n; k++) a0[m][k] = drand() + 1.0I*drand(); // 係数をfloat型に変換し、配列 a に代入する for(m=0; m<n; m++) { for(k=0; k<n; k++) a[m][k] = (float complex)a0[m][k]; t = 0; for(k=0; k<n; k++) t += a0[m][k]*a0[k][n]; a[m][n] = (float complex)t; } // 連立方程式を解き、数値解を a[][n] に求める sweepout(a,n); // 2乗誤差を求める d = r = 0; for(m=0; m<n; m++) { d += pow(cabs(a[m][n]-a0[m][n]),2); r += pow(cabs(a0[m][n]),2); } printf("%lf\t\n", 0.5*log10(d/r)); } for(m=0; m<n; m++) { free(a0[m]); free(a[m]); } free(a0); free(a); }

  • 組織的ディザ法のプログラムがうまくいきません

    下記のプログラムはPGM画像に組織的ディザ法を行い、2値化を行うプログラムなのですがうまく作動しません。 どこがダメなのかわかる方回答お願いします。 また、PGMのフォーマットをP5しか読み込むことしか出来ないのですが、これを P2のアスキーで読み込めるように変更できないでしょうか? /* 組織的ディザ法のプログラム dither.c */ #include<stdio.h> #include<stdlib.h> #include<string.h> #include"mypgm.h" #define BLOCK_SIZE 4 /* ブロックの横(=縦)画素数 */ #define NEW_LEVEL 16 /* 擬似階調数(= BLOCK_SIZE の2乗) */ #define MAXWIDTH 1000 #define MAXHEIGHT 1000 /* 原画像 image1[y][x] のディザ画像を作り image2[y][x] に代入 */ void make_dither_image( ) { double width; /* 16段階画像の階調値の単位幅 */ int x,y,i,j,m,n; int x_block = x_size1 / BLOCK_SIZE; /* 横のブロック数 */ int y_block = y_size1 / BLOCK_SIZE; /* 縦のブロック数 */ int gray_16 = (int)( image1[y][x] / width ); /* 新しい階調(16階調での値) */ /* Bayer 型ディザ行列 */ int dither_matrix [4][4] = { { 0, 8, 2, 10}, {12, 4, 14, 6}, { 3, 11, 1, 9}, {15, 7, 13, 5} }; /* 横,縦の画素数がBLOCK_SIZEの倍数であるかのチェック */ if ( x_size1 % BLOCK_SIZE != 0 || y_size1 % BLOCK_SIZE != 0 ){ printf("原画像の横・縦の画素数が不適切です.\n"); exit(1); } /* 16階調の画像を作る */ //一度、画像を16階調に変換して(正確にはディザブロック分の1)さらに2階調(白黒)に変換する。 width = MAX_BRIGHTNESS / (double)NEW_LEVEL; x_size2 = x_size1; y_size2 = y_size1; for (y = 0; y < y_size1; y ++ ){ for (x = 0; x < x_size1; x ++ ){ if ( gray_16 > NEW_LEVEL - 1 ) gray_16 = NEW_LEVEL - 1; image2[y][x] = (unsigned char)gray_16; } } /* ディザ画像を作る */ printf("ディザ画像を作ります.\n"); for (i = 0; i < y_block; i ++ ){ for (j = 0; j < x_block; j ++ ){ int x = BLOCK_SIZE * j; int y = BLOCK_SIZE * i; for (m = 0; m < BLOCK_SIZE; m ++ ){ for (n = 0; n < BLOCK_SIZE; n ++ ){ if ( image2[y + m][x + n] <= dither_matrix[m][n] ) image2[y + m][x + n] = 0; else image2[y + m][x + n] = MAX_BRIGHTNESS; } } } } } 【mypgm.h】 http://cis.k.hosei.ac.jp/~wakahara/mypgm.h

  • C言語のプログラムを見てください

    ある100行の値がx列、y列の2列あるファイルを読み込んでそれを配列に入れ、yの最小値及びそれと同じ行にあるxの値を表示するプログラムを書きたいのですがy列の最小値を表示するプログラムを書き終えた所でコンパイルして実行してみると正しく値が表示されませんでした。それどころか実行するたびに値が変わってしまいます。どこがおかしいのかわからないため、ご指摘のほどよろしくお願いします。また、できれば同じ行にあるx列の値も表示させるプログラムを教えてください。 よろしくお願いします。 #include <stdio.h> #include <stdlib.h> #define N 100 int main(void) { int x[N],i; double y[N],min; FILE *fp; fp=fopen("book.dat","r"); if(fp==NULL){ puts("can't open file!"); exit(-1); } for(i=0;i<N;i++){ fscanf(fp,"%d %lf", &x[N],&y[N]); printf("x=%d\n y=%lf\n",x[N],y[N]); } min=y[0]; for(i=1;i<N;i++){ if(y[i]<min) min=y[i]; } fclose(fp); printf("最小値:%lf\n",min); return 0; }

  • 行列の計算

    #include<stdio.h> #define N 2 #define M 3 void hyoji(float[][M]); int main(){ int i,j,k; float a[N][M] = {{2.0,2.0,2.0},{2.0,2.0,2.0}}; float b[M][M] = {{1.0,1.0,1.0},{2.0,2.0,2.0},{1.0,1.0,1.0}}; float c[N][N]; for(i=0; i<N; i++){ for(j=0; j<M; j++){ c[i][j] = 0; for(k=0; k<M; k++){ c[i][j] += a[i][k] * b[k][j]; } } } hyoji(c); return(0); } void hyoji(float x[][M]){ int i,j; for(i=0; i<N; i++){ for(j=0; j<M; j++){ printf("%4.1f ",x[i][j]); } printf("\n"); } } 以上のプログラムで 行列aと行列bをかけ合せた行列cを求めるのですが コンパイルすると 8 8 8 8 8 1 となり、正しい結果がでません。 なにが間違っているのでしょうか?? よろしくお願いします。

  • C言語のプログラムで質問です。

    C言語のプログラムで質問です。 下のプログラム(最小二乗法の計算)を実行したところ -1.#IND00 というエラーが出てしまいます。 どこを直せばいいのでしょうか、教えてください。 #include <stdio.h> #include <math.h> /* gauss33.c */ #define N 3 main(){ double A[N][N],Aa[N][N]; double b[N],x[N], bb[N], e[N]; int n=N; int i, j, k; double akk, aik, s; double y[N]; double xx,yy; for(i=0;i<n;i++){ /*変数の初期化*/ x[i]=y[i]=0; for(j=0;j<n;j++) A[i][j]=0; } for(i=0;i<5;i++){ /*データ点は5点*/ printf("\n(x,y)="); scanf("%lf,%lf",&xx,&yy); A[0][0]+=xx*xx*xx*xx; /*Σx^4*/ A[0][1]+=xx*xx*xx; /*Σx^3*/ A[0][2]+=xx*xx; /*Σx^2*/ A[0][1]=A[1][0]; A[0][2]=A[1][1]=A[2][0]; A[1][2]+=xx; /*Σx*/ A[1][2]=A[2][1]; A[2][2]=n; y[0]+=xx*xx*yy; /*Σx^2y*/ y[1]+=xx*yy; /*Σxy*/ y[2]+=yy; /*Σy*/ } /* save original coefficients */ for(i=0; i<n; i++){ for(j=0; j<n; j++){ Aa[i][j]=A[i][j]; } bb[i]=b[i]; } /* forward operation */ for(k=0; k<n-1; k++){ akk=1/A[k][k]; for (i=k+1; i<n; i++){ aik=-A[i][k]*akk; for (j=k+1; j<n; j++){ A[i][j]+=aik*A[k][j]; } b[i]+=aik*b[k]; } for(j=k+1; j<n; j++){ A[k][j]*=akk; } b[k]*=akk; } /* backward operation */ x[n-1]=b[n-1]/A[n-1][n-1]; for(k=n-2; k>=0; k--){ s=0.0; for (j=k+1; j<n; j++){ s+=A[k][j]*x[j]; } x[k]=b[k]-s; } /* chek */ for(i=0; i<n; i++){ s=0.0; for(j=0; j<n; j++){ s+=Aa[i][j]*x[j];} e[i]=s-bb[i]; printf("\nx(%d)=%f error=%f\n",i, x[i], e[i]); } }

  • 数独を解くアルゴリズム

    バックトラック法で解いているのですが、どこがおかしいのか見当もつかないので教えてください。 コンパイルエラーはありません。 表示の関数は省いてあります。 よろしくお願いします。 #include <stdio.h> #define M 3 //小さいブロックのサイズ #define N M*M //全体のサイズ #define MTX N*N //全体のマス数 int sudoku[N][N]={    {0,2,4,5,0,0,6,0,0},    {0,0,6,3,2,0,0,0,4},    {0,0,5,0,9,0,0,8,3},    {0,0,8,4,0,3,0,0,1},    {0,6,1,9,0,0,4,3,0},    {7,0,0,1,0,0,5,0,0},    {8,3,0,0,4,0,9,0,0},    {4,0,0,0,3,5,8,0,0},    {0,0,7,0,0,9,3,4,0}    }; /* 候補がOKかどうかチェック */ int OKkouho(int x, int y, int k) {    int i,j;    int p,q;    for(i=0; i < N; i++){ //その行に候補は入るか       if(sudoku[y][i] == k)          return 0;    }    for(j=0; j < N; j++){ //その列に候補は入るか       if(sudoku[j][x] == k)          return 0;    }    p = x/M*M;    q = y/M*M;    //そのブロックに候補は入るか    for(j = q; j < q+M; j++){       for(i = p; i < p+M; i++){          if(sudoku[j][i] == k)             return 0;       }    }    return 1; } void Solve(int level) {    int k;    int x,y;    if(level >= MTX){       printf("OK");       return;    }    x = level%N;    y = level/N;    if(sudoku[y][x])       Solve(level+1);    else{       for(k = 1; k <= N; k++){          if(OKkouho(x,y,k)){             sudoku[y][x] = k;             Solve(level+1);             sudoku[y][x] = 0;             }       }    } } int main(void) {    Solve(0);    return 0; }

  • 行列の積のプログラム

    n次正方行列X=(xij),Y=(yij)の積XYの(i,j)成分はΣ(k=1,n)xikykjで定義する。これをmin{k∈1,2,…n}(xik+ykj)と変更したとき行列の積を計算するプログラムの作成をしたいです。 ※minXは、Xの中の最小値を意味する。 十進BASICで解きたいのですが、以下のプログラムで間違いがあったら指摘してただけないでしょうか?よろしくお願いします。 INPUT N DIM X(n,n) DIM Y(n,n) DIM Z(n,n) INPUT X(n,n) INPUT Y(n,n) FOR i = 1 TO n  FOR j = 1 TO n   LET Z(i,j) = X(i,1) * Y(1,j)    FOR k = 2 TO n     IF Z(i,j) > X(i,k) * Y(k,j) THEN LET Z(i,j) = X(i,k) * Y(k,j)   NEXT k  NEXT j NEXT i INPUT Z(n,n) END

  • 変数宣言にいらないの入れると正確な出力になる(なんかおかしいです

    main関数の中の double x,y; のままだと出力のout.txtは間違った答えになるのに double x,y,n;とか関係ない変数を宣言に足すと、 正解な値が出ます。 ソースはRunge-Kuttaの計算をするものです。 他はまったく変えてないのになぜ結果がちがくなるのでしょうか? おかしいとおもって友達などにも実行してもらったんですが同じ症状がでます。 環境はVC++6.0でOSはMEと2kとXPで試したんですが、同じ結果でした。 ソースは↓です。よろしくお願いします。 #include<stdio.h> #include<stdlib.h> #define X0 0.0 #define Y0 1.0 #define XEND 0.5 #define XSTEP 0.1 double func(double xx,double yy); main() { double x,y; double k[3]; FILE *fp1; if(!(fp1=fopen("out.txt","w"))){ printf("ファイルを開けません\n"); exit(1); } x=X0; y=Y0; for(x=X0;x<=XEND;x=x+XSTEP){ fprintf(fp1,"%f\t%f\t\n",x,y); k[0]=XSTEP*func(x,y); k[1]=XSTEP*func(x+XSTEP/2,y+k[0]/2); k[2]=XSTEP*func(x+XSTEP/2,y+k[1]/2); k[3]=XSTEP*func(x+XSTEP,y+k[2]); y=y+(k[0]+2*k[1]+2*k[2]+k[3])/6; } return 0; } double func(double xx,double yy) { return yy; }

  • 台形公式について

    台形公式を使って、2*sqrt(1-x*x)の-1から1の積分の近似値を求めようと思うのですが、結果が違う気がします。おかしなところがありますか?また、皆さんの結果ではどういった結果が出てきますか? 台形公式のプログラムリスト double daikei(double N){ int k; double y,S,sum; sum = 0.0; for(k=0; k<=N; k++){ y = 4.0 * sqrt((k/N)*(1.0+(k/N))); if(k==0 , k==N){ S = (1.0/N) * y; } else { S = (2.0/N) * y; } sum = sum + S; } return sum; }

専門家に質問してみよう