#!/usr/bin/env python
# coding: utf-8
"""
Zde leží DiceBox (tuším, bude jeden)
DiceBox pěčlivě ukladá věškerá data,
věškeré sady vzorků, průběžné odhady a tak.
Nejsem už jistý, zda DiceBox je šťastný nazev, neboť
teďkom je to spíše jen krabička pro krámy
"""
import numpy as np
from scipy import spatial
from . import plot
import pickle
from . import IS_stat
from .candybox import CandyBox
from scipy import optimize # for BlackSimpleX
from .samplebox import SampleBox # for candidates packing
from . import simplex as sx
from . import lukiskon as lk
from . import estimation as stm # for KechatoLukiskon
import collections #E for Counter in MinEnergyCensoredSampling
# considering to rewrite it with pandas
class GuessBox:
"""
Je tu vynalezaní kola, ale aspoň tak
Odhady můžou tvořít strašnej bordel a proto jsou
ukladany do slovníku.
Tak ale jej nemůžu furt ukladat,
proto to robim s určitým krokem
Na konci je třeba zabalit tuhle krabičku ručně!
"""
def __init__(gb, filename='', flush=100):
"""
.counter - kdy bylo poslední ukladaní
"""
gb.estimations = dict()
gb.filename = filename
gb.counter = 0
gb.flush = flush
gb.pick()
def __repr__(self):
return "%s(%r, %s)"%(self.__class__.__name__, self.filename, self.flush)
def __str__(gb):
return str(gb.estimations)
def __len__(gb):
return len(gb.estimations)
def __getitem__(gb, slice):
return gb.estimations[slice]
def guess(gb, index, nsim, estimation):
if index in gb.estimations:
gb.estimations[index][0].append(nsim)
gb.estimations[index][1].append(estimation)
else:
gb.estimations[index] = [[nsim], [estimation]]
gb.counter+= 1
if gb.filename and gb.counter > gb.flush:
gb.put()
def pick(gb):
if gb.filename:
try:
with open(gb.filename + '.pickle', 'rb') as f:
gb.estimations = pickle.load(f)
except:
# škoda, no
print("GuessBox: Já tu vaši odhady %s.pickle nevidím" % gb.filename)
else:
print('GuessBox is in air mode')
def put(gb):
if gb.filename:
try:
with open(gb.filename + '.pickle', 'wb') as f:
pickle.dump(gb.estimations, f)
gb.counter = 0
except:
# nefrčí...
print("GuessBox: Can not write %s.pickle" % gb.filename)
else:
print('GuessBox is in air mode')
#оӵ дӥсё
class DiceBox:
"""
DiceBox pěčlivě ukladá věškerá data,
věškeré sady vzorků (well, no yet), průběžné odhady a tak.
Nejsem už jistý, zda DiceBox je šťastný nazev, neboť
teďkom je to spíše jen krabička pro krámy
"""
def __init__(bx, sample_box):
bx.sample_box = sample_box
# user candidates
#ё шоб было
bx.candidates = CandyBox(bx.f_model())
# nové uložiště odhadů zadám explicitně, aby se pak
# odhady v stm kodu přířazovaly správné krabičce
bx.estimations = []
# má bejt GuessBox součástí DiceBoxu?
try:
bx.guessbox = GuessBox(sample_box.filename, flush=20)
except:
bx.guessbox = GuessBox("", flush=20)
bx.regen()
def __repr__(bx):
return "%s(%s)"%('DiceBox', repr(bx.sample_box))
def __str__(bx):
return str('DiceBox ' + bx.sample_box)
def __len__(bx):
return bx.sample_box.nsim
def __call__(bx):
"""
Offer next sample
"""
# I do not see nothing illegal here
# LHS_like_correction do right conversion
return bx.LHS_like_correction(bx.f_model(1))
def __getitem__(bx, slice):
# stačí vratit sample_box
return bx.sample_box[slice]
def __getattr__(dx, attr):
if attr == 'dicebox':
return dx
# branime sa rekurzii
# defend against recursion
# рекурсилы пезьдэт!
if attr == 'sample_box':
raise AttributeError
# По всем вопросам обращайтесь
# на нашу горячую линию
else:
return getattr(dx.sample_box, attr)
# just plot, green points, red points...
plot2D = plot.plot2D
plot3D = plot.plot3D
show2D = plot.show2D
show3D = plot.show3D
# přidávání vzorků musí bejt explicitní!
def add_sample(bx, input_sample):
bx._logger(msg="we have got new data:", data=input_sample)
bx.sample_box.add_sample(input_sample)
# tohle musí převest rozdělení vstupního vzorku na vlastní rozdělení skříňky
inner_sample = bx.sample_box.new_sample(input_sample)
bx.increment(inner_sample)
def increment(bx, input_sample):
bx._LHS_increment(input_sample)
def regen(bx):
#ё шайтан регенираци лэзьиз
bx._logger(msg='regeneration started')
bx._LHS_regen()
def _LHS_regen(bx):
# pro LHS_like_correction
bx.sorted_plan_U = [i for i in range(bx.nvar)] # just create list
for i in range(bx.nvar):
bx.sorted_plan_U[i] = np.concatenate(([0], np.sort(bx.sampled_plan.U[:, i]), [1]))
# LHS_style correction
def LHS_like_correction(bx, input_sample):
"""
returns sample object (f_model)
"""
# what is input?
# as we need transformation anyway,
# I'll ask for conversion to f sample
#ё Здесь вижу железную конвертацию до f-ка,
#ё которая пройдёт по R координатам
#č Kruci drát, tady by se nemohlo nic posrat
to_sample_node = bx.f_model.new_sample(input_sample)
LHS_node = np.empty(bx.nvar, dtype=float)
for i in range(bx.nvar):
if to_sample_node.U.flatten()[i] <= bx.sorted_plan_U[i][0]:
LHS_node[i] = (bx.sorted_plan_U[i][0] + bx.sorted_plan_U[i][1]) / 2
elif to_sample_node.U.flatten()[i] >= bx.sorted_plan_U[i][-1]:
LHS_node[i] = (bx.sorted_plan_U[i][-2] + bx.sorted_plan_U[i][-1]) / 2
else:
plan_index = np.searchsorted(bx.sorted_plan_U[i], to_sample_node.U.flatten()[i])
# vzdy
LHS_node[i] = (bx.sorted_plan_U[i][plan_index] + bx.sorted_plan_U[i][plan_index - 1]) / 2
return bx.f_model.new_sample(LHS_node, 'U')
def _LHS_increment(bx, input_sample):
for i in range(bx.nvar):
for j in range(len(input_sample)):
plan_index = np.searchsorted(bx.sorted_plan_U[i], input_sample.U[j,i])
bx.sorted_plan_U[i] = np.insert(bx.sorted_plan_U[i], plan_index, input_sample.U[j,i])
# The DiceBox Observer
def _logger(self, *args, msg="", indent=0, **kwargs):
if not kwargs:
kwargs = "" #č ať se nám prázdné závorky nezobrazujou
print(self.__class__.__name__ + ":", msg, *args, kwargs)
# inspired by Qt
def connect(self, slot): self._logger = slot
def disconnect(self): del(self._logger)
# kdyby něco
# callback = lambda *_, **__: None
# MinEnergyCensoredSampling
class Chrt(DiceBox):
#č už mě to dědění nebaví
#ё без поллитры было не разобраться, что этот слоёный пирог делал
def __init__(bx, sample_object, tri_space='Rn', tree_space=None,\
sampling_space=None, kechato_space='U', potencial='psee',\
p_norm=2, budget=1000, simplex_budget=100, \
LHS_correction=False, design=None):
bx.tri_space = tri_space
if tree_space is None:
bx.tree_space = tri_space
else:
bx.tree_space = tree_space
if sampling_space is None:
bx.sampling_space = tri_space
else:
bx.sampling_space = sampling_space
bx.kechato_space = kechato_space
bx.budget = budget
bx.simplex_budget = simplex_budget
bx.p_norm = p_norm
bx.potencial = potencial
bx.LHS_correction = LHS_correction
bx.design = design
# for current candidates
# kandidaty musí být 'judged' a 'assessed'
# viz. regen()
#bx.candidates_index = dict()
# krám, přece třidíme odpad!
bx.former_candidates = []
bx.unjudged_candidates = []
super().__init__(sample_object)
def init_parameters(bx):
"""
Returns dictionary of parameters the DiceBox was initialized with
"""
return {'sample_object':bx.sample_box, \
'tri_space':bx.tri_space, 'tree_space':bx.tree_space,\
'sampling_space':bx.sampling_space, 'kechato_space':bx.kechato_space,\
'potencial':bx.potencial, 'p_norm':bx.p_norm, 'budget':bx.budget,\
'simplex_budget':bx.simplex_budget, \
'LHS_correction':bx.LHS_correction, 'design':str(bx.design)}
def __repr__(bx):
return "%s(**%s)"%(bx.__class__.__name__, repr(bx.init_parameters()))
def __str__(bx):
return "%s(%s)"%(bx.__class__.__name__, str(bx.init_parameters()))
def get_events(bx, simplices=None):
"""
Metoda musí simplexům přiřazovat jev
0=success, 1=failure, 2=mix
"""
if simplices is None:
simplices = bx.tri.simplices
in_failure = np.isin(simplices, bx.failure_points)
has_failure = in_failure.any(axis=1)
all_failure = in_failure.all(axis=1)
return np.int8(np.where(has_failure, np.where(all_failure, 1, 2), 0))
def regen(bx):
"""
regen() recreates data structures of the box.
It shouldn't be called without reason, changed distribution, settings or so.
"""
#оӵ шайтан регенираци лэзьиз
bx._logger(msg='regeneration started')
bx._LHS_regen()
# kind of interface to CandidatesWidget
bx.candidates_index = dict()
if bx.nsim > 0:
# needed for potencial calculation
sampled_plan_tree = getattr(bx.sample_box, bx.tree_space)
bx.tree = spatial.cKDTree(sampled_plan_tree)
bx.highest_bid = 0
bx._regen_outside()
bx._regen_inside()
def _regen_outside(bx):
if bx.nsim >= bx.nvar + 1:
try:
bx.shull = sx.Shull(bx.f_model, bx.tri_space, bx.sampling_space,\
powerset_correction=True, design=bx.design)
bx.siss = bx.shull.oiss
bx.convex_hull = bx.shull.convex_hull # for gl_plot
bx.estimate_outside()
#č a máme hotovo
return # Ok, go away
except BaseException as e:
# I suppose ConvexHull to be much more stable
# (if compare with Delaunay triangulation).
# Hope no issues "we have triangulation, but not the hull" will occur here
msg = "error of creating ConvexHull "
error_msg = bx.__class__.__name__ + ": " + msg + repr(e)
bx._logger(msg=error_msg)
# nothing happened? We are still here?
# we need to generate at least something
if bx.nsim > 0: #č požaduji, aby nějaké těčíčky byly vždy pritomné
if bx.design is None:
nodes = bx.f_model(bx.budget)
else:
nodes = bx.f_model.new_sample(bx.design(bx.budget, bx.nvar), 'U')
#č současný CandyBox odmítne vytvořit neprazdný object bez atributů
candidates = CandyBox(nodes, event_id=np.full(bx.budget, -1, dtype=np.int8))
bx.assess_candidates(candidates)
#č uložíme
bx.candidates_index[-1] = candidates
def _regen_inside(bx):
#оӵ кылсузъет кылдытом
bx.simplex_stats = dict()
# create .tri triangulation
if bx.nsim > bx.nvar + 1: # incremental triangulation require one more point
try:
#č tri - Deloneho triangulace
tri_plan = getattr(bx.sampled_plan, bx.tri_space)
bx.tri = spatial.Delaunay(tri_plan, incremental=True)
if len(bx.tri.coplanar):
#print('triangulace v pořádku není')
bx._logger(msg='triangulation is coplanar')
else:
#print('triangulace je v pořádku')
bx._logger(msg='triangulation is OK')
#č vyhodil jsem simplex_id'y
bx.simplex_events = bx.get_events()
#č ty množiny jsou tak trošku overkill, ale budiž
bx.simplices_set = set()
for simplex in bx.tri.simplices:
# zde jen počítame
bx.estimate_simplex(simplex)
except BaseException as e:
#č chcu zachytit spadnuti QHull na začatku,
#č kdy ještě není dostatek teček.
#č Jinak je třeba nechat QHull spadnout
if bx.nsim > 2*bx.nvar + 3:
#č no to teda ne!
raise
else:
#č lze přípustit chybu triangulace
bx._logger(msg='triangulation failed')
#č beží 99% času
def increment(bx, input_sample):
#ё ну нахрен это ваше наследование-расследование
#č nechť bude, asi nikomu nevadí
bx._LHS_increment(input_sample)
#č strom posuneme sem
# cKDTree is used for potencial calculation
# we need everytime regenerate it
sampled_plan_tree = getattr(bx.sample_box, bx.tree_space)
bx.tree = spatial.cKDTree(sampled_plan_tree)
bx.highest_bid = 0
#č fór je v tom, že tu triangulaci nemůžeme výtvořit hned na začátku
#č a ConvexHull taky ne
#č tri - Deloneho triangulace
if ("tri" in dir(bx)) and ("shull" in dir(bx)):
bx.export_estimation()
bx._handle_changed_triangulation(input_sample)
bx._handle_changed_outside(input_sample)
bx._handle_candidates()
else:
bx._logger('Triangulace (zatím?) neexistuje')
bx.regen()
#č tato funkce běží 91% času
# bottleneck function
def _handle_changed_triangulation(bx, input_sample):
"""
Triangulace zajistěně existuje
"""
former_simplices = bx.tri.simplices
#č sample je jíž převeden na f (v .add_sample()), takže je to bezpěčný
bx.tri.add_points(getattr(input_sample, bx.tri_space))
bx.simplex_events = bx.get_events()
# print('increment se podaril')
if len(bx.tri.coplanar): # pokud triangulace není v pořadku
#print('triangulace v pořádku není')
bx._logger(msg='triangulation has coplanar points', coplanar=bx.tri.coplanar)
# zkontrolujeme co se změnilo
# předpokladám, že se počet simplexů přidaním bodů nezměnší
equal_mask = former_simplices == bx.tri.simplices[:len(former_simplices)]
#č zde spolehám na to, že pořadí indexů se nikdy nezmění
#č (dá se něco takovýho očekavát podle toho co jsem čet v dokumentaci)
#č u těch přečíslovaných zkolntrolujeme, zda fakt v té triangulaci nejsou
for simplex in former_simplices[~equal_mask.all(axis=1)]:
#č když tam je
#č každopadně tohle je rychlejší než přepočet spousty simplexů
#isin = np.any(np.all(np.isin(bx.tri.simplices, simplex),axis=1))
# few times faster
isin = (bx.tri.simplices == simplex).all(axis=1).any()
if not isin:
bx._invalidate_simplex(simplex)
# změněné simplexy přepočítáme
for simplex in bx.tri.simplices[:len(former_simplices)][~equal_mask.all(axis=1)]:
#č ty množiny jsou tak trošku overkill, ale budiž
if tuple(simplex) not in bx.simplices_set:
bx.estimate_simplex(simplex)
# teď nové simplexy
# simplexy свежего разлива
for simplex in bx.tri.simplices[len(former_simplices):]:
#č ty množiny jsou tak trošku overkill, ale budiž
if tuple(simplex) not in bx.simplices_set:
bx.estimate_simplex(simplex)
def _handle_changed_outside(bx, input_sample):
"""
Triangulace a ConvexHull zajistěně existujou
"""
# sample je jíž převeden na f (v .add_sample()), takže je to bezpěčný
bx.shull.increment(input_sample)
# handle changed outside
#č přepočíst -1 v zavislosti na simplexu vstupního bodu
try:
#č kontrola korrektní i v případě NaN
test = input_sample.event_id > -1
#оӵ эскером
if not test.all():
bx.former_candidates.append(bx.candidates_index.pop(-1))
bx.estimate_outside()
except BaseException as e:
msg = "input sample didn't provide correct 'event_id' attribute "
error_msg = bx.__class__.__name__ + ": " + msg + repr(e)
bx._logger(msg=error_msg)
bx.former_candidates.append(bx.candidates_index.pop(-1))
bx.estimate_outside()
def _handle_candidates(bx):
#č prohrabeme odpad
bx._judge_unjudged(bx.unjudged_candidates)
bx._judge_unjudged(bx.former_candidates)
#č A ještě... AUKCE, AUCTION
# Election - selection
for candidates in bx.candidates_index.values():
bids = getattr(candidates, bx.potencial)
if len(bids):
bid = np.nanmax(bids)
# side effect
if bid > bx.highest_bid:
#č pokud neprovadíme optimalizaci v simplexech
#č tak nám stačí jednoduše assessovat
bx.assess_candidates(candidates)
# probably, we shouldn't purge user candidates (if they are)
# just every time evaluate them
if len(bx.candidates) > 0:
bx.judge_candidates(bx.candidates)
bx.assess_candidates(bx.candidates)
def _nominate(bx, candidates):
"""
function should be only runned by .assess_candidates()
"""
bids = getattr(candidates, bx.potencial)
# -1 = 'out', 0=success, 1=failure, 2=mix
#č -1 a 2 jsou samozrejmě disjunktní
bids *= (candidates.event_id == -1) + (candidates.event_id == 2)
if len(bids):
bid = np.nanmax(bids)
# side effect
if bid > bx.highest_bid:
# já prečo spoléhám na ksee a psee potenciály
# v tom, že nepřířadí vysoký potenciál
# vzorkům s nulovou hustotou
bx.bidder = candidates[np.nanargmax(bids)]
bx.highest_bid = bid
def is_mixed(bx, simplices=None):
"""
Metoda musí simplexům přiřazovat jev
0=success, 1=failure, 2=mix
"""
if simplices is None:
simplices = bx.tri.simplices
in_failure = np.isin(simplices, bx.failure_points)
has_failure = in_failure.any(axis=1)
all_failure = in_failure.all(axis=1)
return np.logical_xor(has_failure, all_failure)
def __call__(bx):
bx._logger(msg="we were asked for an recommendation")
if bx.nsim < 1: # je to legální
bx._logger(msg="median first!")
return bx.LHS_like_correction(bx.f_model(1))
else:
selected = bx.bidder
if bx.LHS_correction:
#č hrubě ošidíme s takovejhlema usilima námi pěčlivě vybraný vzorečiček
selected.sampling_plan = bx.LHS_like_correction(selected)
return selected
def estimate_outside(bx):
# předpokládám, že convex_hull jíž existuje
# get candidates!
#č explicitně (pokažde) počtem teček zadavám přesnost integrace
#č takže změny bx.budget budou při dálším spuštění aplikovány
candidates = bx.shull.integrate(bx.budget)
candidates = candidates[candidates.is_outside]
#č vyhodnotíme
bx.assess_candidates(candidates)
#č vzorky je třeba přidát ke kandidatům
#č jako, nic nepokazí, ale čo tam připadně bylo - přepíše
# -1 = 'outside', 0=success, 1=failure, 2=mix
bx.candidates_index[-1] = candidates
# potřebuju nová slovesa
def assess_candidates(bx, candidates):
candidates.nsim_stamp = np.full(len(candidates), bx.nsim)
candidates_tree = getattr(candidates, bx.tree_space)
dd, ii = bx.tree.query(candidates_tree, k=1, p=bx.p_norm)
# from scipy documentation:
# [dd] Missing neighbors are indicated with infinite distances.
# [ii] Missing neighbors are indicated with self.n
#č mǐ radši budeme předpokladat nulovou vzdálenost a třeba nulového souseda
#č ne, radší posledného souseda
#č pokud ten chytrej strom si myslí, že nějaký kandidat nemá spolubydlu
mask = ii == bx.nsim
if np.any(mask): #č ať mě to neznervozňuje
ii[mask] = bx.nsim - 1
dd[mask] = 0
bx._logger(msg="cKDTree zlobí", orphan_candidates=candidates[mask])
candidates.dd = dd
candidates.ii = ii
if bx.potencial in ('psee', 'fee', 'fee2'):
#оӵ кучапи
#č pejskovej potenciál
#č psí-kučapí není invariántní vůči lineárním transformácím
PDFs = bx.sample_box.pdf(bx.tree_space)
# teď máme hustoty kandidatů a prislušejicích jím vzorků
PDF = PDFs[ii]
pdf = candidates.pdf(bx.tree_space)
candidates.tree_PDF = PDF
candidates.tree_pdf = pdf
#sampled_tree = getattr(bx.sample_box, bx.tree_space)
#mirrored_tree = candidates_tree*2
#mirrored_tree -= sampled_tree[ii] #č ušetříme aspoň kuseček paměti
#candidates.mirror_pdf = candidates.sample_pdf(mirrored_tree, bx.tree_space)
candidates.tree_Pdf_mean = (pdf+PDF)/2
candidates.tree_Pdf_gmean = np.sqrt(pdf*PDF)
candidates.volume = np.power(dd , bx.nvar)
candidates.psee = candidates.tree_Pdf_gmean * candidates.volume
#candidates.density = PDF + 4*pdf + candidates.mirror_pdf #pdf**2/PDF
candidates.fee = candidates.tree_Pdf_mean * candidates.volume * np.power(pdf/PDF, 1/(bx.nvar+1))
candidates.fee2 = candidates.tree_Pdf_mean * candidates.volume * np.power(pdf/PDF, 1/(bx.nvar*2))
elif bx.potencial == 'ksee': # ksee
#оӵ кечато
#č koťatko-káčátkovej potenciál
#č ksí-kěčató není invariántní vůčí rotacím
ksee = np.empty(len(candidates))
for i in np.unique(ii):
# doufám, že je to legální
ksee[i==ii] = lk.kechato_potential(bx.f_model[i], candidates[i==ii], kechato_space=bx.kechato_space)
candidates.ksee = ksee
# prepare to elections
bx._nominate(candidates)
def _judge_unjudged(bx, list):
for i in range(len(list)):
candidates = list.pop()
bx.shull.is_outside(candidates)
mask = candidates.is_outside
if np.any(mask): #č pokud aspoň jeden bydlí mimo Brno
candidates = candidates[mask]
#č shull event_id přiřadí
#candidates.event_id = np.full(len(candidates), -1, dtype=np.int8)
#č vyhodnotíme
bx.assess_candidates(candidates)
#č půlku prýč
bids = getattr(candidates, bx.potencial)
mask = np.isfinite(bids)
if np.any(mask): #č hmm...
candidates = candidates[mask]
bids = bids[mask]
median = np.median(bids, overwrite_input=False)#č bojím sa
candidates = candidates[bids > median]
#č vzorky je třeba přidát ke kandidatům
bx.candidates_index[-1].add_sample(candidates)
# ještě by asi hodily funkce pro pridaní uživatelských kandidatů
# funkce, která přídává dálší kandidaty? outside sampling
def get_pf_estimation(bx):
# TRI-compatible estimation
# -1=outside, 0=success, 1=failure, 2=mix
#č dostaneme vyrovnané odhady Brna-města (-2) a Brna-venkova (-1)
tri_estimation = dict()
tri_estimation[-1] = bx.siss.estimations[-1]
# set initial values
tri_estimation[0] = 0
tri_estimation[1] = 0
tri_estimation[2] = 0
#č něco konkretnějšího
vertex_estimation = 0
weighted_vertex_estimation = 0
pf_inside = bx.siss.estimations[-2]
if "tri" in dir(bx):
# let's iterate over all simplices we have
# (calling code is responsible for the .simplex_stats validity)
for event_id, simplex_measure, fm, wfm in bx.simplex_stats.values():
tri_estimation[event_id] += simplex_measure
vertex_estimation += fm
weighted_vertex_estimation += wfm
#č success klidně může být i záporným
tri_estimation[0] = pf_inside - tri_estimation[1] - tri_estimation[2]
elif np.all(bx.failsi[:len(bx.convex_hull.points)]):
#č veškerej vnitršek je v poruše
tri_estimation[1] = pf_inside
vertex_estimation = pf_inside
weighted_vertex_estimation = pf_inside
else:
#č vnitršek je asi v pořadku
tri_estimation[0] = pf_inside
return {'TRI_overall_estimations': tri_estimation, \
'vertex_estimation' : vertex_estimation, \
'weighted_vertex_estimation' : weighted_vertex_estimation}
def export_estimation(bx):
for key, value in bx.get_pf_estimation().items():
bx.guessbox.guess(key, len(bx.convex_hull.points), value) #č nebo bx.tri.npoints
#č vyhodil jsem simplex_id'y
def estimate_simplex(bx, indices):
#č zkusím funkci návrhnout tak, že
#ё вызывающая функция запускает estimate_simplex
#ё на всём подряд без разбору.
#č Našim úkolem je zjistit co je simplex zač
#č a ty zelené ignorovat
#č ty množiny jsou tak trošku overkill, ale budiž
bx.simplices_set.add(tuple(indices))
# I'll use tree_space as a weigthing space
# It could be separeted, but I am a little bit tired
# from so much different spaces over there
event, event_id, fr, wfr = sx.get_indices_event(bx, indices, bx.tree_space)
# -1 = 'outside', 0=success, 1=failure, 2=mix
if event_id != 0:
#оӵ чылкыт f_model
#č do sample_simplexu musíme poslat čístý f_model
# we should send pure f_model to sample_simplex()
vertices = bx.f_model[indices]
print("estimate", indices)
h_plan, convex_hull, simplex_measure = sx.sample_simplex(vertices,\
model_space=bx.tri_space, design=bx.design,\
sampling_space=bx.sampling_space, nis=bx.simplex_budget)
fm = simplex_measure * fr
wfm = simplex_measure * wfr
#č ISSI tu nemáme, místo toho prostě ukladáme co máme do slovníku
bx.simplex_stats[tuple(indices)] = (event_id, simplex_measure, fm, wfm)
mask = ~h_plan.is_outside
if event == 'mix':
candidates = h_plan[mask]
#bx._former_candidates_recovering(candidates, convex_hull, bx.unjudged_candidates)
bx._former_candidates_recovering(candidates, convex_hull, \
bx.former_candidates)
candidates.event_id = np.full(len(candidates), event_id, dtype=np.int8)
#candidates.simplex = np.full((len(candidates), bx.nvar+1), indices)
#č vyhodnotíme je
bx.assess_candidates(candidates)
#č vzorky je třeba přidát ke kandidatům
#č jako, nic nepokazí, ale čo tam připadně bylo - přepíše
bx.candidates_index[tuple(indices)] = candidates
#č vzorky je třeba přidát ke kandidatům
#č zás nakladaní s odpadem...
#bx.unjudged_candidates.append(h_plan[~mask])
#č roušky jsou dráhé
bx.unjudged_candidates.append(h_plan)
#č vyhodil jsem simplex_id'y
def _invalidate_simplex(bx, indices):
simplex = tuple(indices)
#č ten simplex tam musí být,
#č pokud teda bo boxu nikdo nesahá...
bx.simplices_set.remove(simplex)
if simplex in bx.simplex_stats:
bx.simplex_stats.pop(simplex)
if simplex in bx.candidates_index:
bx.former_candidates.append(bx.candidates_index.pop(simplex))
def _former_candidates_recovering(bx, actual, convex_hull, former_list):
#č prohrabeme odpad
for former in former_list:
former_tri = getattr(former, bx.tri_space)
mask = ~sx.is_outside(convex_hull, former_tri)
if np.any(mask): #č pokud aspoň jeden se nám hodí
#č vzorky je třeba přidát ke kandidatům
actual.add_sample(former[mask])
def judge_candidates(bx, candidates):
"""
Only for user candidates should be used
"""
candidates_tri = getattr(candidates, bx.tri_space)
found_simplices = bx.tri.find_simplex(candidates_tri)
candidates.simplex = found_simplices
events = found_simplices.copy()
# black magic
# zhruba - get_events() vrací pole s odpovidajícími čísly jevů pro každý simplex, počineje od nuly
# tím slajsingem my jakoby vybirame ke každemu nalezenemu simplexovi ten správnej mu odpovídajicí jev
events[found_simplices >= 0] = bx.simplex_events[found_simplices[found_simplices >= 0]]
candidates.event_id = events
#оӵ ӧрӟи
#č RJ
class Erjee(Chrt):
def _regen_inside(bx):
failsi = bx.failsi
if np.any(failsi) and not np.all(failsi):
#bx._logger(msg="triangulation started")
super()._regen_inside()
else:
#č jíž není nutný
#bx.simplex_stats = dict() # for .get_pf_estimation()
bx._logger(msg="triangulation skipped")
def increment(bx, input_sample):
#ё ну нахрен это ваше наследование-расследование
#č nechť bude, asi nikomu nevadí
bx._LHS_increment(input_sample)
#č strom posuneme sem
# cKDTree is used for potencial calculation
# we need everytime regenerate it
sampled_plan_tree = getattr(bx.sample_box, bx.tree_space)
bx.tree = spatial.cKDTree(sampled_plan_tree)
bx.highest_bid = 0
#č fór je v tom, že tu triangulaci nemůžeme výtvořit hned na začátku
#č a ConvexHull taky ne
#č tri - Deloneho triangulace
if ("tri" in dir(bx)) and ("shull" in dir(bx)):
bx.export_estimation()
bx._handle_changed_triangulation(input_sample)
bx._handle_changed_outside(input_sample)
bx._handle_candidates()
elif "shull" in dir(bx):
bx.export_estimation()
bx._regen_inside()
bx._handle_changed_outside(input_sample)
bx._handle_candidates()
else:
#bx._logger('Triangulace (zatím?) neexistuje')
#bx._logger('Konvexnej tvař (zatím?) neexistuje')
bx._logger("Neither triangulation, neither convex hull does not exist yet")
bx._regen_outside()
bx._regen_inside()
# MinEnergyCensoredSampling
class Razitko(Erjee):
#č už mě to dědění nebaví
#ё без поллитры было не разобраться, что этот слоёный пирог делал
def __init__(bx, sample_object, scheme, tri_space='Rn', tree_space=None,\
sampling_space=None, kechato_space='U', potencial='psee',\
p_norm=2, budget=1000, \
LHS_correction=False, design=None):
bx.scheme = scheme
bx.tri_space = tri_space
if tree_space is None:
bx.tree_space = tri_space
else:
bx.tree_space = tree_space
if sampling_space is None:
bx.sampling_space = tri_space
else:
bx.sampling_space = sampling_space
bx.kechato_space = kechato_space
bx.budget = budget
bx.p_norm = p_norm
bx.potencial = potencial
bx.LHS_correction = LHS_correction
bx.design = design
# for current candidates
# kandidaty musí být 'judged' a 'assessed'
# viz. regen()
#bx.candidates_index = dict()
# krám, přece třidíme odpad!
bx.former_candidates = []
bx.unjudged_candidates = []
DiceBox.__init__(bx, sample_object)
# přidávání vzorků musí bejt explicitní!
# def add_sample(bx, input_sample):
# bx._logger(msg="we have got new data:", data=input_sample)
# bx.sample_box.add_sample(input_sample)
# # tohle musí převest rozdělení vstupního vzorku na vlastní rozdělení skříňky
# #inner_sample = bx.sample_box.new_sample(input_sample)
# #bx.increment(inner_sample)
def init_parameters(bx):
"""
Returns dictionary of parameters the DiceBox was initialized with
"""
return {'sample_object':bx.sample_box, 'scheme':bx.scheme.name,\
'tri_space':bx.tri_space, 'tree_space':bx.tree_space,\
'sampling_space':bx.sampling_space, 'kechato_space':bx.kechato_space,\
'potencial':bx.potencial, 'p_norm':bx.p_norm, 'budget':bx.budget,\
'LHS_correction':bx.LHS_correction, 'design':str(bx.design)}
def _regen_inside(bx):
failsi = bx.failsi
if np.any(failsi) and not np.all(failsi):
#bx._logger(msg="triangulation started")
bx.__regen_inside()
else:
#č jíž není nutný
#bx.simplex_stats = dict() # for .get_pf_estimation()
bx._logger(msg="triangulation skipped")
def __regen_inside(bx):
# create .tri triangulation
if bx.nsim > bx.nvar + 1: # incremental triangulation require one more point
try:
# I'll use tri_space as a weigthing space
# It could be separeted, but I am a little bit tired
# from so much different spaces over there
bx.Tri = sx.FastCubatureTriangulation(bx.samplebox, bx.scheme,\
tri_space=bx.tri_space, issi=bx.siss, \
weighting_space=bx.tri_space, incremental=True,\
on_add_simplex=bx._on_add_simplex,\
on_delete_simplex=bx._invalidate_simplex)
bx.Tri.integrate()
#č tri - Deloneho triangulace
bx.tri = bx.Tri.tri #č všichní tam očekávajou QHull
except BaseException as e:
#č chcu zachytit spadnuti QHull na začatku,
#č kdy ještě není dostatek teček.
#č Jinak je třeba nechat QHull spadnout
if bx.nsim > 2*bx.nvar + 3:
#č no to teda ne!
raise
else:
#č lze přípustit chybu triangulace
bx._logger(msg='triangulation failed')
#č tato funkce běží 91% času
# bottleneck function
def _handle_changed_triangulation(bx, input_sample):
"""
Triangulace zajistěně existuje
"""
bx.Tri.update()
def get_pf_estimation(bx):
#č dle toho, čo vidím v kódu (spouští nás .increment())
#č přinejmenším konvexní obálka
#č zajištěně existuje
if 'tri' in dir(bx):
estimations = bx.Tri.get_pf_estimation()
tri_estimation = estimations.pop('TRI_estimation')
estimations['TRI_overall_estimations'] = tri_estimation
return estimations
#оӵ триангуляци ӧвӧл, иськем...
#č dostaneme vyrovnané odhady Brna-města (-2) a Brna-venkova (-1)
pf_inside = bx.siss.estimations[-2]
pf_outside = bx.siss.estimations[-1]
if np.all(bx.failsi[:len(bx.convex_hull.points)]):
#č veškerej vnitršek je v poruše
# -1=outside, 0=success, 1=failure, 2=mix
return {'TRI_overall_estimations': {-1:pf_outside, 0:0, 1:pf_inside, 2:0}, \
'vertex_estimation' : pf_inside, \
'weighted_vertex_estimation' : pf_inside}
else:
#č vnitršek je asi v pořadku
# -1=outside, 0=success, 1=failure, 2=mix
return {'TRI_overall_estimations': {-1:pf_outside, 0:pf_inside, 1:0, 2:0}, \
'vertex_estimation' : 0, \
'weighted_vertex_estimation' : 0}
#č bejvalej .estimate_simplex()
#č teď je to kolbek, který volá Triangulation
def _on_add_simplex(bx, box=None, indices=None, simplex=None, nodes=None, cell_stats=None):
if cell_stats['event'] == 'mix':
candidates = CandyBox(nodes, event_id=np.full(len(nodes), 2, dtype=np.int8))
#č vyhodnotíme je
bx.assess_candidates(candidates)
#č vzorky je třeba přidát ke kandidatům
#č jako, nic nepokazí, ale čo tam připadně bylo - přepíše
bx.candidates_index[tuple(indices)] = candidates
# callback
#č sx.on_delete_simplex(indices=indices)
def _invalidate_simplex(bx, indices):
simplex = tuple(indices)
if simplex in bx.candidates_index:
bx.candidates_index.pop(simplex)
def export_estimation(bx):
for key, value in bx.get_pf_estimation().items():
bx.guessbox.guess(key, len(bx.convex_hull.points), value) #č nebo bx.tri.npoints
class FullSimpleX:
def export_estimation(bx):
bx.siss.get_estimations()
simplices = np.array(tuple(bx.siss.estimations.keys()))
probabilities = np.array(tuple(bx.siss.estimations.values()))
estimation = dict()
estimation[-1] = np.sum(probabilities[simplices == -1])
# jevy aj klidně in-place (nerobím kopiju)
events = simplices[simplices != -1]
probabilities = probabilities[simplices != -1]
# zhruba - get_events() vrací pole s odpovidajícími čísly jevů pro každý simplex, počineje od nuly
# tím slajsingem my jakoby vybirame ke každemu nalezenemu simplexovi ten správnej mu odpovídajicí jev
events = bx.simplex_events[events]
for i in range(3): # kvůli 0,1,2 robiť cyklus?
estimation[i] = np.sum(probabilities[events == i])
bx.guessbox.guess('TRI_overall_estimations', bx.tri.npoints, estimation)
def estimate_simplex(bx, simplex_id):
"""
Delaunay triangulation
"""
#bx._logger(msg="estimate simplex"+str(simplex_id))
simplex = bx.tri.simplices[simplex_id]
# чылкыт f_model
vertices = bx.f_model[simplex]
# already divided by nsim in variance formule
# divide by /(nvar+1)/(nvar+2) from simplex inertia tensor solution
# multiply by simplex_volume, but it looks like it shouldn't be here
# for simplex: d = nvar+2
# sice to má nazev h_plan, ale nese rozdělení a hustoty v f-ku
h_plan = IS_stat.IS_like(vertices, sampling_space=bx.sampling_space, nis=bx.simplex_budget, d=bx.nvar+2)
# nejdřív vyfiltrujeme vzorky, pak budeme řešit hustoty
#
h_plan_model = getattr(h_plan, bx.tri_space)
vertices_model = getattr(vertices, bx.tri_space)
# budeme pokažde sestavovat triangulaci z jedného simplexu
# a rešit jen zda naši bodíky "inside or outside"
# (s narustajícím nsim tohle brzy se stavá rychlejším než bežný dotaz)
found_simplices = spatial.Delaunay(vertices_model).find_simplex(h_plan_model)
# ten simplex nic neznamená, asi nebudu jej použivat
h_plan.simplex = found_simplices
# uvnitř simplexu - mel by tam bejt pouze jeden, "nulový" simplex
mask = found_simplices == 0
# necháme ISSI trapit sa pravděpodobnostma
bx.siss.add_single_event_data(h_plan.w[mask], event=simplex_id, nis=bx.simplex_budget)
# je nejvyšší čas zjistit čo to byl za utvar
# fp like a failure points. Number of failure points
# intersect 2 times faster than setdiff (in my tests)
fp = len(np.intersect1d(simplex, bx.sample_box.failure_points, assume_unique=True))
# -1 = 'out', 0=success, 1=failure, 2=mix
if fp == bx.nvar + 1:
pass
#event = 'failure'
#event_id = 0
elif fp == 0:
pass
#event = 'success'
#event_id = 1
else:
#event = 'mix'
event_id = 2
candidates = h_plan[mask]
candidates.event = np.full(len(candidates), event_id, dtype=np.int8)
# a vyhodnotíme je
bx.assess_candidates(candidates)
# vzorky je třeba přidát ke kandidatům
# jako, nic nepokazí, ale čo tam připadně bylo - přepíše
bx.candidates_index[simplex_id] = candidates
# vzorky je třeba přidát ke kandidatům
# zás nakladaní s odpadem...
bx.unjudged_candidates.append(h_plan[~mask])
def _handle_candidates(bx):
# pokud -2 jíž existuje, tak pro dnešek stačí
if (-2 not in bx.candidates_index) and (len(bx.former_candidates) > 0):
# nikdo nám neslibil, že u starých kandidatu
# třeba se nebude zvýšovat potanciál
# (je to prostě, opravdu ríct, jednodušší)
# prohrabeme odpad
candidates = bx.former_candidates.pop()
for i in range(len(bx.former_candidates)):
candidates.add_sample(bx.former_candidates.pop())
for i in range(len(bx.unjudged_candidates)):
candidates.add_sample(bx.unjudged_candidates.pop())
# hodil by se ještě nám?
bx.judge_candidates(candidates)
# profiltrujeme
# -1 = 'out', 0=success, 1=failure, 2=mix
candidates = candidates[candidates.event != 0]
candidates = candidates[candidates.event != 1]
# uvalíme pokutu
bx.assess_candidates(candidates)
#č někoho z tyto hromady dostaneme
for __ in range((bx.nvar+1)*2):
if len(candidates) > 0:
mc_id = collections.Counter(candidates.simplex).most_common()[0][0]
#č uložíme
bx.candidates_index[mc_id].add_sample(candidates[candidates.simplex == mc_id])
#č a teď bacha - ty co jsem uložil do simplexu nechcu v -2 videt
candidates = candidates[candidates.simplex != mc_id]
else:
break
if len(candidates) > 0:
#č -2 je určen pro zbytky, кылем-мылем
bx.candidates_index[-2] = candidates
#č alternativní název je
#:) UltimateFastOptimizationOptimizedMinDistanceEnergyAdaptiveCensoringSampling
class DiceSimpleX:
#č rozdil je v chybejicích odhadéch
def _handle_changed_triangulation(bx, input_sample):
"""
Triangulace zajistěně existuje
"""
former_simplices = bx.tri.simplices
mixed = bx.is_mixed()
# sample je jíž převeden na f (v .add_sample()), takže je to bezpěčný
bx.tri.add_points(getattr(input_sample, bx.tri_space))
bx.simplex_events = bx.get_events()
# print('increment se podaril')
if len(bx.tri.coplanar): # pokud triangulace není v pořadku
#print('triangulace v pořádku není')
bx._logger(msg='triangulation has coplanar points')
# zkontrolujeme co se změnilo
# předpokladám, že se počet simplexů přidaním bodů nezměnší
equal_mask = former_simplices == bx.tri.simplices[:len(former_simplices)]
changed_simplices_ids = np.argwhere(~equal_mask.all(axis=1)).flatten()
#č popajem pouze mixy, ty musel jsem spočítat před aktualizací
for simplex_id in changed_simplices_ids[mixed[changed_simplices_ids]]:
bx.candidates_index.pop(simplex_id)
# pokud není splněná podmínka,
# tak nemáme jistotu, že se potenciály nezměni
# ani u kandidatů, které se nacházejí v pojíštěných státem buňkách
if (bx.tree_space != bx.tri_space) or (bx.p_norm != 2):
for candidates in bx.candidates_index.values():
bx.assess_candidates(candidates)
# změněné simplexy přepočítáme
for simplex_id in changed_simplices_ids:
bx.estimate_simplex(simplex_id)
# teď nové simplexy
# simplexy свежего разлива
for simplex_id in range(len(former_simplices), bx.tri.nsimplex):
# zde jen počítame
bx.estimate_simplex(simplex_id)
def _handle_candidates(bx):
#č prohrabeme odpad
bx._judge_unjudged(bx.unjudged_candidates)
bx._judge_unjudged(bx.former_candidates)
#č A ještě...
#
highest_bid = 0
for i, candidates in bx.candidates_index.items():
bids = getattr(candidates, bx.potencial)
bid = np.max(bids)
# side effect
if bid > highest_bid:
if np.any(candidates.nsim != bx.nsim):
if i == -1:
bx.assess_candidates(candidates)
else:
bx.estimate_simplex(i)
candidates = bx.candidates_index[i]
#š a eště ráz
bids = getattr(candidates, bx.potencial)
bid = np.max(bids)
if bid > highest_bid:
highest_bid = bid
else:
highest_bid = bid
#č pro kompatibilitu s bx.regen() rodičovské třidy
#č nechávám stejné názvy, ale žádný estimate tu nedělám
def estimate_simplex(bx, simplex_id):
simplex = bx.tri.simplices[simplex_id]
# fp like a failure points. Number of failure points
# intersect 2 times faster than setdiff (in my tests)
fp = len(np.intersect1d(simplex, bx.samplebox.failure_points, assume_unique=True))
#č hned na začátku odmítneme simplex,
#č pokud nevypadá jako stará Běloruská vlajka
if (fp > 0) and (fp < bx.nvar + 1):
# чылкыт f_model
vertices = bx.f_model[simplex]
vertices_model = getattr(vertices, bx.tri_space)
#č budeme pokažde sestavovat ConvexHull z jedného simplexu
#č a rešit jen zda naši bodíky "inside or outside"
#č (s narustajícím nsim tohle brzy se stavá rychlejším než bežný dotaz)
convex_hull = spatial.ConvexHull(vertices_model)
#č nepodařilo se mi ve FORTRANovém kódě Kobyly význat #ё(древние руны, блин)
#č a tak nevím jak přesně Kobyla sestavuje simplex.
#č Každopádně, jsme asi schopní nabídnout lepší "roběh",
#č než s tou implicitnou jedničkou.
x0 = np.mean(vertices_model, axis=0)
rhobeg = np.mean(np.abs(vertices_model - x0))
#print("roběh", rhobeg)
# catol - Tolerance (absolute) for constraint violations
# default value for catol is 0.0002
options = {'rhobeg': rhobeg, 'maxiter': bx.simplex_budget, 'disp': False, 'catol': 0}
constraints = six.get_COBYLA_constraints(convex_hull)
# as I can see, scipy treats 'tol' as 'rhoend'
# with default value tol=1e-4
#č jediný mechnizmus ukončení - vyčerpaní maximálního počtu iterací
res = optimize.minimize(bx.assess_candidate, x0, args=(), method='COBYLA', \
tol=0, constraints=constraints, options=options)
bx._logger("simplex %s optimization: %s" %(simplex_id, res))
#bx._logger(msg="estimate simplex"+str(simplex_id))
x_sample = bx.f_model.new_sample(res.x, bx.tri_space)
candidate = CandyBox(x_sample, event=[2])
#č a, kruci, je třeba zas je vyhodnotit
bx.assess_candidates(candidate)
# vzorky je třeba přidát ke kandidatům
# jako, nic nepokazí, ale čo tam připadně bylo - přepíše
bx.candidates_index[simplex_id] = candidate
def assess_candidate(bx, x):
"""
Objective function for optimalization
"""
if (bx.tri_space == bx.tree_space) and (bx.potencial == 'psee'):
x_tree = x
pdf = float(bx.f_model.sample_pdf(x, bx.tree_space))
else:#č máme smulu
x_sample = bx.f_model.new_sample(x, bx.tri_space)
x_tree = getattr(x_sample, bx.tree_space)
pdf = float(x_sample.pdf(bx.tree_space))
#č dd a ii budou prostě skalární hodnoty
dd, ii = bx.tree.query(x_tree, k=1, p=bx.p_norm)
PDFs = bx.sample_box.pdf(bx.tree_space)
# teď máme hustoty kandidatů a prislušejicích jím vzorků
PDF = PDFs[ii]
if bx.potencial == 'psee':
#оӵ кучапи
#č pejskovej potenciál
#č psí-kučapí není invariántní vůči lineárním transformácím
psee = -np.sqrt(pdf*PDF) * np.power(dd , bx.nvar)
#print(psee)
return psee
else: # ksee
#оӵ кечато
#č koťatko-káčátkovej potenciál
#č ksí-kěčató není invariántní vůčí rotacím
ksee = -float(lk.kechato_potential(bx.f_model[ii], x_sample, kechato_space=bx.kechato_space))
#print(ksee)
return ksee
#♥♥♥♥♥♥
# DiceBoxiCheck
class KechatoLukiskon(DiceBox):
def __init__(kl, sample_object, model_space='Rn', sampling_space=None, kechato_space='Rn', p_norm=1, gradient=None, budget=20000):
kl.model_space = model_space
kl.sampling_space = sampling_space
kl.kechato_space = kechato_space
kl.p_norm = p_norm
kl.gradient = gradient
kl.budget = budget
super().__init__(sample_object)
def __call__(kl):
kl._logger(msg="умой! Умойлэсь но умой сэмпл шедьтоно")
if (len(kl.failure_points) < 1) or (len(kl.success_points) < 1):
kl._logger(msg="Умоез сэмпл шедьтыны уг быгаты :( ")
return kl.LHS_like_correction(kl.h(1))
else:
kl.ivortodon = 0
kl.to_sample = None
# ty brdo, stm nedává číslo tečky. Nemusí, no...
kl.i = 0
stm.Voronoi_2_point_estimation(kl, model_space=kl.model_space, sampling_space=kl.sampling_space,\
p_norm=kl.p_norm, gradient=kl.gradient, budget=kl.budget, callback=kl.callback)
if kl.to_sample is not None:
# hrubě ošidíme s takovejhlema usilima námi pěčlivě vybraný vzorečiček
return kl.LHS_like_correction(kl.to_sample)
else:
kl._logger(msg="Умоез сэмпл шедьтыны ӧй быгаты :( ")
return kl.LHS_like_correction(kl.h(1))
def callback(kl, *args, **kwargs):
# spoléhám na to, že stm vrácí tečky v f-ku
nodes = kwargs['nodes']
node_pf = nodes.node_pf_estimations
mask = (node_pf > 0) * (node_pf < 1)
nodes = nodes[mask]
if len(nodes) > 0:
node_pf = node_pf[mask]
# !!!! ENTROPY !!!
nodes.entropy = -node_pf*np.log(node_pf) - (1-node_pf)*np.log(1-node_pf)
nodes.ksee = lk.kechato_potential(kl.f_model[kl.i], nodes, kechato_space=kl.kechato_space)
nodes.ivortodon = nodes.entropy * nodes.ksee
if np.max(nodes.ivortodon) > kl.ivortodon:
# side effects
kl.ivortodon = np.max(nodes.ivortodon)
kl.to_sample = nodes[np.argmax(nodes.ivortodon)]
# side effect
kl.i += 1
#♥♥♥♥♥♥♥♥♥♥♥♥
class KechatoTwoPointLukiskon(DiceBox):
def __init__(kl, sample_object, model_space='Rn', sampling_space=None, kechato_space='Rn', p_norm=1, gradient=None, budget=20000):
kl.model_space = model_space
kl.sampling_space = sampling_space
kl.kechato_space = kechato_space
kl.p_norm = p_norm
kl.gradient = gradient
kl.budget = budget
super().__init__(sample_object)
def __call__(kl):
kl._logger(msg="умой! Умойлэсь но умой сэмпл шедьтоно")
kl.candidates_index = {}
if (len(kl.failure_points) < 1) or (len(kl.success_points) < 1):
kl._logger(msg="Умоез сэмпл шедьтыны уг быгаты :( ")
return kl.LHS_like_correction(kl.h(1))
else:
kl.ivortodon = 0
kl.to_sample = None
# ty brdo, stm nedává číslo tečky. Nemusí, no...
kl.i = 0
stm.Voronoi_2_point_estimation(kl, model_space=kl.model_space, sampling_space=kl.sampling_space,\
p_norm=kl.p_norm, gradient=kl.gradient, budget=kl.budget, callback=kl.callback)
if kl.to_sample is not None:
# hrubě ošidíme s takovejhlema usilima námi pěčlivě vybraný vzorečiček
return kl.LHS_like_correction(kl.to_sample)
else:
kl._logger(msg="Умоез сэмпл шедьтыны ӧй быгаты :( ")
return kl.LHS_like_correction(kl.h(1))
def callback(kl, *args, **kwargs):
# spoléhám na to, že stm vrácí tečky v f-ku
nodes = kwargs['nodes']
node_pf = nodes.node_pf_estimations
mask = (node_pf > 0) * (node_pf < 1)
nodes = nodes[mask]
if len(nodes) > 0:
node_pf = node_pf[mask]
# !!!! ENTROPY !!!
nodes.entropy = -node_pf*np.log(node_pf) - (1-node_pf)*np.log(1-node_pf)
#nodes.ksee = lk.kechato_potential(kl.f_model[kl.i], nodes, kechato_space=kl.kechato_space)
#♥ кечато
#č ksí-kěčató není invariántní vůčí rotacím
ksee = np.empty(len(nodes))
ii2 = nodes.ii2
for ii in np.unique(nodes.ii2):
#č doufám, že je to legální
ksee[ii==ii2] = lk.kechato_potential(kl.f_model[[kl.i, ii]], nodes[ii==ii2], kechato_space=kl.kechato_space)
nodes.ksee = ksee
nodes.ivortodon = nodes.entropy * nodes.ksee
kl.candidates_index[kl.i] = nodes
if np.max(nodes.ivortodon) > kl.ivortodon:
#E side effects
kl.ivortodon = np.max(nodes.ivortodon)
kl.to_sample = nodes[np.argmax(nodes.ivortodon)]
#E side effect
kl.i += 1