シンプレックス法

# -*- coding: UTF-8 -*-
from math import *
import numpy as np

############################################
# シンプレックス法
#      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

----------------------------------

# -*- coding: UTF-8 -*-
import numpy as np
import sys
from math import *
from function import simplex

############################################
# シンプレックス法による最小値の計算
#      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))