| 情報学部 | 菅沼ホーム | 目次 | 索引 | 
/*********************************************/
/* 黄金分割法によるy=x^4+3x^3+2x^2+1の最小値 */
/*      coded by Y.Suganuma                  */
/*********************************************/
#include <stdio.h>
double snx(double);
double gold(double, double, double, double *, int *, int, double (*)(double));
int main()
{
	double a, b, eps, val, x;
	int ind, max;
	a   = -2.0;
	b   = -1.0;
	eps = 1.0e-10;
	max = 100;
	x = gold(a, b, eps, &val, &ind, max, snx);
	printf("x %f val %f ind %d\n", x, val, ind);
	return 0;
}
/****************/
/* 関数値の計算 */
/****************/
double snx(double x)
{
	double f;
	f  = x * x * x * x + 3.0 * x * x * x + 2.0 * x * x + 1.0;
	return f;
}
/******************************************/
/* 黄金分割法(関数の最小値)               */
/*      a,b : 初期区間 a < b              */
/*      eps : 許容誤差                    */
/*      val : 間数値                      */
/*      ind : 計算状況                    */
/*              >= 0 : 正常終了(収束回数) */
/*              = -1 : 収束せず           */
/*      max : 最大試行回数                */
/*      fun : 関数値を計算する関数の名前  */
/*      return : 結果                     */
/******************************************/
#include <math.h>
double gold(double a, double b, double eps, double *val, int *ind, int max, double (*fun)(double))
{
	double f1, f2, fa, fb, tau, x = 0.0, x1, x2;
	int count;
	tau   = (sqrt(5.0) - 1.0) / 2.0;
	count = 0;
	*ind  = -1;
	x1    = b - tau * (b - a);
	x2    = a + tau * (b - a);
	f1    = fun(x1);
	f2    = fun(x2);
	while (count < max && *ind < 0) {
		count += 1;
		if (f2 > f1) {
			if (fabs(b-a) < eps && fabs(b-a) < eps*fabs(b)) {
				*ind = 0;
				x    = x1;
				*val = f1;
			}
			else {
				b  = x2;
				x2 = x1;
				x1 = a + (1.0 - tau) * (b - a);
				f2 = f1;
				f1 = fun(x1);
			}
		}
		else {
			if (fabs(b-a) < eps && fabs(b-a) < eps*fabs(b)) {
				*ind = 0;
				x    = x2;
				*val = f2;
				f1   = f2;
			}
			else {
				a  = x1;
				x1 = x2;
				x2 = b - (1.0 - tau) * (b - a);
				f1 = f2;
				f2 = fun(x2);
			}
		}
	}
	if (*ind == 0) {
		*ind = count;
		fa   = fun(a);
		fb   = fun(b);
		if (fb < fa) {
			a  = b;
			fa = fb;
		}
		if (fa < f1) {
			x    = a;
			*val = fa;
		}
	}
	return x;
}
			
/*********************************************/
/* 黄金分割法によるy=x^4+3x^3+2x^2+1の最小値 */
/*        coded by Y.Suganuma                */
/*********************************************/
import java.io.*;
public class Test {
	public static void main(String args[]) throws IOException
	{
		double a, b, eps, x, val[] = new double [1];
		int max, ind[] = new int [1];
		a   = -2.0;
		b   = -1.0;
		eps = 1.0e-10;
		max = 100;
		Kansu kn = new Kansu();
		x = kn.gold(a, b, eps, val, ind, max);
		System.out.println("x " + x + " val " + val[0] + " ind " + ind[0]);
	}
}
/****************/
/* 関数値の計算 */
/****************/
class Kansu extends Gold
{
	double snx(double x)
	{
		double y = x * x * x * x + 3.0 * x * x * x + 2.0 * x * x + 1.0;
		return y;
	}
}
abstract class Gold 
{
	/************************************************/
	/* 黄金分割法(関数の最小値)                     */
	/*      a,b : 初期区間 a < b                    */
	/*      eps : 許容誤差                          */
	/*      val : 間数値                            */
	/*      ind : 計算状況                          */
	/*              >= 0 : 正常終了(収束回数)       */
	/*              = -1 : 収束せず                 */
	/*      max : 最大試行回数                      */
	/*      return : 結果                           */
	/************************************************/
	abstract double snx(double x);
	double gold(double a, double b, double eps, double val[], int ind[], int max)
	{
		double f1, f2, fa, fb, tau, x = 0.0, x1, x2;
		int count;
		tau    = (Math.sqrt(5.0) - 1.0) / 2.0;
		count  = 0;
		ind[0] = -1;
		x1     = b - tau * (b - a);
		x2     = a + tau * (b - a);
		f1     = snx(x1);
		f2     = snx(x2);
		while (count < max && ind[0] < 0) {
			count += 1;
			if (f2 > f1) {
				if (Math.abs(b-a) < eps && Math.abs(b-a) < eps*Math.abs(b)) {
					ind[0] = 0;
					x      = x1;
					val[0] = f1;
				}
				else {
					b  = x2;
					x2 = x1;
					x1 = a + (1.0 - tau) * (b - a);
					f2 = f1;
					f1 = snx(x1);
				}
			}
			else {
				if (Math.abs(b-a) < eps && Math.abs(b-a) < eps*Math.abs(b)) {
					ind[0] = 0;
					x      = x2;
					val[0] = f2;
					f1     = f2;
				}
				else {
					a  = x1;
					x1 = x2;
					x2 = b - (1.0 - tau) * (b - a);
					f1 = f2;
					f2 = snx(x2);
				}
			}
		}
		if (ind[0] == 0) {
			ind[0] = count;
			fa     = snx(a);
			fb     = snx(b);
			if (fb < fa) {
				a  = b;
				fa = fb;
			}
			if (fa < f1) {
				x      = a;
				val[0] = fa;
			}
		}
		return x;
	}
}
			
<!DOCTYPE HTML>
<HTML>
<HEAD>
	<TITLE>最適化(黄金分割法)</TITLE>
	<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
	<SCRIPT TYPE="text/javascript">
		str = "";
		function main()
		{
			str = document.getElementById("func").value + ";";
					// データの設定
			let a   = parseFloat(document.getElementById("a").value);
			let b   = parseFloat(document.getElementById("b").value);
			let max = parseInt(document.getElementById("max").value);
			let eps = 1.0e-10;
			let val = new Array();
			let ind = new Array();
					// 実行
			let x = gold(a, b, eps, val, ind, max, snx);
					// 結果
			if (ind < 0)
				document.getElementById("res").value = "解を求めることができませんでした!";
			else {
				let c = 100000;
				let s1 = Math.round(x * c) / c;
				let s2 = Math.round(val[0] * c) / c;
				document.getElementById("res").value = " x = " + s1 + ",f(x) = " + s2 + ",ind = " + ind[0];
			}
		}
		/****************/
		/* 関数値の計算 */
		/****************/
		function snx(x)
		{
			let y = eval(str);
			return y;
		}
		/*******************************************/
		/* 黄金分割法(関数の最小値)                */
		/*      a,b : 初期区間 a < b               */
		/*      eps : 許容誤差                     */
		/*      val : 間数値                       */
		/*      ind : 計算状況                     */
		/*              >= 0 : 正常終了(収束回数)  */
		/*              = -1 : 収束せず            */
		/*      max : 最大試行回数                 */
		/*      return : 結果                      */
		/*******************************************/
		function gold(a, b, eps, val, ind, max)
		{
			let tau   = (Math.sqrt(5.0) - 1.0) / 2.0;
			let count = 0;
			ind[0]    = -1;
			let x     = 0.0;
			let x1    = b - tau * (b - a);
			let x2    = a + tau * (b - a);
			let f1    = snx(x1);
			let f2    = snx(x2);
			while (count < max && ind[0] < 0) {
				count += 1;
				if (f2 > f1) {
					if (Math.abs(b-a) < eps && Math.abs(b-a) < eps*Math.abs(b)) {
						ind[0] = 0;
						x      = x1;
						val[0] = f1;
					}
					else {
						b  = x2;
						x2 = x1;
						x1 = a + (1.0 - tau) * (b - a);
						f2 = f1;
						f1 = snx(x1);
					}
				}
				else {
					if (Math.abs(b-a) < eps && Math.abs(b-a) < eps*Math.abs(b)) {
						ind[0] = 0;
						x      = x2;
						val[0] = f2;
						f1     = f2;
					}
					else {
						a  = x1;
						x1 = x2;
						x2 = b - (1.0 - tau) * (b - a);
						f1 = f2;
						f2 = snx(x2);
					}
				}
			}
			if (ind[0] == 0) {
				ind[0] = count;
				let fa = snx(a);
				let fb = snx(b);
				if (fb < fa) {
					a  = b;
					fa = fb;
				}
				if (fa < f1) {
					x      = a;
					val[0] = fa;
				}
			}
			return x;
		}
	</SCRIPT>
</HEAD>
<BODY STYLE="font-size: 130%; background-color: #eeffee;">
	<H2 STYLE="text-align:center"><B>最適化(黄金分割法)</B></H2>
	<DL>
		<DT>  テキストフィールドには,例として,以下に示すような関数の [-2, -1] 区間における最小値を求める場合に対する値が設定されています.他の問題を実行する場合は,それらを適切に修正してください.なお,目的関数は,JavaScript の仕様に適合した形式で記述してあることに注意してください. 
		<P STYLE="text-align:center"><IMG SRC="gold.gif"></P>
	</DL>
	<DIV STYLE="text-align:center">
		初期値:<INPUT ID="a" STYLE="font-size: 100%" TYPE="text" SIZE="5" VALUE="-2">,
				<INPUT ID="b" STYLE="font-size: 100%" TYPE="text" SIZE="5" VALUE="-1"> 
		最大繰り返し回数:<INPUT ID="max" STYLE="font-size: 100%" TYPE="text" SIZE="5" VALUE="100"><BR><BR>
		目的関数: f(x) = <INPUT ID="func" STYLE="font-size: 100%" TYPE="text" SIZE="50" VALUE="x * x * x * x + 3.0 * x * x * x + 2.0 * x * x + 1.0">  
		<BUTTON STYLE="font-size: 100%; background-color: pink" onClick="main()">実行</BUTTON><BR><BR>
		結果:<INPUT ID="res" STYLE="font-size: 100%" TYPE="text" SIZE="40">
	</DIV>
</BODY>
</HTML>
			
<?php
/*********************************************/
/* 黄金分割法によるy=x^4+3x^3+2x^2+1の最小値 */
/*      coded by Y.Suganuma                  */
/*********************************************/
	$a   = -2.0;
	$b   = -1.0;
	$eps = 1.0e-10;
	$max = 100;
	$x = gold($a, $b, $eps, $val, $ind, $max, "snx");
	printf("x %f val %f ind %d\n", $x, $val, $ind);
/****************/
/* 関数値の計算 */
/****************/
function snx($x)
{
	return $x * $x * $x * $x + 3.0 * $x * $x * $x + 2.0 * $x * $x + 1.0;
}
/******************************************/
/* 黄金分割法(関数の最小値)               */
/*      a,b : 初期区間 a < b              */
/*      eps : 許容誤差                    */
/*      val : 間数値                      */
/*      ind : 計算状況                    */
/*              >= 0 : 正常終了(収束回数) */
/*              = -1 : 収束せず           */
/*      max : 最大試行回数                */
/*      fun : 関数値を計算する関数の名前  */
/*      return : 結果                     */
/******************************************/
function gold($a, $b, $eps, &$val, &$ind, $max, $fun)
{
	$x     = 0.0;
	$tau   = (sqrt(5.0) - 1.0) / 2.0;
	$count = 0;
	$ind   = -1;
	$x1    = $b - $tau * ($b - $a);
	$x2    = $a + $tau * ($b - $a);
	$f1    = $fun($x1);
	$f2    = $fun($x2);
	while ($count < $max && $ind < 0) {
		$count += 1;
		if ($f2 > $f1) {
			if (abs($b-$a) < $eps && abs($b-$a) < $eps*abs($b)) {
				$ind = 0;
				$x   = $x1;
				$val = $f1;
			}
			else {
				$b  = $x2;
				$x2 = $x1;
				$x1 = $a + (1.0 - $tau) * ($b - $a);
				$f2 = $f1;
				$f1 = $fun($x1);
			}
		}
		else {
			if (abs($b-$a) < $eps && abs($b-$a) < $eps*abs($b)) {
				$ind = 0;
				$x   = $x2;
				$val = $f2;
				$f1  = $f2;
			}
			else {
				$a  = $x1;
				$x1 = $x2;
				$x2 = $b - (1.0 - $tau) * ($b - $a);
				$f1 = $f2;
				$f2 = $fun($x2);
			}
		}
	}
	if ($ind == 0) {
		$ind = $count;
		$fa  = $fun($a);
		$fb  = $fun($b);
		if ($fb < $fa) {
			$a  = $b;
			$fa = $fb;
		}
		if ($fa < $f1) {
			$x   = $a;
			$val = $fa;
		}
	}
	return $x;
}
?>
			
#********************************************/
# 黄金分割法によるy=x^4+3x^3+2x^2+1の最小値 */
#      coded by Y.Suganuma                  */
#********************************************/
#***************/
# 関数値の計算 */
#***************/
snx = Proc.new { |x|
	x * x * x * x + 3.0 * x * x * x + 2.0 * x * x + 1.0
}
#*****************************************/
# 黄金分割法(関数の最小値)               */
#      a,b : 初期区間 a < b              */
#      eps : 許容誤差                    */
#      val : 間数値                      */
#      ind : 計算状況                    */
#              >= 0 : 正常終了(収束回数) */
#              = -1 : 収束せず           */
#      max : 最大試行回数                */
#      fun : 関数値を計算する関数の名前  */
#      return : 結果                     */
#*****************************************/
def gold(a, b, eps, val, ind, max, &fun)
	x      = 0.0
	tau    = (Math.sqrt(5.0) - 1.0) / 2.0
	count  = 0
	ind[0] = -1
	x1     = b - tau * (b - a)
	x2     = a + tau * (b - a)
	f1     = fun.call(x1)
	f2     = fun.call(x2)
	while count < max && ind[0] < 0
		count += 1
		if f2 > f1
			if (b-a).abs() < eps && (b-a).abs() < eps*b.abs()
				ind[0] = 0
				x      = x1
				val[0] = f1
			else
				b  = x2
				x2 = x1
				x1 = a + (1.0 - tau) * (b - a)
				f2 = f1
				f1 = fun.call(x1)
			end
		else
			if (b-a).abs() < eps && (b-a).abs() < eps*b.abs()
				ind[0] = 0
				x      = x2
				val[0] = f2
				f1     = f2
			else
				a  = x1
				x1 = x2
				x2 = b - (1.0 - tau) * (b - a)
				f1 = f2
				f2 = fun.call(x2)
			end
		end
	end
	if ind[0] == 0
		ind[0] = count
		fa     = fun.call(a)
		fb     = fun.call(b)
		if fb < fa
			a  = b
			fa = fb
		end
		if fa < f1
			x      = a
			val[0] = fa
		end
	end
	return x
end
ind = Array.new(1)
val = Array.new(1)
a   = -2.0
b   = -1.0
eps = 1.0e-10
max = 100
x = gold(a, b, eps, val, ind, max, &snx)
printf("x %f val %f ind %d\n", x, val[0], ind[0])
			
# -*- coding: UTF-8 -*-
import numpy as np
import sys
from math import *
############################################
# 黄金分割法(関数の最小値)
#      a,b : 初期区間 a < b
#      eps : 許容誤差
#      val : 間数値
#      ind : 計算状況
#              >= 0 : 正常終了(収束回数)
#              = -1 : 収束せず
#      max : 最大試行回数
#      fun : 関数値を計算する関数の名前
#      return : 結果
#      coded by Y.Suganuma
############################################
def gold(a, b, eps, val, ind, max, fun) :
	x      = 0.0
	tau    = (sqrt(5.0) - 1.0) / 2.0
	count  = 0
	ind[0] = -1
	x1     = b - tau * (b - a)
	x2     = a + tau * (b - a)
	f1     = fun(x1)
	f2     = fun(x2)
	while count < max and ind[0] < 0 :
		count += 1
		if f2 > f1 :
			if (abs(b-a) < eps) and (abs(b-a) < eps*abs(b)) :
				ind[0] = 0
				x      = x1
				val[0] = f1
			else :
				b  = x2
				x2 = x1
				x1 = a + (1.0 - tau) * (b - a)
				f2 = f1
				f1 = fun(x1)
		else :
			if (abs(b-a) < eps) and (abs(b-a) < eps*abs(b)) :
				ind[0] = 0
				x      = x2
				val[0] = f2
				f1     = f2
			else :
				a  = x1
				x1 = x2
				x2 = b - (1.0 - tau) * (b - a)
				f1 = f2
				f2 = fun(x2)
	if ind[0] == 0 :
		ind[0] = count
		fa     = fun(a)
		fb     = fun(b)
		if fb < fa :
			a  = b
			fa = fb
		if fa < f1 :
			x      = a
			val[0] = fa
	return x
############################################
# 黄金分割法によるy=x^4+3x^3+2x^2+1の最小値
#      coded by Y.Suganuma
############################################
			# 関数値の計算
def snx(x) :
	return x * x * x * x + 3.0 * x * x * x + 2.0 * x * x + 1.0
			# 設定と実行
a   = -2.0
b   = -1.0
eps = 1.0e-10
max = 100
val = np.empty(1, np.float)
ind = np.empty(1, np.int)
x = gold(a, b, eps, val, ind, max, snx)
print("x " + str(x) + " val " + str(val[0]) + " ind " + str(ind[0]))
			
/*********************************************/
/* 黄金分割法によるy=x^4+3x^3+2x^2+1の最小値 */
/*        coded by Y.Suganuma                */
/*********************************************/
using System;
class Program
{
	static void Main()
	{
		Test1 ts = new Test1();
	}
}
class Test1
{
	public Test1()
	{
		double a   = -2.0;
		double b   = -1.0;
		double eps = 1.0e-10;
		double val = 0.0;
		int max    = 100;
		int ind    = 0;
		double x = gold(a, b, eps, ref val, ref ind, max, snx);
		Console.WriteLine("x " + x + " val " + val + " ind " + ind);
	}
			// 関数値の計算
	double snx(double x)
	{
		return x * x * x * x + 3.0 * x * x * x + 2.0 * x * x + 1.0;
	}
	/************************************************/
	/* 黄金分割法(関数の最小値)                     */
	/*      a,b : 初期区間 a < b                    */
	/*      eps : 許容誤差                          */
	/*      val : 間数値                            */
	/*      ind : 計算状況                          */
	/*              >= 0 : 正常終了(収束回数)       */
	/*              = -1 : 収束せず                 */
	/*      max : 最大試行回数                      */
	/*      fn : 関数値を計算する関数               */
	/*      return : 結果                           */
	/************************************************/
	double gold(double a, double b, double eps, ref double val, ref int ind, int max,
	            Func<double, double> fn)
	{
		ind        = -1;
		int count  = 0;
		double tau = (Math.Sqrt(5.0) - 1.0) / 2.0;
		double x1  = b - tau * (b - a);
		double x2  = a + tau * (b - a);
		double f1  = fn(x1);
		double f2  = fn(x2);
		double x   = 0.0;
		while (count < max && ind < 0) {
			count += 1;
			if (f2 > f1) {
				if (Math.Abs(b-a) < eps && Math.Abs(b-a) < eps*Math.Abs(b)) {
					ind = 0;
					x   = x1;
					val = f1;
				}
				else {
					b  = x2;
					x2 = x1;
					x1 = a + (1.0 - tau) * (b - a);
					f2 = f1;
					f1 = fn(x1);
				}
			}
			else {
				if (Math.Abs(b-a) < eps && Math.Abs(b-a) < eps*Math.Abs(b)) {
					ind = 0;
					x   = x2;
					val = f2;
					f1  = f2;
				}
				else {
					a  = x1;
					x1 = x2;
					x2 = b - (1.0 - tau) * (b - a);
					f1 = f2;
					f2 = fn(x2);
				}
			}
		}
		if (ind == 0) {
			ind       = count;
			double fa = fn(a);
			double fb = fn(b);
			if (fb < fa) {
				a  = b;
				fa = fb;
			}
			if (fa < f1) {
				x   = a;
				val = fa;
			}
		}
		return x;
	}
}
			
'''''''''''''''''''''''''''''''''''''''''''''
' 黄金分割法によるy=x^4+3x^3+2x^2+1の最小値 '
'        coded by Y.Suganuma                '
'''''''''''''''''''''''''''''''''''''''''''''
Module Test
	Sub Main()
		Dim a As Double    = -2.0
		Dim b As Double    = -1.0
		Dim eps As Double  = 1.0e-10
		Dim val As Double  = 0.0
		Dim max As Integer = 100
		Dim ind As Integer = 0
			' 関数値の計算(ラムダ式)
		Dim snx = Function(v) As Double 
			Return v * v * v * v + 3.0 * v * v * v + 2.0 * v * v + 1.0
		End Function
			' 実行
		Dim x As Double = gold(a, b, eps, val, ind, max, snx)
		Console.WriteLine("x " & x & " val " & val & " ind " & ind)
	End Sub
	''''''''''''''''''''''''''''''''''''''''''''''''
	' 黄金分割法(関数の最小値)                     '
	'      a,b : 初期区間 a < b                    '
	'      eps : 許容誤差                          '
	'      val : 間数値                            '
	'      ind : 計算状況                          '
	'              >= 0 : 正常終了(収束回数)       '
	'              = -1 : 収束せず                 '
	'      max : 最大試行回数                      '
	'      fn : 関数値を計算する関数               '
	'      return : 結果                           '
	''''''''''''''''''''''''''''''''''''''''''''''''
	Function gold(a As Double, b As Double, eps As Double, ByRef val As Double,
	              ByRef ind As Integer, max As Integer, fn As Func(Of Double, Double))
		ind = -1
		Dim count As Integer  = 0
		Dim tau As Double = (Math.Sqrt(5.0) - 1.0) / 2.0
		Dim x1 As Double  = b - tau * (b - a)
		Dim x2 As Double  = a + tau * (b - a)
		Dim f1 As Double  = fn(x1)
		Dim f2 As Double  = fn(x2)
		Dim x As Double   = 0.0
		Do while count < max and ind < 0
			count += 1
			If f2 > f1
				If Math.Abs(b-a) < eps and Math.Abs(b-a) < eps*Math.Abs(b)
					ind = 0
					x   = x1
					val = f1
				Else
					b  = x2
					x2 = x1
					x1 = a + (1.0 - tau) * (b - a)
					f2 = f1
					f1 = fn(x1)
				End If
			Else
				If Math.Abs(b-a) < eps and Math.Abs(b-a) < eps*Math.Abs(b)
					ind = 0
					x   = x2
					val = f2
					f1  = f2
				Else
					a  = x1
					x1 = x2
					x2 = b - (1.0 - tau) * (b - a)
					f1 = f2
					f2 = fn(x2)
				End If
			End If
		Loop
		If ind = 0
			ind = count
			Dim fa As Double = fn(a)
			Dim fb As Double = fn(b)
			If fb < fa
				a  = b
				fa = fb
			End If
			If fa < f1
				x   = a
				val = fa
			End If
		End If
		Return x
	End Function
End Module
			
| 情報学部 | 菅沼ホーム | 目次 | 索引 |