#оптимизатор DiscrOptimizer <- function(fitness, minValue, maxValue, targetLength, fitnessCallLimit, loops = 3){ testVector <- rep(minValue, targetLength) fitnessAccessCounter <- 0 prevBestScore <- Inf bestSolution <- testVector for(loopIter in 1:loops){ for(i in 1:targetLength){ testVector <- bestSolution valueGrid <- seq(minValue + (loopIter-1)/loops, maxValue + (loopIter-1)/loops, length.out = round(fitnessCallLimit/loops/targetLength)+1) valueGrid <- valueGrid[-length(valueGrid)] for(j in valueGrid){ testVector[i] <- j fitnessAccessCounter <- fitnessAccessCounter + 1 score <- fitness(testVector) if(score < prevBestScore){ bestSolution <- testVector prevBestScore <- score } if(fitnessAccessCounter >= fitnessCallLimit) break } if(fitnessAccessCounter >= fitnessCallLimit) break } } return(list(solution = bestSolution, n_calls = fitnessAccessCounter)) } library(compiler) DiscrOptimizerCmp <- cmpfun(DiscrOptimizer) #обратите внимание что для оптимизации испольуется функция выше (DiscrOptimizerCmp). Она создана до инициализации тестовых данных, и не использует их, читерства нету. #Это функция не будет изменяться в коде далее, это финальный вариант. #входные данные key <- c("A","a","B","b","C","c","D","d","E","e","F","f","G","g","H","h","I","i","J","j","K","k","L","l","M","m","N","n","O","o","P","p","Q","q","R","r","S","s","T","t","U","u","V","v","W","w","X","x","Y","y","Z","z") test1 <- "SptstmLEjXhdESqotbRQbmsYKkJTZiOHBEenIbGqLHwxqfWTok" test2 <- "HXWSXpsaYbViFIQUlKYbpCiZfBdyHGKxNLFrigWMOlDjzpFlLHOKONHlkxILqfpmdHHoTwMfCwzqLELqceuLeHtrdpvjBxfdzDHzmopkgKPXKnYWItcjFRFsqpOQdQRQZNSTNtCwvxicircFznboUJ" test3 <- "QbgpsGPELKivNySHxdBjAJKudnJtvQDXtBlfKQBuUjFyovbSejUiPaByUjmMWHEGIHRqDCHbMDPdnRRcEMuXzCoBvifSQAdcbopwGBiDbECxbrzJLZTkOYdWdEmUhnelievPauljpmAmvbUnDuBVPvejBBBTbmqLatRbuPgjUMNSQXBVviWULZjslNLgFKfINJFGzOOusXnBDeCpthgOmlTEUPxQyrUOTKhtySNODxsqEtLjPvxceGodZRqWqspsEUQXeaNPeEQJNmaVOoMzYGjfONlPPTEpUtqPbigcrPlpCBxUKLFnHgAENIzDExGCcBoKdkTKXQgorapGkuGPrzPWjsSjThwffRjOYxFyQCWZhytILMltScNKgSuZUVlgRdWyaLFLGEwHVHJiuqOgxblyTshFTLPOpJQFZKNpPmSPghRsKxZyYIjxzoxyCWEqRpylkGHLccmQoGGdqHyLkfNVrMHViujGBpBpzFWASkeuvHXINEnVyAKIzCRabWrELmTEknYoWHNFDkteLimAJVvgrlgMvnwkCTthjHMPPxZNmqFulCkmHSxqaAXRHfYetIpvQmQPkBxDcVXlCzqLmqzQUpIWBgfTuNmIYbyhKqJBcrVmkDJRuNsNIOYXUVHPaclvEVgqDGeZrYemBXMQBBaTMlBHfCZJUfIGCmOQsrzHcEmdcermCYDyqkQEcBnUzkrypSGMwGgXoUoIgfmatuMYTxnKeqiWcqxcQaxNtPDOkgMAsRdRBcXQHvIMHTDrBHFlCvngcvpnXWoLFPSnvGLbEmJNFcwMhbllYogKDmltLUNwymaJenKnYOVhviXqYFkEFkoTQlFxJEeWUFRoBeLLrdQICasUmgOiWoGgxZegCZVAaBCGmhkhYtmqWqGPBGFJBcHcWWmSCFwDmrkCPxnWvJxbDoNYFNKhtzanuEawUpeEPgpmLZGZaFezWCZwExZWfDbBrLlaTyrGGfLMehhrqbImcjiPOQPKmgIF" key_numeric <- 1:length(key) test1_numeric <- c() for(i in 1:nchar(test1)){ test1_numeric[i] <- which(key == substr(test1, i, i)) } test2_numeric <- c() for(i in 1:nchar(test2)){ test2_numeric[i] <- which(key == substr(test2, i, i)) } test3_numeric <- c() for(i in 1:nchar(test3)){ test3_numeric[i] <- which(key == substr(test3, i, i)) } testRepeats <- 20 #фитнесс функция targetVector <- c() fitness <- function(solution){ return(-sum(targetVector == round(solution))) } fitnessCmp <- cmpfun(fitness) #выполнение теста. В данном случае фитнесс фунция будет вызвана 20000 раз. #Шаг поиска определяется в зависимости от допустимого числа попыток. #Чем больше попыток разрешено (fitnessCallLimit), тем мельче будет сетка, и точнее поиск. startTime <- Sys.time() for (i in 1:testRepeats){ targetVector <- test1_numeric result1 <- DiscrOptimizerCmp(fitness = fitnessCmp, minValue = 1, maxValue = length(key_numeric), targetLength = length(targetVector), fitnessCallLimit = 20000) } executionTime <- (Sys.time() - startTime)/testRepeats #вывод данных cat("Accuracy: ", mean(targetVector == round(result1$solution)), "; fitness calls: ", result1$n_calls, "; average execution time: ", executionTime, " s\n", sep="") #cat("result text: ", paste(key[round(result1$solution)], collapse=""), "\n") #cat("original text: ", test1, "\n") #comparedText <- key[round(result1$solution)] #comparedText[round(result1$solution) != targetVector] <- "_" #cat("compared text: ", paste(comparedText, collapse=""), "\n") startTime <- Sys.time() for (i in 1:testRepeats){ targetVector <- test2_numeric result2 <- DiscrOptimizerCmp(fitness = fitnessCmp, minValue = 1, maxValue = length(key_numeric), targetLength = length(targetVector), fitnessCallLimit = 20000) } executionTime <- (Sys.time() - startTime)/testRepeats #вывод данных cat("Accuracy: ", mean(targetVector == round(result2$solution)), "; fitness calls: ", result2$n_calls, "; average execution time: ", executionTime, " s\n", sep="") #cat("result text: ", paste(key[round(result2$solution)], collapse=""), "\n") #cat("original text: ", test2, "\n") #comparedText <- key[round(result2$solution)] #comparedText[round(result2$solution) != targetVector] <- "_" #cat("compared text: ", paste(comparedText, collapse=""), "\n") startTime <- Sys.time() for (i in 1:testRepeats){ targetVector <- test3_numeric result3 <- DiscrOptimizerCmp(fitness = fitnessCmp, minValue = 1, maxValue = length(key_numeric), targetLength = length(targetVector), fitnessCallLimit = 20000) } executionTime <- (Sys.time() - startTime)/testRepeats #вывод данных cat("Accuracy: ", mean(targetVector == round(result3$solution)), "; fitness calls: ", result3$n_calls, "; average execution time: ", executionTime, " s\n", sep="") #cat("result text: ", paste(key[round(result3$solution)], collapse=""), "\n") #cat("original text: ", test3, "\n") #comparedText <- key[round(result3$solution)] #comparedText[round(result3$solution) != targetVector] <- "_" #cat("compared text: ", paste(comparedText, collapse=""), "\n") #Для доказательства что оптимизатор DiscrOptimizerCmp не читерит с тестовыми данными, и может работать с любой фитнесс функцией - я просто беру и подставляю в него функцию x^2 + y^2 + z^2 #Оптимизатор её принмает, и ищет минимум, без всяких дополнительных манипуляций. newFitness <- function(inp){sum(inp * inp)} newFitnessCmp <- cmpfun(newFitness) result_squares <- DiscrOptimizerCmp(fitness = newFitnessCmp, minValue = -10, maxValue = 10, targetLength = 3, fitnessCallLimit = 1000) cat("Another test. Optimisation result: ", newFitnessCmp(result_squares$solution), "\n") cat("Global minimum (correct result) should be 0. Error = ", 0-newFitnessCmp(result_squares$solution), "\n") #Оптимизация функции Rastrigin() rastr_imput_length = 100 #Длинна входного вектора Rastrigin = 100 rastr <- function(xx) { ########################################################################## # # RASTRIGIN FUNCTION # # Authors: Sonja Surjanovic, Simon Fraser University # Derek Bingham, Simon Fraser University # Questions/Comments: Please email Derek Bingham at dbingham@stat.sfu.ca. # # Copyright 2013. Derek Bingham, Simon Fraser University. # # THERE IS NO WARRANTY, EXPRESS OR IMPLIED. WE DO NOT ASSUME ANY LIABILITY # FOR THE USE OF THIS SOFTWARE. If software is modified to produce # derivative works, such modified software should be clearly marked. # Additionally, this program is free software; you can redistribute it # and/or modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; version 2.0 of the License. # Accordingly, this program is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # For function details and reference information, see: # http://www.sfu.ca/~ssurjano/ # ########################################################################## # # INPUT: # # xx = c(x1, x2, ..., xd) # ########################################################################## d <- length(xx) sum <- sum(xx^2 - 10*cos(2*pi*xx)) y <- 10*d + sum return(y) } rastrCmp <- cmpfun(rastr) result_rastr <- DiscrOptimizerCmp(fitness = rastrCmp, minValue = -5, maxValue = 5, targetLength = rastr_imput_length, fitnessCallLimit = 100000) cat("Rastrigin test. Optimisation result: ", rastrCmp(result_rastr$solution), "\n") cat("Global minimum (correct result) should be 0. Error = ", 0-rastrCmp(result_rastr$solution), "\n")