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