模拟退火中的约束

2024-04-19 01:06:58 发布

您现在位置:Python中文网/ 问答频道 /正文

我有这个模拟退火算法,我从一个教程中得到的。我的两个边界必须是正的,希望是平的>;1.如何在不产生偏差的情况下将其纳入算法中

我曾考虑过在目标函数中取候选人的绝对值,但我认为这会影响算法,对吗

编辑:添加代码

from numpy import asarray
from numpy import exp
from numpy.random import randn
from numpy.random import rand
from numpy.random import seed
import numpy as np
import matplotlib.pyplot as plt
import cv2
import sklearn.metrics

def to_shape(a, shape):
    x_, y_ = shape
    x, y = a.shape
    x_pad = (x_-x)
    y_pad = (y_-y)

    if x_pad >= 0 and y_pad >= 0:
        return np.pad(a, ((x_pad//2, x_pad//2 + x_pad%2),(y_pad//2, y_pad//2 + y_pad%2)), mode = 'constant', constant_values=(0))

    elif x_pad >= 0 and y_pad < 0:
        return np.pad(a,((x_pad//2, x_pad//2 + x_pad%2),(0,0)), mode = 'constant')[:,abs(y_pad//2 + y_pad%2):y_pad//2]

    elif x_pad < 0 and y_pad >= 0:
        return np.pad(a,((0,0),(y_pad//2, y_pad//2 + y_pad%2)), mode = 'constant')[abs(x_pad//2 + x_pad%2):x_pad//2:,]

    elif x_pad < 0 and y_pad < 0:
        return a[abs(x_pad//2 + x_pad%2):x_pad//2 , abs(y_pad//2 + y_pad%2):y_pad//2]

    else:
        return a

def objective(x):
    if x[0] < 0.5:
        x[0] = 0.5
    if x[1] < 0.5:
        x[1] = 0.5
    y = to_shape(cv2.resize(img.astype("uint8"), None, fx=np.float64(x[0]), fy=np.float64(x[1]), interpolation=cv2.INTER_LINEAR), img.shape)
    measure = sklearn.metrics.mean_squared_error(y, img)
    return measure



def simulated_annealing(bounds, n_iterations, step_size, temp):
    best = np.array([random.uniform(bounds[0][0],bounds[0][1]), 
                     random.uniform(bounds[1][0],bounds[1][1])])
    best_eval = objective(best)
    curr, curr_eval = best, best_eval

    for i in range(n_iterations):
        candidate = curr + randn(len(bounds)) * step_size
        candidate_eval = objective(candidate)

        if candidate_eval < best_eval:
            best, best_eval = candidate, candidate_eval
            print('>%d f(%s) = %.5f' % (i, best, best_eval))

        diff = candidate_eval - curr_eval
        t = temp / float(i + 1)
        metropolis = exp(-diff / t)

        if diff < 0 or rand() < metropolis:
            curr, curr_eval = candidate, candidate_eval
        
    return [best, best_eval]

bounds = asarray([[1, 3], [1, 3]])
img = np.zeros((100, 100)).astype(int)
img = cv2.circle(img, (50, 50), 40, 1, thickness=1, lineType=8, shift=0)
n_iterations = 2000
step_size = 0.2
temp = 100
best, score = simulated_annealing(bounds, n_iterations, step_size, temp)
print('Done!')
print('f(%s) = %f' % (best, score))

Tags: fromimportnumpyimgreturnifevalnp