情報学部 菅沼ホーム 目次 索引

最適化(シンプレックス法)

    1. A. C++
    2. B. Java
    3. C. JavaScript
    4. D. PHP
    5. E. Ruby
    6. F. Python
    7. G. C#
    8. H. VB

  プログラムは,シンプレックス法を使用して,非線形関数の最小値を求めるためのものです( プログラムの使用方法).

  1. C++

    /**************************************/
    /* シンプレックス法による最小値の計算 */
    /*      coded by Y.Suganuma           */
    /**************************************/
    #include <stdio.h>
    
    double snx1(double *);
    double snx2(double *);
    double snx3(double *);
    int simplex(int, int, double, double, double, double, double *, double *, double (*)(double *));
    
    int main()
    {
    	double eps, r1, r2, *x, y, k;
    	int fun, i1, max, n, sw = 0;
    					// データの入力
    	scanf("%*s %d %*s %d %*s %d %*s %lf", &fun, &n, &max, &k);
    	scanf("%*s %lf %*s %lf %*s %lf", &eps, &r1, &r2);
    	x = new double [n];
    	scanf("%*s");
    	for (i1 = 0; i1 < n; i1++)
    		scanf("%lf", &x[i1]);
    					// 実行
    	switch (fun) {
    		case 1:
    			sw = simplex(max, n, k, eps, r1, r2, &y, x, snx1);
    			break;
    		case 2:
    			sw = simplex(max, n, k, eps, r1, r2, &y, x, snx2);
    			break;
    		case 3:
    			sw = simplex(max, n, k, eps, r1, r2, &y, x, snx3);
    			break;
    	}
    					// 結果の出力
    	if (sw < 0)
    		printf("   収束しませんでした!");
    	else {
    		printf("   結果=");
    		for (i1 = 0; i1 < n; i1++)
    			printf("%f ", x[i1]);
    		printf(" 最小値=%f  回数=%d\n", y, sw);
    	}
    
    	delete [] x;
    
    	return 0;
    }
    
    /******************************************/
    /* シンプレックス法                       */
    /*      max : 最大繰り返し回数            */
    /*      n : 次元                          */
    /*      k : 初期値設定係数                */
    /*      r1 : 縮小比率                     */
    /*      r2 : 拡大比率                     */
    /*      y : 最小値                        */
    /*      x : x(初期値と答え)               */
    /*      snx : 関数値を計算する関数名      */
    /*      return : >=0 : 正常終了(収束回数) */
    /*               =-1 : 収束せず           */
    /******************************************/
    #include <math.h>
    
    int simplex(int max, int n, double k, double eps, double r1, double r2, double *y, double *x, double (*snx)(double *))
    {
    	double **xx, *yy, *xg, *xr, *xn, yr, yn, e;
    	int i1, i2, fh = -1, fg = -1, fl = -1, count = 0, sw = -1;
    					// 初期値の設定
    	yy = new double [n+1];
    	xg = new double [n];
    	xr = new double [n];
    	xn = new double [n];
    	xx = new double * [n+1];
    	for (i1 = 0; i1 < n+1; i1++)
    		xx[i1] = new double [n];
    	for (i1 = 0; i1 < n+1; i1++) {
    		for (i2 = 0; i2 < n; i2++)
    			xx[i1][i2] = x[i2];
    		if (i1 > 0)
    			xx[i1][i1-1] += k;
    		yy[i1] = snx(xx[i1]);
    	}
    					// 最大値,最小値の計算
    	for (i1 = 0; i1 < n+1; i1++) {
    		if (fh < 0 || yy[i1] > yy[fh])
    			fh = i1;
    		if (fl < 0 || yy[i1] < yy[fl])
    			fl = i1;
    	}
    	for (i1 = 0; i1 < n+1; i1++) {
    		if (i1 != fh && (fg < 0 || yy[i1] > yy[fg]))
    			fg = i1;
    	}
    					// 最小値の計算
    	while (count < max && sw < 0) {
    		count++;
    							// 重心の計算
    		for (i1 = 0; i1 < n; i1++)
    			xg[i1] = 0.0;
    		for (i1 = 0; i1 < n+1; i1++) {
    			if (i1 != fh) {
    				for (i2 = 0; i2 < n; i2++)
    					xg[i2] += xx[i1][i2];
    			}
    		}
    		for (i1 = 0; i1 < n; i1++)
    			xg[i1] /= n;
    							// 最大点の置き換え
    		for (i1 = 0; i1 < n; i1++)
    			xr[i1] = 2.0 * xg[i1] - xx[fh][i1];
    		yr = snx(xr);
    		if (yr >= yy[fh]) {   // 縮小
    			for (i1 = 0; i1 < n; i1++)
    				xr[i1] = (1.0 - r1) * xx[fh][i1] + r1 * xr[i1];
    			yr = snx(xr);
    		}
    		else if (yr < (yy[fl]+(r2-1.0)*yy[fh])/r2) {   // 拡大
    			for (i1 = 0; i1 < n; i1++)
    				xn[i1] = r2 * xr[i1] - (r2 - 1.0) * xx[fh][i1];
    			yn = snx(xn);
    			if (yn <= yr) {
    				for (i1 = 0; i1 < n; i1++)
    					xr[i1] = xn[i1];
    				yr = yn;
    			}
    		}
    		for (i1 = 0; i1 < n; i1++)
    			xx[fh][i1] = xr[i1];
    		yy[fh] = yr;
    							// シンプレックス全体の縮小
    		if (yy[fh] >= yy[fg]) {
    			for (i1 = 0; i1 < n+1; i1++) {
    				if (i1 != fl) {
    					for (i2 = 0; i2 < n; i2++)
    						xx[i1][i2] = 0.5 * (xx[i1][i2] + xx[fl][i2]);
    					yy[i1] = snx(xx[i1]);
    				}
    			}
    		}
    							// 最大値,最小値の計算
    		fh = -1;
    		fg = -1;
    		fl = -1;
    		for (i1 = 0; i1 < n+1; i1++) {
    			if (fh < 0 || yy[i1] > yy[fh])
    				fh = i1;
    			if (fl < 0 || yy[i1] < yy[fl])
    				fl = i1;
    		}
    		for (i1 = 0; i1 < n+1; i1++) {
    			if (i1 != fh && (fg < 0 || yy[i1] > yy[fg]))
    				fg = i1;
    		}
    							// 収束判定
    		e = 0.0;
    		for (i1 = 0; i1 < n+1; i1++) {
    			if (i1 != fl) {
    				yr  = yy[i1] - yy[fl];
    				e  += yr * yr;
    			}
    		}
    		if (e < eps)
    			sw = 0;
    	}
    
    	if (sw == 0) {
    		sw = count;
    		*y = yy[fl];
    		for (i1 = 0; i1 < n; i1++)
    			x[i1] = xx[fl][i1];
    	}
    
    	delete [] yy;
    	delete [] xg;
    	delete [] xr;
    	delete [] xn;
    	for (i1 = 0; i1 < n+1; i1++)
    		delete [] xx[i1];
    	delete [] xx;
    
    	return sw;
    }
    
    /*******************/
    /* 関数値の計算    */
    /*      y = f(x)   */
    /*      return : y */
    /*******************/
    					// 関数1
    double snx1(double *x)
    {
    	double x1, y1, y;
    
    	x1 = x[0] - 1.0;
    	y1 = x[1] - 2.0;
    	y  = x1 * x1 + y1 * y1;
    
    	return y;
    }
    					// 関数2
    double snx2(double *x)
    {
    	double x1, y1, y;
    
    	x1 = x[1] - x[0] * x[0];
    	y1 = 1.0 - x[0];
    	y  = 100.0 * x1 * x1 + y1 * y1;
    
    	return y;
    }
    					// 関数3
    double snx3(double *x)
    {
    	double x1, y1, z1, y;
    
    	x1 = 1.5 - x[0] * (1.0 - x[1]);
    	y1 = 2.25 - x[0] * (1.0 - x[1] * x[1]);
    	z1 = 2.625 - x[0] * (1.0 - x[1] * x[1] * x[1]);
    	y  = x1 * x1 + y1 * y1 + z1 * z1;
    
    	return y;
    }
    			

  2. Java

    /**************************************/
    /* シンプレックス法による最小値の計算 */
    /*      coded by Y.Suganuma           */
    /**************************************/
    import java.io.*;
    import java.util.StringTokenizer;
    
    public class Test {
    	public static void main(String args[]) throws IOException
    	{
    		double eps, r1, r2, x[], y[], k;
    		int fun, i1, max, n, sw = 0;
    		StringTokenizer str;
    		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    					// データの入力
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		fun = Integer.parseInt(str.nextToken());
    		str.nextToken();
    		n = Integer.parseInt(str.nextToken());
    		str.nextToken();
    		max = Integer.parseInt(str.nextToken());
    		str.nextToken();
    		k = Double.parseDouble(str.nextToken());
    		x = new double [n];
    		y  = new double [1];
    
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		eps = Double.parseDouble(str.nextToken());
    		str.nextToken();
    		r1 = Double.parseDouble(str.nextToken());
    		str.nextToken();
    		r2 = Double.parseDouble(str.nextToken());
    
    		str = new StringTokenizer(in.readLine(), " ");
    		str.nextToken();
    		for (i1 = 0; i1 < n; i1++) {
    			x[i1] = Double.parseDouble(str.nextToken());
    		}
    					// 実行
    		Kansu kn = new Kansu(fun);
    		sw = kn.simplex(max, n, k, eps, r1, r2, y, x);
    					// 結果の出力
    		if (sw < 0)
    			System.out.print("   収束しませんでした!");
    		else {
    			System.out.print("   結果=");
    			for (i1 = 0; i1 < n; i1++)
    				System.out.print(x[i1] + " ");
    			System.out.println(" 最小値=" + y[0] + "  回数=" + sw);
    		}
    	}
    }
    
    /**********/
    /* 関数値 */
    /**********/
    class Kansu extends Simplex
    {
    	private int sw;
    					// コンストラクタ
    	Kansu (int s) {sw = s;}
    					// 関数値の計算
    	double snx(double x[])
    	{
    		double x1, y1, z1, y = 0.0;
    
    		switch (sw) {
    			case 1:
    				x1 = x[0] - 1.0;
    				y1 = x[1] - 2.0;
    				y  = x1 * x1 + y1 * y1;
    				break;
    			case 2:
    				x1 = x[1] - x[0] * x[0];
    				y1 = 1.0 - x[0];
    				y  = 100.0 * x1 * x1 + y1 * y1;
    				break;
    			case 3:
    				x1 = 1.5 - x[0] * (1.0 - x[1]);
    				y1 = 2.25 - x[0] * (1.0 - x[1] * x[1]);
    				z1 = 2.625 - x[0] * (1.0 - x[1] * x[1] * x[1]);
    				y  = x1 * x1 + y1 * y1 + z1 * z1;
    				break;
    		}
    
    		return y;
    	}
    }
    
    abstract class Simplex {
    
    	/******************************************/
    	/* シンプレックス法                       */
    	/*      max : 最大繰り返し回数            */
    	/*      n : 次元                          */
    	/*      k : 初期値設定係数                */
    	/*      r1 : 縮小比率                     */
    	/*      r2 : 拡大比率                     */
    	/*      y : 最小値                        */
    	/*      x : x(初期値と答え)               */
    	/*      return : >=0 : 正常終了(収束回数) */
    	/*               =-1 : 収束せず           */
    	/******************************************/
    
    	abstract double snx(double x[]);
    
    	int simplex(int max, int n, double k, double eps, double r1, double r2, double y[], double x[])
    	{
    		double xx[][], yy[], xg[], xr[], xn[], yr, yn, e;
    		int i1, i2, fh = -1, fg = -1, fl = -1, count = 0, sw = -1;
    						// 初期値の設定
    		yy = new double [n+1];
    		xg = new double [n];
    		xr = new double [n];
    		xn = new double [n];
    		xx = new double [n+1][n];
    		for (i1 = 0; i1 < n+1; i1++) {
    			for (i2 = 0; i2 < n; i2++)
    				xx[i1][i2] = x[i2];
    			if (i1 > 0)
    				xx[i1][i1-1] += k;
    			yy[i1] = snx(xx[i1]);
    		}
    						// 最大値,最小値の計算
    		for (i1 = 0; i1 < n+1; i1++) {
    			if (fh < 0 || yy[i1] > yy[fh])
    				fh = i1;
    			if (fl < 0 || yy[i1] < yy[fl])
    				fl = i1;
    		}
    		for (i1 = 0; i1 < n+1; i1++) {
    			if (i1 != fh && (fg < 0 || yy[i1] > yy[fg]))
    				fg = i1;
    		}
    						// 最小値の計算
    		while (count < max && sw < 0) {
    			count++;
    								// 重心の計算
    			for (i1 = 0; i1 < n; i1++)
    				xg[i1] = 0.0;
    			for (i1 = 0; i1 < n+1; i1++) {
    				if (i1 != fh) {
    					for (i2 = 0; i2 < n; i2++)
    						xg[i2] += xx[i1][i2];
    				}
    			}
    			for (i1 = 0; i1 < n; i1++)
    				xg[i1] /= n;
    								// 最大点の置き換え
    			for (i1 = 0; i1 < n; i1++)
    				xr[i1] = 2.0 * xg[i1] - xx[fh][i1];
    			yr = snx(xr);
    			if (yr >= yy[fh]) {   // 縮小
    				for (i1 = 0; i1 < n; i1++)
    					xr[i1] = (1.0 - r1) * xx[fh][i1] + r1 * xr[i1];
    				yr = snx(xr);
    			}
    			else if (yr < (yy[fl]+(r2-1.0)*yy[fh])/r2) {   // 拡大
    				for (i1 = 0; i1 < n; i1++)
    					xn[i1] = r2 * xr[i1] - (r2 - 1.0) * xx[fh][i1];
    				yn = snx(xn);
    				if (yn <= yr) {
    					for (i1 = 0; i1 < n; i1++)
    						xr[i1] = xn[i1];
    					yr = yn;
    				}
    			}
    			for (i1 = 0; i1 < n; i1++)
    				xx[fh][i1] = xr[i1];
    			yy[fh] = yr;
    								// シンプレックス全体の縮小
    			if (yy[fh] >= yy[fg]) {
    				for (i1 = 0; i1 < n+1; i1++) {
    					if (i1 != fl) {
    						for (i2 = 0; i2 < n; i2++)
    							xx[i1][i2] = 0.5 * (xx[i1][i2] + xx[fl][i2]);
    						yy[i1] = snx(xx[i1]);
    					}
    				}
    			}
    								// 最大値,最小値の計算
    			fh = -1;
    			fg = -1;
    			fl = -1;
    			for (i1 = 0; i1 < n+1; i1++) {
    				if (fh < 0 || yy[i1] > yy[fh])
    					fh = i1;
    				if (fl < 0 || yy[i1] < yy[fl])
    					fl = i1;
    			}
    			for (i1 = 0; i1 < n+1; i1++) {
    				if (i1 != fh && (fg < 0 || yy[i1] > yy[fg]))
    					fg = i1;
    			}
    								// 収束判定
    			e = 0.0;
    			for (i1 = 0; i1 < n+1; i1++) {
    				if (i1 != fl) {
    					yr  = yy[i1] - yy[fl];
    					e  += yr * yr;
    				}
    			}
    			if (e < eps)
    				sw = 0;
    		}
    	
    		if (sw == 0) {
    			sw   = count;
    			y[0] = yy[fl];
    			for (i1 = 0; i1 < n; i1++)
    				x[i1] = xx[fl][i1];
    		}
    	
    		return sw;
    	}
    }
    			

  3. JavaScript

      ここをクリックすると,JavaScript の仕様に適合した形で最小値を求めたい式を入力することによって,任意の関数の最小値を画面上で求めることができます.
    <!DOCTYPE HTML>
    
    <HTML>
    
    <HEAD>
    
    	<TITLE>最適化(シンプレックス法)</TITLE>
    	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
    	<SCRIPT TYPE="text/javascript">
    		str = "";
    		function main()
    		{
    					// データの設定
    			let n   = parseInt(document.getElementById("n").value);
    			let max = parseInt(document.getElementById("max").value);
    			let k   = parseFloat(document.getElementById("k").value);
    			let r1  = parseFloat(document.getElementById("r1").value);
    			let r2  = parseFloat(document.getElementById("r2").value);
    			let x   = document.getElementById("x0").value.split(/ {1,}/)
    			for (let i1 = 0; i1 < n; i1++)
    				x[i1] = parseFloat(x[i1]);
    			str = document.getElementById("func").value + ";";
    			let eps = 1.0e-20;
    			let y   = new Array();
    					// 実行
    			let sw = simplex(max, n, k, eps, r1, r2, y, x, snx);
    					// 結果
    			let res;
    			if (sw < 0) {
    				res = " 収束しませんでした!";
    				switch (sw) {
    					case -1:
    						res += "(収束回数)";
    						break;
    					case -2:
    						res += "(1次元最適化の区間)";
    						break;
    					case -3:
    						res += "(黄金分割法)";
    						break;
    				}
    				document.getElementById("res").value = res;
    			}
    			else {
    				let c = 100000;
    				res = " x =";
    				for (let i1 = 0; i1 < n; i1++) {
    					let s1 = Math.round(x[i1] * c) / c;
    					res = res + " " + s1;
    				}
    				res += "\n";
    				let s2 = Math.round(y[0] * c) / c;
    				res = res + " 最小値 = " + s2 + "  回数 = " + sw;
    				document.getElementById("res").value = res;
    			}
    		}
    
    		/****************/
    		/* 関数値の計算 */
    		/****************/
    		function snx(x)
    		{
    			let y = eval(str);
    			return y;
    		}
    
    		/******************************************/
    		/* シンプレックス法                       */
    		/*      max : 最大繰り返し回数            */
    		/*      n : 次元                          */
    		/*      k : 初期値設定係数                */
    		/*      r1 : 縮小比率                     */
    		/*      r2 : 拡大比率                     */
    		/*      y : 最小値                        */
    		/*      x : x(初期値と答え)               */
    		/*      fn : 関数値を計算する関数         */
    		/*      return : >=0 : 正常終了(収束回数) */
    		/*               =-1 : 収束せず           */
    		/******************************************/
    		function simplex(max, n, k, eps, r1, r2, y, x, fn)
    		{
    			let yr, yn, e, fh = -1, fg = -1, fl = -1, count = 0, sw = -1;
    						// 初期値の設定
    			yy = new Array();
    			xg = new Array();
    			xr = new Array();
    			xn = new Array();
    			xx = new Array();
    			for (let i1 = 0; i1 < n+1; i1++) {
    				xx[i1] = new Array();
    				for (let i2 = 0; i2 < n; i2++)
    					xx[i1][i2] = x[i2];
    				if (i1 > 0)
    					xx[i1][i1-1] += k;
    				yy[i1] = fn(xx[i1]);
    			}
    						// 最大値,最小値の計算
    			for (let i1 = 0; i1 < n+1; i1++) {
    				if (fh < 0 || yy[i1] > yy[fh])
    					fh = i1;
    				if (fl < 0 || yy[i1] < yy[fl])
    					fl = i1;
    			}
    			for (let i1 = 0; i1 < n+1; i1++) {
    				if (i1 != fh && (fg < 0 || yy[i1] > yy[fg]))
    					fg = i1;
    			}
    						// 最小値の計算
    			while (count < max && sw < 0) {
    				count++;
    								// 重心の計算
    				for (let i1 = 0; i1 < n; i1++)
    					xg[i1] = 0.0;
    				for (let i1 = 0; i1 < n+1; i1++) {
    					if (i1 != fh) {
    						for (let i2 = 0; i2 < n; i2++)
    							xg[i2] += xx[i1][i2];
    					}
    				}
    				for (let i1 = 0; i1 < n; i1++)
    					xg[i1] /= n;
    								// 最大点の置き換え
    				for (let i1 = 0; i1 < n; i1++)
    					xr[i1] = 2.0 * xg[i1] - xx[fh][i1];
    				yr = fn(xr);
    				if (yr >= yy[fh]) {   // 縮小
    					for (i1 = 0; i1 < n; i1++)
    						xr[i1] = (1.0 - r1) * xx[fh][i1] + r1 * xr[i1];
    					yr = fn(xr);
    				}
    				else if (yr < (yy[fl]+(r2-1.0)*yy[fh])/r2) {   // 拡大
    					for (let i1 = 0; i1 < n; i1++)
    						xn[i1] = r2 * xr[i1] - (r2 - 1.0) * xx[fh][i1];
    					yn = fn(xn);
    					if (yn <= yr) {
    						for (i1 = 0; i1 < n; i1++)
    							xr[i1] = xn[i1];
    						yr = yn;
    					}
    				}
    				for (let i1 = 0; i1 < n; i1++)
    					xx[fh][i1] = xr[i1];
    				yy[fh] = yr;
    								// シンプレックス全体の縮小
    				if (yy[fh] >= yy[fg]) {
    					for (let i1 = 0; i1 < n+1; i1++) {
    						if (i1 != fl) {
    							for (let i2 = 0; i2 < n; i2++)
    								xx[i1][i2] = 0.5 * (xx[i1][i2] + xx[fl][i2]);
    							yy[i1] = fn(xx[i1]);
    						}
    					}
    				}
    								// 最大値,最小値の計算
    				fh = -1;
    				fg = -1;
    				fl = -1;
    				for (let i1 = 0; i1 < n+1; i1++) {
    					if (fh < 0 || yy[i1] > yy[fh])
    						fh = i1;
    					if (fl < 0 || yy[i1] < yy[fl])
    						fl = i1;
    				}
    				for (let i1 = 0; i1 < n+1; i1++) {
    					if (i1 != fh && (fg < 0 || yy[i1] > yy[fg]))
    						fg = i1;
    				}
    								// 収束判定
    				e = 0.0;
    				for (let i1 = 0; i1 < n+1; i1++) {
    					if (i1 != fl) {
    						yr  = yy[i1] - yy[fl];
    						e  += yr * yr;
    					}
    				}
    				if (e < eps)
    					sw = 0;
    			}
    	
    			if (sw == 0) {
    				sw   = count;
    				y[0] = yy[fl];
    				for (let i1 = 0; i1 < n; i1++)
    					x[i1] = xx[fl][i1];
    			}
    	
    			return sw;
    		}
    	</SCRIPT>
    
    </HEAD>
    
    <BODY STYLE="font-size: 130%; background-color: #eeffee;">
    
    	<H2 STYLE="text-align:center"><B>最適化(シンプレックス法)</B></H2>
    
    	<DL>
    		<DT>  テキストフィールドには,例として,以下に示すような関数の最小値を求める場合に対する値が設定されています(他の問題を実行する場合は,それらを適切に修正してください).
    		<P STYLE="text-align:center"><IMG SRC="simplex.gif"></P>
    		<DT>目的関数の箇所には,その計算式が与えられています.ただし,プログラム内では,変数 x は,この例の x と y からなる配列として表現されています.なお,目的関数は,JavaScript の仕様に適合した形式で記述してあることに注意してください. 
    	</DL>
    
    	<DIV STYLE="text-align:center">
    		変数の数(n):<INPUT ID="n" STYLE="font-size: 100%" TYPE="text" SIZE="2" VALUE="2"> 
    		最大繰り返し回数:<INPUT ID="max" STYLE="font-size: 100%" TYPE="text" SIZE="3" VALUE="1000"> 
    		初期値設定係数:<INPUT ID="k" STYLE="font-size: 100%" TYPE="text" SIZE="3" VALUE="1.0"><BR>
    		縮小比率:<INPUT ID="r1" STYLE="font-size: 100%" TYPE="text" SIZE="3" VALUE="0.7"> 
    		拡大比率:<INPUT ID="r2" STYLE="font-size: 100%" TYPE="text" SIZE="3" VALUE="1.5"> 
    		初期値(n個):<INPUT ID="x0" STYLE="font-size: 100%" TYPE="text" SIZE="20" VALUE="0.0 0.0"><BR><BR>
    		目的関数: f(x) = <INPUT ID="func" STYLE="font-size: 100%" TYPE="text" SIZE="70" VALUE="100.0 * (x[1] - x[0] * x[0]) * (x[1] - x[0] * x[0]) + (1.0 - x[0]) * (1.0 - x[0])"><BR><BR>
    		<BUTTON STYLE="font-size: 100%; background-color: pink" onClick="main()">実行</BUTTON><BR><BR>
    		結果:<TEXTAREA ID="res" STYLE="font-size: 110%" COLS="40" ROWS="2"></TEXTAREA>
    	</DIV>
    
    </BODY>
    
    </HTML>
    			

  4. PHP

    <?php
    
    /**************************************/
    /* シンプレックス法による最小値の計算 */
    /*      coded by Y.Suganuma           */
    /**************************************/
    
    	$sw = 0;
    					// データの入力
    	fscanf(STDIN, "%*s %d %*s %d %*s %d %*s %lf", $fun, $n, $max, $k);
    	fscanf(STDIN, "%*s %lf %*s %lf %*s %lf", $eps, $r1, $r2);
    
    	$x   = array($n);
    	$str = trim(fgets(STDIN));
    	strtok($str, " ");
    	for ($i1 = 0; $i1 < $n; $i1++)
    		$x[$i1] = floatval(strtok(" "));
    					// 実行
    	switch ($fun) {
    		case 1:
    			$sw = simplex($max, $n, $k, $eps, $r1, $r2, $y, $x, "snx1");
    			break;
    		case 2:
    			$sw = simplex($max, $n, $k, $eps, $r1, $r2, $y, $x, "snx2");
    			break;
    		case 3:
    			$sw = simplex($max, $n, $k, $eps, $r1, $r2, $y, $x, "snx3");
    			break;
    	}
    					// 結果の出力
    	if ($sw < 0)
    		printf("   収束しませんでした!");
    	else {
    		printf("   結果=");
    		for ($i1 = 0; $i1 < $n; $i1++)
    			printf("%f ", $x[$i1]);
    		printf(" 最小値=%f  回数=%d\n", $y, $sw);
    	}
    
    /******************************************/
    /* シンプレックス法                       */
    /*      max : 最大繰り返し回数            */
    /*      n : 次元                          */
    /*      k : 初期値設定係数                */
    /*      r1 : 縮小比率                     */
    /*      r2 : 拡大比率                     */
    /*      y : 最小値                        */
    /*      x : x(初期値と答え)               */
    /*      snx : 関数値を計算する関数名      */
    /*      return : >=0 : 正常終了(収束回数) */
    /*               =-1 : 収束せず           */
    /******************************************/
    
    function simplex($max, $n, $k, $eps, $r1, $r2, &$y, &$x, $snx)
    {
    					// 初期値の設定
    	$fh    = -1;
    	$fg    = -1;
    	$fl    = -1;
    	$count = 0;
    	$sw    = -1;
    	$yy    = array($n+1);
    	$xg    = array($n);
    	$xr    = array($n);
    	$xn    = array($n);
    	$xx    = array($n+1);
    	for ($i1 = 0; $i1 < $n+1; $i1++)
    		$xx[$i1] = array($n);
    	for ($i1 = 0; $i1 < $n+1; $i1++) {
    		for ($i2 = 0; $i2 < $n; $i2++)
    			$xx[$i1][$i2] = $x[$i2];
    		if ($i1 > 0)
    			$xx[$i1][$i1-1] += $k;
    		$yy[$i1] = $snx($xx[$i1]);
    	}
    					// 最大値,最小値の計算
    	for ($i1 = 0; $i1 < $n+1; $i1++) {
    		if ($fh < 0 || $yy[$i1] > $yy[$fh])
    			$fh = $i1;
    		if ($fl < 0 || $yy[$i1] < $yy[$fl])
    			$fl = $i1;
    	}
    	for ($i1 = 0; $i1 < $n+1; $i1++) {
    		if ($i1 != $fh && ($fg < 0 || $yy[$i1] > $yy[$fg]))
    			$fg = $i1;
    	}
    					// 最小値の計算
    	while ($count < $max && $sw < 0) {
    		$count++;
    							// 重心の計算
    		for ($i1 = 0; $i1 < $n; $i1++)
    			$xg[$i1] = 0.0;
    		for ($i1 = 0; $i1 < $n+1; $i1++) {
    			if ($i1 != $fh) {
    				for ($i2 = 0; $i2 < $n; $i2++)
    					$xg[$i2] += $xx[$i1][$i2];
    			}
    		}
    		for ($i1 = 0; $i1 < $n; $i1++)
    			$xg[$i1] /= $n;
    							// 最大点の置き換え
    		for ($i1 = 0; $i1 < $n; $i1++)
    			$xr[$i1] = 2.0 * $xg[$i1] - $xx[$fh][$i1];
    		$yr = $snx($xr);
    		if ($yr >= $yy[$fh]) {   // 縮小
    			for ($i1 = 0; $i1 < $n; $i1++)
    				$xr[$i1] = (1.0 - $r1) * $xx[$fh][$i1] + $r1 * $xr[$i1];
    			$yr = $snx($xr);
    		}
    		else if ($yr < ($yy[$fl]+($r2-1.0)*$yy[$fh])/$r2) {   // 拡大
    			for ($i1 = 0; $i1 < $n; $i1++)
    				$xn[$i1] = $r2 * $xr[$i1] - ($r2 - 1.0) * $xx[$fh][$i1];
    			$yn = $snx($xn);
    			if ($yn <= $yr) {
    				for ($i1 = 0; $i1 < $n; $i1++)
    					$xr[$i1] = $xn[$i1];
    				$yr = $yn;
    			}
    		}
    		for ($i1 = 0; $i1 < $n; $i1++)
    			$xx[$fh][$i1] = $xr[$i1];
    		$yy[$fh] = $yr;
    							// シンプレックス全体の縮小
    		if ($yy[$fh] >= $yy[$fg]) {
    			for ($i1 = 0; $i1 < $n+1; $i1++) {
    				if ($i1 != $fl) {
    					for ($i2 = 0; $i2 < $n; $i2++)
    						$xx[$i1][$i2] = 0.5 * ($xx[$i1][$i2] + $xx[$fl][$i2]);
    					$yy[$i1] = $snx($xx[$i1]);
    				}
    			}
    		}
    							// 最大値,最小値の計算
    		$fh = -1;
    		$fg = -1;
    		$fl = -1;
    		for ($i1 = 0; $i1 < $n+1; $i1++) {
    			if ($fh < 0 || $yy[$i1] > $yy[$fh])
    				$fh = $i1;
    			if ($fl < 0 || $yy[$i1] < $yy[$fl])
    				$fl = $i1;
    		}
    		for ($i1 = 0; $i1 < $n+1; $i1++) {
    			if ($i1 != $fh && ($fg < 0 || $yy[$i1] > $yy[$fg]))
    				$fg = $i1;
    		}
    							// 収束判定
    		$e = 0.0;
    		for ($i1 = 0; $i1 < $n+1; $i1++) {
    			if ($i1 != $fl) {
    				$yr  = $yy[$i1] - $yy[$fl];
    				$e  += $yr * $yr;
    			}
    		}
    		if ($e < $eps)
    			$sw = 0;
    	}
    
    	if ($sw == 0) {
    		$sw = $count;
    		$y  = $yy[$fl];
    		for ($i1 = 0; $i1 < $n; $i1++)
    			$x[$i1] = $xx[$fl][$i1];
    	}
    
    	return $sw;
    }
    
    /*******************/
    /* 関数値の計算    */
    /*      y = f(x)   */
    /*      return : y */
    /*******************/
    					// 関数1
    function snx1($x)
    {
    	$x1 = $x[0] - 1.0;
    	$y1 = $x[1] - 2.0;
    	$y  = $x1 * $x1 + $y1 * $y1;
    
    	return $y;
    }
    					// 関数2
    function snx2($x)
    {
    	$x1 = $x[1] - $x[0] * $x[0];
    	$y1 = 1.0 - $x[0];
    	$y  = 100.0 * $x1 * $x1 + $y1 * $y1;
    
    	return $y;
    }
    					// 関数3
    function snx3($x)
    {
    	$x1 = 1.5 - $x[0] * (1.0 - $x[1]);
    	$y1 = 2.25 - $x[0] * (1.0 - $x[1] * $x[1]);
    	$z1 = 2.625 - $x[0] * (1.0 - $x[1] * $x[1] * $x[1]);
    	$y  = $x1 * $x1 + $y1 * $y1 + $z1 * $z1;
    
    	return $y;
    }
    
    ?>
    			

  5. Ruby

    #*************************************/
    # シンプレックス法による最小値の計算 */
    #      coded by Y.Suganuma           */
    #*************************************/
    
    #******************/
    # 関数値の計算    */
    #      y = f(x)   */
    #      return : y */
    #******************/
    			# 関数1
    snx1 = Proc.new { |x|
    	x1 = x[0] - 1.0
    	y1 = x[1] - 2.0
    	x1 * x1 + y1 * y1
    }
    			# 関数2
    snx2 = Proc.new { |x|
    	x1 = x[1] - x[0] * x[0]
    	y1 = 1.0 - x[0]
    	100.0 * x1 * x1 + y1 * y1
    }
    			# 関数3
    snx3 = Proc.new { |x|
    	x1 = 1.5 - x[0] * (1.0 - x[1])
    	y1 = 2.25 - x[0] * (1.0 - x[1] * x[1])
    	z1 = 2.625 - x[0] * (1.0 - x[1] * x[1] * x[1])
    	x1 * x1 + y1 * y1 + z1 * z1
    }
    
    #*****************************************/
    # シンプレックス法                       */
    #      max : 最大繰り返し回数            */
    #      n : 次元                          */
    #      k : 初期値設定係数                */
    #      r1 : 縮小比率                     */
    #      r2 : 拡大比率                     */
    #      y : 最小値                        */
    #      x : x(初期値と答え)               */
    #      snx : 関数値を計算する関数名      */
    #      return : >=0 : 正常終了(収束回数) */
    #               =-1 : 収束せず           */
    #*****************************************/
    def simplex(max, n, k, eps, r1, r2, y, x, &snx)
    					# 初期値の設定
    	fh    = -1
    	fg    = -1
    	fl    = -1
    	count = 0
    	sw    = -1
    	yy    = Array.new(n+1)
    	xg    = Array.new(n)
    	xr    = Array.new(n)
    	xn    = Array.new(n)
    	xx    = Array.new(n+1)
    	for i1 in 0 ... n+1
    		xx[i1] = Array.new(n)
    	end
    	for i1 in 0 ... n+1
    		for i2 in 0 ... n
    			xx[i1][i2] = x[i2]
    		end
    		if i1 > 0
    			xx[i1][i1-1] += k
    		end
    		yy[i1] = snx.call(xx[i1])
    	end
    					# 最大値,最小値の計算
    	for i1 in 0 ... n+1
    		if fh < 0 || yy[i1] > yy[fh]
    			fh = i1
    		end
    		if fl < 0 || yy[i1] < yy[fl]
    			fl = i1
    		end
    	end
    	for i1 in 0 ... n+1
    		if i1 != fh && (fg < 0 || yy[i1] > yy[fg])
    			fg = i1
    		end
    	end
    					# 最小値の計算
    	while count < max && sw < 0
    		count += 1
    							# 重心の計算
    		for i1 in 0 ... n
    			xg[i1] = 0.0
    		end
    		for i1 in 0 ... n+1
    			if i1 != fh
    				for i2 in 0 ... n
    					xg[i2] += xx[i1][i2]
    				end
    			end
    		end
    		for i1 in 0 ... n
    			xg[i1] /= n
    		end
    							# 最大点の置き換え
    		for i1 in 0 ... n
    			xr[i1] = 2.0 * xg[i1] - xx[fh][i1]
    		end
    		yr = snx.call(xr)
    		if yr >= yy[fh]   # 縮小
    			for i1 in 0 ... n
    				xr[i1] = (1.0 - r1) * xx[fh][i1] + r1 * xr[i1]
    			end
    			yr = snx.call(xr)
    		elsif yr < (yy[fl]+(r2-1.0)*yy[fh])/r2   # 拡大
    			for i1 in 0 ... n
    				xn[i1] = r2 * xr[i1] - (r2 - 1.0) * xx[fh][i1]
    			end
    			yn = snx.call(xn)
    			if yn <= yr
    				for i1 in 0 ... n
    					xr[i1] = xn[i1]
    				end
    				yr = yn
    			end
    		end
    		for i1 in 0 ... n
    			xx[fh][i1] = xr[i1]
    		end
    		yy[fh] = yr
    							# シンプレックス全体の縮小
    		if yy[fh] >= yy[fg]
    			for i1 in 0 ... n+1
    				if i1 != fl
    					for i2 in 0 ... n
    						xx[i1][i2] = 0.5 * (xx[i1][i2] + xx[fl][i2])
    					end
    					yy[i1] = snx.call(xx[i1])
    				end
    			end
    		end
    							# 最大値,最小値の計算
    		fh = -1
    		fg = -1
    		fl = -1
    		for i1 in 0 ... n+1
    			if fh < 0 || yy[i1] > yy[fh]
    				fh = i1
    			end
    			if fl < 0 || yy[i1] < yy[fl]
    				fl = i1
    			end
    		end
    		for i1 in 0 ... n+1
    			if i1 != fh && (fg < 0 || yy[i1] > yy[fg])
    				fg = i1
    			end
    		end
    							# 収束判定
    		e = 0.0
    		for i1 in 0 ... n+1
    			if i1 != fl
    				yr  = yy[i1] - yy[fl]
    				e  += yr * yr
    			end
    		end
    		if e < eps
    			sw = 0
    		end
    	end
    
    	if sw == 0
    		sw   = count
    		y[0] = yy[fl]
    		for i1 in 0 ... n
    			x[i1] = xx[fl][i1]
    		end
    	end
    
    	return sw
    end
    				# データの入力
    sw  = 0
    str = gets()
    a   = str.split(" ")
    fun = Integer(a[1])
    n   = Integer(a[3])
    max = Integer(a[5])
    k   = Float(a[7])
    str = gets();
    a   = str.split(" ");
    eps = Float(a[1])
    r1  = Float(a[3])
    r2  = Float(a[5])
    x   = Array.new(n)
    y   = Array.new(1)
    sw  = 0
    str = gets();
    a   = str.split(" ");
    for i1 in 0 ... n
    	x[i1]  = Float(a[i1+1])
    end
    				# 実行
    case fun
    	when 1
    		sw = simplex(max, n, k, eps, r1, r2, y, x, &snx1)
    	when 2
    		sw = simplex(max, n, k, eps, r1, r2, y, x, &snx2)
    	when 3
    		sw = simplex(max, n, k, eps, r1, r2, y, x, &snx3)
    end
    				# 結果の出力
    if sw < 0
    	printf("   収束しませんでした!")
    else
    	printf("   結果=")
    	for i1 in 0 ... n
    		printf("%f ", x[i1])
    	end
    	printf(" 最小値=%f  回数=%d\n", y[0], sw)
    end
    			

  6. Python

    # -*- coding: UTF-8 -*-
    import numpy as np
    import sys
    from math import *
    
    ############################################
    # シンプレックス法
    #      max : 最大繰り返し回数
    #      n : 次元
    #      k : 初期値設定係数
    #      r1 : 縮小比率
    #      r2 : 拡大比率
    #      y : 最小値
    #      x : x(初期値と答え)
    #      snx : 関数値を計算する関数名
    #      return : >=0 : 正常終了(収束回数)
    #               =-1 : 収束せず
    #      coded by Y.Suganuma
    ############################################
    
    def simplex(max, n, k, eps, r1, r2, y, x, snx) :
    
    			# 初期値の設定
    	fh    = -1
    	fg    = -1
    	fl    = -1
    	count = 0
    	sw    = -1
    	yy    = np.empty(n+1, np.float)
    	xg    = np.empty(n, np.float)
    	xr    = np.empty(n, np.float)
    	xn    = np.empty(n, np.float)
    	xx    = np.empty((n+1, n), np.float)
    	for i1 in range(0, n+1) :
    		for i2 in range(0, n) :
    			xx[i1][i2] = x[i2]
    		if i1 > 0 :
    			xx[i1][i1-1] += k
    		yy[i1] = snx(xx[i1])
    			# 最大値,最小値の計算
    	for i1 in range(0, n+1) :
    		if fh < 0 or yy[i1] > yy[fh] :
    			fh = i1
    		if fl < 0 or yy[i1] < yy[fl] :
    			fl = i1
    	for i1 in range(0, n+1) :
    		if i1 != fh and (fg < 0 or yy[i1] > yy[fg]) :
    			fg = i1
    			# 最小値の計算
    	while count < max and sw < 0 :
    		count += 1
    				# 重心の計算
    		for i1 in range(0, n) :
    			xg[i1] = 0.0
    		for i1 in range(0, n+1) :
    			if i1 != fh :
    				for i2 in range(0, n) :
    					xg[i2] += xx[i1][i2]
    		for i1 in range(0, n) :
    			xg[i1] /= n
    				# 最大点の置き換え
    		for i1 in range(0, n) :
    			xr[i1] = 2.0 * xg[i1] - xx[fh][i1]
    		yr = snx(xr)
    		if yr >= yy[fh] :   # 縮小
    			for i1 in range(0, n) :
    				xr[i1] = (1.0 - r1) * xx[fh][i1] + r1 * xr[i1]
    			yr = snx(xr)
    		elif yr < (yy[fl]+(r2-1.0)*yy[fh])/r2 :   # 拡大
    			for i1 in range(0, n) :
    				xn[i1] = r2 * xr[i1] - (r2 - 1.0) * xx[fh][i1]
    			yn = snx(xn)
    			if yn <= yr :
    				for i1 in range(0, n) :
    					xr[i1] = xn[i1]
    				yr = yn
    		for i1 in range(0, n) :
    			xx[fh][i1] = xr[i1]
    		yy[fh] = yr
    				# シンプレックス全体の縮小
    		if yy[fh] >= yy[fg] :
    			for i1 in range(0, n+1) :
    				if i1 != fl :
    					for i2 in range(0, n) :
    						xx[i1][i2] = 0.5 * (xx[i1][i2] + xx[fl][i2])
    					yy[i1] = snx(xx[i1])
    				# 最大値,最小値の計算
    		fh = -1
    		fg = -1
    		fl = -1
    		for i1 in range(0, n+1) :
    			if fh < 0 or yy[i1] > yy[fh] :
    				fh = i1
    			if fl < 0 or yy[i1] < yy[fl] :
    				fl = i1
    		for i1 in range(0, n+1) :
    			if i1 != fh and (fg < 0 or yy[i1] > yy[fg]) :
    				fg = i1
    				# 収束判定
    		e = 0.0
    		for i1 in range(0, n+1) :
    			if i1 != fl :
    				yr  = yy[i1] - yy[fl]
    				e  += yr * yr
    		if e < eps :
    			sw = 0
    
    	if sw == 0 :
    		sw   = count
    		y[0] = yy[fl]
    		for i1 in range(0, n) :
    			x[i1] = xx[fl][i1]
    
    	return sw
    
    ############################################
    # シンプレックス法による最小値の計算
    #      coded by Y.Suganuma
    ############################################
    
    ###############
    # 関数値の計算
    ###############
    
    			# 関数1
    def snx1(x) :
    	x1 = x[0] - 1.0
    	y1 = x[1] - 2.0
    	y  = x1 * x1 + y1 * y1
    	return y
    
    			# 関数2
    def snx2(x) :
    	x1 = x[1] - x[0] * x[0]
    	y1 = 1.0 - x[0]
    	y  = 100.0 * x1 * x1 + y1 * y1
    	return y
    
    			# 関数3
    def snx3(x) :
    	x1 = 1.5 - x[0] * (1.0 - x[1])
    	y1 = 2.25 - x[0] * (1.0 - x[1] * x[1])
    	z1 = 2.625 - x[0] * (1.0 - x[1] * x[1] * x[1])
    	y  = x1 * x1 + y1 * y1 + z1 * z1
    	return y
    
    			# データの入力
    sw   = 0
    line = sys.stdin.readline()
    s    = line.split()
    fun  = int(s[1])
    n    = int(s[3])
    max  = int(s[5])
    k    = float(s[7])
    
    line = sys.stdin.readline()
    s    = line.split()
    eps  = float(s[1])
    r1   = float(s[3])
    r2   = float(s[5])
    
    x    = np.empty(n, np.float)
    y    = np.empty(1, np.float)
    
    line = sys.stdin.readline()
    s    = line.split()
    for i1 in range(0, n) :
    	x[i1] = float(s[i1+1])
    			# 実行
    if fun == 1 :
    	sw = simplex(max, n, k, eps, r1, r2, y, x, snx1)
    elif fun == 2 :
    	sw = simplex(max, n, k, eps, r1, r2, y, x, snx2)
    else :
    	sw = simplex(max, n, k, eps, r1, r2, y, x, snx3)
    			# 結果の出力
    if sw < 0 :
    	print("   収束しませんでした!")
    else :
    	print("   結果=", end="")
    	for i1 in range(0, n) :
    		print(str(x[i1]) + " ", end="")
    	print(" 最小値=" + str(y[0]) + "  回数=" + str(sw))
    			

  7. C#

    /**************************************/
    /* シンプレックス法による最小値の計算 */
    /*      coded by Y.Suganuma           */
    /**************************************/
    using System;
    
    class Program
    {
    	static void Main()
    	{
    		Test1 ts = new Test1();
    	}
    }
    
    class Test1
    {
    	public Test1()
    	{
    					// データの入力
    							// 1 行目
    		string[] str = Console.ReadLine().Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
    		int fun      = int.Parse(str[1]);
    		int n        = int.Parse(str[3]);
    		int max      = int.Parse(str[5]);
    		double k     = double.Parse(str[7]);
    							// 2 行目
    		str        = Console.ReadLine().Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
    		double eps = double.Parse(str[1]);
    		double r1  = double.Parse(str[3]);
    		double r2  = double.Parse(str[5]);
    							// 3 行目
    		double[] x = new double [n];
    		double y   = 0.0;
    		str        = Console.ReadLine().Split(new char[] {' '}, StringSplitOptions.RemoveEmptyEntries);
    		for (int i1 = 0; i1 < n; i1++)
    			x[i1] = double.Parse(str[i1+1]);
    					// 実行
    		int sw;
    		if (fun == 1)
    			sw = simplex(max, n, k, eps, r1, r2, ref y, x, snx1);
    		else if (fun == 2)
    			sw = simplex(max, n, k, eps, r1, r2, ref y, x, snx2);
    		else
    			sw = simplex(max, n, k, eps, r1, r2, ref y, x, snx3);
    					// 結果の出力
    		if (sw < 0)
    			Console.WriteLine("   収束しませんでした!");
    		else {
    			Console.Write("   結果=");
    			for (int i1 = 0; i1 < n; i1++)
    				Console.Write(x[i1] + " ");
    			Console.WriteLine(" 最小値=" + y + "  回数=" + sw);
    		}
    	}
    			// 関数1の値の計算
    	double snx1(double[] x)
    	{
    		double x1  = x[0] - 1.0;
    		double y1  = x[1] - 2.0;
    		double y   = x1 * x1 + y1 * y1;
    		return y;
    	}
    			// 関数2の値の計算
    	double snx2(double[] x)
    	{
    		double x1  = x[1] - x[0] * x[0];
    		double y1  = 1.0 - x[0];
    		double y   = 100.0 * x1 * x1 + y1 * y1;
    		return y;
    	}
    			// 関数3の値の計算
    	double snx3(double[] x)
    	{
    		double x1  = 1.5 - x[0] * (1.0 - x[1]);
    		double y1  = 2.25 - x[0] * (1.0 - x[1] * x[1]);
    		double z1  = 2.625 - x[0] * (1.0 - x[1] * x[1] * x[1]);
    		double y   = x1 * x1 + y1 * y1 + z1 * z1;
    		return y;
    	}
    
    	/******************************************/
    	/* シンプレックス法                       */
    	/*      max : 最大繰り返し回数            */
    	/*      n : 次元                          */
    	/*      k : 初期値設定係数                */
    	/*      r1 : 縮小比率                     */
    	/*      r2 : 拡大比率                     */
    	/*      y : 最小値                        */
    	/*      x : x(初期値と答え)               */
    	/*      fn : 関数値を計算する関数         */
    	/*      return : >=0 : 正常終了(収束回数) */
    	/*               =-1 : 収束せず           */
    	/******************************************/
    	int simplex(int max, int n, double k, double eps, double r1, double r2,
    	            ref double y, double[] x, Func<double[], double> fn)
    	{
    						// 初期値の設定
    		double[] yy = new double [n+1];
    		double[] xg = new double [n];
    		double[] xr = new double [n];
    		double[] xn = new double [n];
    		double[][] xx = new double [n+1][];
    		for (int i1 = 0; i1 < n+1; i1++) {
    			xx[i1] = new double [n];
    			for (int i2 = 0; i2 < n; i2++)
    				xx[i1][i2] = x[i2];
    			if (i1 > 0)
    				xx[i1][i1-1] += k;
    			yy[i1] = fn(xx[i1]);
    		}
    						// 最大値,最小値の計算
    		int fh = -1, fg = -1, fl = -1;
    		for (int i1 = 0; i1 < n+1; i1++) {
    			if (fh < 0 || yy[i1] > yy[fh])
    				fh = i1;
    			if (fl < 0 || yy[i1] < yy[fl])
    				fl = i1;
    		}
    		for (int i1 = 0; i1 < n+1; i1++) {
    			if (i1 != fh && (fg < 0 || yy[i1] > yy[fg]))
    				fg = i1;
    		}
    						// 最小値の計算
    		int count = 0, sw = -1;
    		while (count < max && sw < 0) {
    			count++;
    								// 重心の計算
    			for (int i1 = 0; i1 < n; i1++)
    				xg[i1] = 0.0;
    			for (int i1 = 0; i1 < n+1; i1++) {
    				if (i1 != fh) {
    					for (int i2 = 0; i2 < n; i2++)
    						xg[i2] += xx[i1][i2];
    				}
    			}
    			for (int i1 = 0; i1 < n; i1++)
    				xg[i1] /= n;
    								// 最大点の置き換え
    			for (int i1 = 0; i1 < n; i1++)
    				xr[i1] = 2.0 * xg[i1] - xx[fh][i1];
    			double yr = fn(xr);
    			if (yr >= yy[fh]) {   // 縮小
    				for (int i1 = 0; i1 < n; i1++)
    					xr[i1] = (1.0 - r1) * xx[fh][i1] + r1 * xr[i1];
    				yr = fn(xr);
    			}
    			else if (yr < (yy[fl]+(r2-1.0)*yy[fh])/r2) {   // 拡大
    				for (int i1 = 0; i1 < n; i1++)
    					xn[i1] = r2 * xr[i1] - (r2 - 1.0) * xx[fh][i1];
    				double yn = fn(xn);
    				if (yn <= yr) {
    					for (int i1 = 0; i1 < n; i1++)
    						xr[i1] = xn[i1];
    					yr = yn;
    				}
    			}
    			for (int i1 = 0; i1 < n; i1++)
    				xx[fh][i1] = xr[i1];
    			yy[fh] = yr;
    								// シンプレックス全体の縮小
    			if (yy[fh] >= yy[fg]) {
    				for (int i1 = 0; i1 < n+1; i1++) {
    					if (i1 != fl) {
    						for (int i2 = 0; i2 < n; i2++)
    							xx[i1][i2] = 0.5 * (xx[i1][i2] + xx[fl][i2]);
    						yy[i1] = fn(xx[i1]);
    					}
    				}
    			}
    								// 最大値,最小値の計算
    			fh = -1;
    			fg = -1;
    			fl = -1;
    			for (int i1 = 0; i1 < n+1; i1++) {
    				if (fh < 0 || yy[i1] > yy[fh])
    					fh = i1;
    				if (fl < 0 || yy[i1] < yy[fl])
    					fl = i1;
    			}
    			for (int i1 = 0; i1 < n+1; i1++) {
    				if (i1 != fh && (fg < 0 || yy[i1] > yy[fg]))
    					fg = i1;
    			}
    								// 収束判定
    			double e = 0.0;
    			for (int i1 = 0; i1 < n+1; i1++) {
    				if (i1 != fl) {
    					yr  = yy[i1] - yy[fl];
    					e  += yr * yr;
    				}
    			}
    			if (e < eps)
    				sw = 0;
    		}
    	
    		if (sw == 0) {
    			sw = count;
    			y  = yy[fl];
    			for (int i1 = 0; i1 < n; i1++)
    				x[i1] = xx[fl][i1];
    		}
    	
    		return sw;
    	}
    }
    			

  8. VB

    ''''''''''''''''''''''''''''''''''''''
    ' シンプレックス法による最小値の計算 '
    '      coded by Y.Suganuma           '
    ''''''''''''''''''''''''''''''''''''''
    Imports System.Text.RegularExpressions
    
    Module Test
    
    	Sub Main()
    					' データの入力
    							' 1 行目
    		Dim MS As Regex     = New Regex("\s+") 
    		Dim str() As String = MS.Split(Console.ReadLine().Trim())
    		Dim fun As Integer  = Integer.Parse(str(1))
    		Dim n As Integer    = Integer.Parse(str(3))
    		Dim max As Integer  = Integer.Parse(str(5))
    		Dim k As Integer    = Double.Parse(str(7))
    							' 2 行目
    		str = MS.Split(Console.ReadLine().Trim())
    		Dim eps As Double = Double.Parse(str(1))
    		Dim r1 As Double  = Double.Parse(str(3))
    		Dim r2 As Double  = Double.Parse(str(5))
    							' 3 行目
    		Dim x(n) As Double
    		Dim y As Double = 0.0
    		str             = MS.Split(Console.ReadLine().Trim())
    		For i1 As Integer = 0 To n-1
    			x(i1) = Double.Parse(str(i1+1))
    		Next
    					' 関数1の値の計算(ラムダ式)
    		Dim snx1 = Function(x0) As Double
    			Dim x1 As Double = x0(0) - 1.0
    			Dim y1 As Double = x0(1) - 2.0
    			Dim y0 As Double = x1 * x1 + y1 * y1
    			Return y0
    		End Function
    					' 関数2の値の計算(ラムダ式)
    		Dim snx2 = Function(x0) As Double
    			Dim x1 As Double = x0(1) - x0(0) * x0(0)
    			Dim y1 As Double = 1.0 - x0(0)
    			Dim y0 As Double = 100.0 * x1 * x1 + y1 * y1
    			Return y0
    		End Function
    					' 関数3の値の計算(ラムダ式)
    		Dim snx3 = Function(x0) As Double
    			Dim x1 As Double = 1.5 - x0(0) * (1.0 - x0(1))
    			Dim y1 As Double = 2.25 - x0(0) * (1.0 - x0(1) * x0(1))
    			Dim z1 As Double = 2.625 - x0(0) * (1.0 - x0(1) * x0(1) * x0(1))
    			Dim y0 As Double = x1 * x1 + y1 * y1 + z1 * z1
    			Return y0
    		End Function
    					' 実行
    		Dim sw As Integer
    		If fun = 1
    			sw = simplex(max, n, k, eps, r1, r2, y, x, snx1)
    		ElseIf fun = 2
    			sw = simplex(max, n, k, eps, r1, r2, y, x, snx2)
    		Else
    			sw = simplex(max, n, k, eps, r1, r2, y, x, snx3)
    		End If
    					' 結果の出力
    		If sw < 0
    			Console.Write("   収束しませんでした!")
    		Else
    			Console.Write("   結果=")
    			For i1 As Integer = 0 To n-1
    				Console.Write(x(i1) & " ")
    			Next
    			Console.WriteLine(" 最小値=" & y & "  回数=" & sw)
    		End If
    
    	End Sub
    
    	''''''''''''''''''''''''''''''''''''''''''
    	' シンプレックス法                       '
    	'      max : 最大繰り返し回数            '
    	'      n : 次元                          '
    	'      k : 初期値設定係数                '
    	'      r1 : 縮小比率                     '
    	'      r2 : 拡大比率                     '
    	'      y : 最小値                        '
    	'      x : x(初期値と答え)               '
    	'      fn : 関数値を計算する関数         '
    	'      return : >=0 : 正常終了(収束回数) '
    	'               =-1 : 収束せず           '
    	''''''''''''''''''''''''''''''''''''''''''
    	Function simplex(max As Integer, n As Integer, k As Double, eps As Double,
    	                 r1 As Double, r2 As Double, ByRef y As Double, x() As Double,
    	                 fn As Func(Of Double(), Double))
    
    						' 初期値の設定
    		Dim yy(n+1) As Double
    		Dim xg(n) As Double
    		Dim xr(n) As Double
    		Dim xn(n) As Double
    		Dim xx(n+1,n) As Double
    		For i1 As Integer = 0 To n
    			For i2 As Integer = 0 To n-1
    				xx(i1,i2) = x(i2)
    			Next
    			If i1 > 0
    				xx(i1,i1-1) += k
    			End If
    			Dim xx1(n) As Double
    			For i2 As Integer = 0 To n-1
    				xx1(i2) = xx(i1,i2)
    			Next
    			yy(i1) = fn(xx1)
    		Next
    						' 最大値,最小値の計算
    		Dim fh As Integer = -1
    		Dim fg As Integer = -1
    		Dim fl As Integer = -1
    		For i1 As Integer = 0 To n
    			If fh < 0
    				fh = i1
    			ElseIf yy(i1) > yy(fh)
    				fh = i1
    			End If
    			If fl < 0
    				fl = i1
    			ElseIf yy(i1) < yy(fl)
    				fl = i1
    			End If
    		Next
    		For i1 As Integer = 0 To n
    			If i1 <> fh
    				If fg < 0
    					fg = i1
    				ElseIf yy(i1) > yy(fg)
    					fg = i1
    				End If
    			End If
    		Next
    						' 最小値の計算
    		Dim count As Integer = 0
    		Dim sw As Integer    = -1
    		Do While count < max and sw < 0
    			count += 1
    								' 重心の計算
    			For i1 As Integer = 0 To n-1
    				xg(i1) = 0.0
    			Next
    			For i1 As Integer = 0 To n
    				If i1 <> fh
    					For i2 As Integer = 0 To n-1
    						xg(i2) += xx(i1,i2)
    					Next
    				End If
    			Next
    			For i1 As Integer = 0 To n-1
    				xg(i1) /= n
    			Next
    								' 最大点の置き換え
    			For i1 As Integer = 0 To n-1
    				xr(i1) = 2.0 * xg(i1) - xx(fh,i1)
    			Next
    			Dim yr As Double = fn(xr)
    			If yr >= yy(fh)   ' 縮小
    				For i1 As Integer = 0 To n-1
    					xr(i1) = (1.0 - r1) * xx(fh,i1) + r1 * xr(i1)
    				Next
    				yr = fn(xr)
    			ElseIf yr < (yy(fl)+(r2-1.0)*yy(fh))/r2   ' 拡大
    				For i1 As Integer = 0 To n-1
    					xn(i1) = r2 * xr(i1) - (r2 - 1.0) * xx(fh,i1)
    				Next
    				Dim yn As Double = fn(xn)
    				If yn <= yr
    					For i1 As Integer = 0 To n-1
    						xr(i1) = xn(i1)
    					Next
    					yr = yn
    				End If
    			End If
    			For i1 As Integer = 0 To n-1
    				xx(fh,i1) = xr(i1)
    			Next
    			yy(fh) = yr
    								' シンプレックス全体の縮小
    			If yy(fh) >= yy(fg)
    				For i1 As Integer = 0 To n
    					If i1 <> fl
    						For i2 As Integer = 0 To n-1
    							xx(i1,i2) = 0.5 * (xx(i1,i2) + xx(fl,i2))
    						Next
    						Dim xx1(n) As Double
    						For i2 As Integer = 0 To n-1
    							xx1(i2) = xx(i1,i2)
    						Next
    						yy(i1) = fn(xx1)
    					End If
    				Next
    			End If
    								' 最大値,最小値の計算
    			fh = -1
    			fg = -1
    			fl = -1
    			For i1 As Integer = 0 To n
    				If fh < 0
    					fh = i1
    				ElseIf yy(i1) > yy(fh)
    					fh = i1
    				End If
    				If fl < 0
    					fl = i1
    				ElseIf yy(i1) < yy(fl)
    					fl = i1
    				End If
    			Next
    			For i1 As Integer = 0 To n
    				If i1 <> fh
    					If fg < 0
    						fg = i1
    					ElseIf yy(i1) > yy(fg)
    						fg = i1
    					End If
    				End If
    			Next
    								' 収束判定
    			Dim e As Double = 0.0
    			For i1 As Integer = 0 To n
    				If i1 <> fl
    					yr  = yy(i1) - yy(fl)
    					e  += yr * yr
    				End If
    			Next
    			If e < eps
    				sw = 0
    			End If
    		Loop
    	
    		If sw = 0
    			sw = count
    			y  = yy(fl)
    			For i1 As Integer = 0 To n-1
    				x(i1) = xx(fl,i1)
    			Next
    		End If
    	
    		Return sw
    
    	End Function
    
    End Module
    			

情報学部 菅沼ホーム 目次 索引