| 情報学部 | 菅沼ホーム | 目次 | 索引 | 
/**************************************/
/* シンプレックス法による最小値の計算 */
/*      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;
}
			
/**************************************/
/* シンプレックス法による最小値の計算 */
/*      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;
	}
}
			
<!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>
			
<?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;
}
?>
			
#*************************************/
# シンプレックス法による最小値の計算 */
#      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
			
# -*- 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))
			
/**************************************/
/* シンプレックス法による最小値の計算 */
/*      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;
	}
}
			
''''''''''''''''''''''''''''''''''''''
' シンプレックス法による最小値の計算 '
'      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
			
| 情報学部 | 菅沼ホーム | 目次 | 索引 |