import sys
sys.dont_write_bytecode=True # no .pyc files
from models import *
from do import *

def saSchaffer():
  sa(model=Schaffer,p=1,kmax=100)
def saKursawe():
  "Controller for sa for Kursawe."
  sa(model=Kursawe,p=0.33,kmax=1000)
def saKursaweSlow():
  "Controller for sa for Kursawe."
  sa(model=Kursawe,p=0.1,kmax=1000)

def sa(model=Kursawe, p=The.sa.p, kmax=The.sa.kmax,
       epsilon=The.sa.epsilon, seed=The.math.seed,
       runs=The.sa.runs,
       stagger=The.sa.stagger,era=The.sa.era): 
  "Simulated annealing."
  def baseline(): 
    for _ in range(100): m.any() 
  def maybe(old,new,t): 
    return math.e**((old - new)*1.0/max(1,t)) < rand()
  def neighbor(lst):
    for h in m.t.nums:
      if rand() < p:
        lst[h.pos] = any(h.lo,h.hi)
    if m.valid(lst):
      return m.seen(lst)
    else:
      return lst
  #--------------------
  
  resetSeed(seed)
  for run,outer in do(range(runs)):
    say('.')
    m   = model()
    baseline()
    sb  = s = m.any()
    eb  = e = fromhell(s, m.t)
    for k,inner in do(range(kmax),
                      epsilon,"best",era,also=outer):
      sn = neighbor(s[:])
      en = fromhell(sn,m.t)
      if en > eb: 
        sb,eb = sn,en
      if en > e:
        s,e = sn,en
      elif maybe(e, en, k*1.0/kmax**stagger) :
        s,e = sn,en
      inner.seen(k, best=eb, every=e)
  done(outer, 0,1,
       key   = lambda z: '%2d'   % z,
       value = lambda z: '%4.2f' % z)

def bias(model=Kursawe,
           seed = The.math.seed,
           bins = The.issamp.bins,
           era  = The.issamp.era): 
  def num2bin(n,about):
    return int((n - about.lo)*1.0/about.div)
  def range2num(r):
    return any(r[0], r[1])
  def theDivs(model):
    tmp = model()
    for _ in range(era): tmp.any()
    out = {}
    for h in tmp.t.nums:
      div    = (h.hi - h.lo)*1.0/bins
      breaks = {}
      for bin in range(bins):
        lo = h.lo + bin*div
        breaks[bin] = (lo, lo+div)
      out[h.pos] = Thing(div=div,lo=h.lo,
                         hi=h.hi,breaks=breaks)
    return out
  #--------------------
  #resetSeed(seed)
  divs = theDivs(model)
  m    = model()
  bias = {}
  for _ in range(era):
    m.any()
    old = m.t.rows[-1]
    s = old.score()
    for h in m.t.nums:
      pos = h.pos
      n   = old.cells[pos]
      bin = num2bin(n,divs[pos])
      key = (pos,bin)
      bias[key] = bias.get(key,0) + s
  ordered = []
  for k in bias:
    ordered += [(bias[k],k)]
  ordered = sorted(ordered,reverse=True)
  for score,(pos,bin) in ordered[:5]:
    print "best",score,':pos',pos,':bin',bin
  for score,(pos,bin) in ordered[-5:]:
    print "worst",score,':pos',pos,':bin',bin
  plot2d([x for x in range(len(ordered))],
         [x[0] for x in ordered],
         xlabel="bins",
         ylabel="scores",
         title=m.name(),
         file="/home/timm/tmp/%s.png" % m.name())

@demo2
def scored():
  "show some scorings"
  resetSeed(1)
  m = Kursawe()
  for _ in range(30): m.any()
  out=[]
  for _ in range(20):
    s = m.any()
    e = fromhell(s,m.t)
    out += [(e,gs(s))]
  for one in sorted(out): print one

if __name__ == '__main__' : 
  eval(cmd('copyleft()'))
