Last active
July 26, 2018 12:38
-
-
Save dayalpuri/8bec9be2fe1956d0aa7c to your computer and use it in GitHub Desktop.
Simulated Annealing (Monte Carlo) sloužící k dekompozici cen balíčků televizních stanic
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#################################################################### | |
# Simulated Annealing je Monte Carlo metoda, která vychází z | |
# fyzikálního pozorování - při kalení oceli je vhodné její | |
# teplotu snižovat postupně, protože molekuly při pomalém tuhnutí | |
# zaujímají prostorovou konfiguraci s minimální energetickou | |
# náročností vazeb - to se projevuje v pevnosti (a křehkosti kovu) | |
# annealing si půjčuje myšlenku, že postupným zkracováním | |
# vzdálenosti pátrače od dosud nejlepšího lokálního minima se | |
# velmi často dosáhne globálního minima, nebo alespoň minima, | |
# které je mu blízké. | |
################################################################### | |
# skript slouží k odhadu cen jednotlivých stanic schovaných v | |
# balíčcích poskytovatelů televizního vysílání | |
# poskytovatelé neuvádějí cenu za stanici, ale pouze za celý balíček | |
# hlavní účel skriptu je stanovit cenové hladiny stanic pro | |
# ACBC conjoint analýzu | |
#################################################################### | |
setwd("./dekompozice cen") | |
for (c in 1:10) { # cyklus pro vícenásobné spuštění annealingu | |
################################################################# | |
# ceny.csv jsou ceny jednotlivých balíčků, ke stažení jsou zde: | |
# https://dl.dropboxusercontent.com/u/5817117/ceny.csv | |
# balicky.csv jsou zastoupeni stanic v baliccich, ke stažení zde: | |
# https://dl.dropboxusercontent.com/u/5817117/balicky.csv | |
################################################################# | |
ceny<-read.csv2("ceny.csv",as.is=T) | |
ceny<-ceny[order(ceny$balicek),] | |
balicky<-read.csv2("balicky.csv",as.is=T) | |
balicky[is.na(balicky)]<-0 | |
#set.seed(1234) # pro zopakovani simulace, pokud chcete pustit více simulací za sebou, tak je to třeba vypnout, jinak se spočítá pokaždé stejně | |
maxcena<-200 # maximální cena jedné stanice | |
# pro jednoduchost je minimální cena vždy 0 | |
step<-2 # maximální krok, kterým se annealing odchyluje od současného lokálního optima | |
pokusu<-100000 # kolik kroků simulace se provede 100 000 už dává velmi dobré výsledky, pro hrubou orientaci stačí 1000 | |
#################################################### | |
# varianta "logaritmické schody" | |
# an<-sort(rep(2:round(step,0),pokusu),decreasing=T) | |
# an<-round(log(an),0) | |
#################################################### | |
########################### | |
# varianta "pevného kroku" | |
#an<-rep(1,pokusu) | |
########################### | |
############################################## | |
# varianta logaritmického poklesu kroku | |
# sample si s tím poradí tak, že část veličin | |
#generuje zaokrouhlených nahoru a část dolu | |
#(asi v proporci, ale nemám to ověřené) | |
############################################## | |
an<-(log(pokusu:1)/log(pokusu)*step) | |
an[an<1]<-1 | |
plot(an) #graf jak se zmenšuje krok = tuhne ocel | |
balicku<-dim(balicky)[1] | |
asum<-1e10 # něco velkého, co určitě bude větší, než součet odchylek annealingu od reálných balíčků | |
asum_e<-1e10 # dtto | |
balicky$best<-round(maxcena/2) #pro balicky, kde je vice nulovych cen je lepsi zadat vychozi hodnotu best<-0 | |
pb <- txtProgressBar(style=3) # inicializace progressbaru | |
j<-0 # v kolikátém jsem kroku cyklu | |
delka_cyklu<-length(an) # kolik kroků cyklus má | |
for (i in an) { | |
j<-j+1 | |
p<-j/delka_cyklu # procento pro porgress bar | |
setTxtProgressBar(pb, p) # update progressbaru | |
print(paste("asum",asum,"asum_e",asum_e)) # jak daleko je lokální optimum od předlohy | |
################################################################ | |
# tohle je vlastní annealing - k optimu přičtu náhodný vektor | |
# inkrementů, které se ((obvykle) logaritmicky) zmenšují v čase | |
# podstata annealingu je, že na začátku je dobrodruh a na | |
# konci je konzerva, která se drží u posledního optima | |
################################################################ | |
balicky$try<-balicky$best+((sample(2,balicku,T)-1)*2-1)*(sample(i,balicku,replace=T)) | |
############################################################ | |
# tohle je z lenosti - když annealingem vyjedu z hranic, | |
# tak to oříznu zpátky | |
############################################################ | |
balicky$try[balicky$try<0]<-0 | |
balicky$try[balicky$try>maxcena]<-maxcena | |
############################################################ | |
# průběžné statistiky o tom, jak vypadá rozložení cen stanic | |
# a taky, jaký je aktuální krok | |
############################################################ | |
print(paste(min(balicky$try),median(balicky$try),max(balicky$try),"@",i)) | |
############################################################ | |
# tohle by asi chtělo uklidit do funkce, je to výpočet | |
# vzdálenosti simulovaného balíčku od předlohy a ukládání | |
# dosud nejlepšího výsledku | |
############################################################ | |
csum<-as.data.frame(colSums(balicky[,2:(length(balicky)-1)]*balicky$try)) | |
csum<-data.frame("balicek"=rownames(csum),"try"=csum[,1]) | |
csum<-csum[order(csum$balicek),] | |
mceny<-merge(ceny,csum,by="balicek") | |
############################################################## | |
# vypadá to, že s eukleidovskou vzdáleností (diff_e) metoda | |
# lépe konverguje, nicméně počítám obě, absolutní hodnoty jsou | |
# poměrně názorné pro laiky | |
############################################################## | |
diff<-abs(mceny$cena-mceny$try) | |
diff_e<-diff*diff | |
if (sqrt(sum(diff_e))<asum_e) { | |
ceny$abest<-mceny$try | |
asum<-sum(diff) | |
asum_e<-sqrt(sum(diff_e)) | |
ceny$diff<-diff | |
ceny$diff_e<-diff_e | |
balicky$best<-balicky$try | |
} | |
} | |
close(pb) # konec progressbaru annealing doběhl | |
################################## | |
# zobrazení a uložení výsledků | |
################################## | |
ceny | |
show<-data.frame("balicek"=balicky[,1],"cena"=balicky$best) | |
show<-show[order(show[,2]),] | |
show | |
asum | |
asum_e | |
write.csv2(show,paste("dekompozice_cen_",asum,"_",c,".csv",sep="")) | |
write.csv2(ceny,paste("dekompozice_balicky_",asum,"_",c,".csv",sep="")) | |
alarm() # akustická signál, že je hotovo | |
} # ukončení cyklu, pokud annealing spouštíme opakovaně, číslo běhu se ukládá do názvu souboru |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment