mvc.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. from math import *
  2. import array
  3. import sys
  4. import random
  5. def run_mvc(k, k1, k2, k3, C, n = 100, do_print = False):
  6. cmd = 'moveto'
  7. result = array.array('d')
  8. cost = 0
  9. th = 0
  10. x = 0
  11. y = 0
  12. dt = 1.0 / n
  13. for i in range(n):
  14. k4 = -k * (k * k2 - .5 * k1 * k1 + C)
  15. cost += dt * k1 * k1
  16. x += dt * cos(th)
  17. y += dt * sin(th)
  18. th += dt * k
  19. k += dt * k1
  20. k1 += dt * k2
  21. k2 += dt * k3
  22. k3 += dt * k4
  23. result.append(k)
  24. if do_print: print 400 + 400 * x, 500 + 400 * y, cmd
  25. cmd = 'lineto'
  26. return result, cost, x, y, th
  27. def run_mec_cos(k, lam1, lam2, n = 100, do_print = False):
  28. cmd = 'moveto'
  29. result = array.array('d')
  30. cost = 0
  31. th = 0
  32. x = 0
  33. y = 0
  34. dt = 1.0 / n
  35. for i in range(n):
  36. k1 = lam1 * cos(th) + lam2 * sin(th)
  37. cost += dt * k * k
  38. x += dt * cos(th)
  39. y += dt * sin(th)
  40. th += dt * k
  41. k += dt * k1
  42. result.append(k)
  43. if do_print: print 400 + 400 * x, 500 + 400 * y, cmd
  44. cmd = 'lineto'
  45. return result, cost, x, y, th
  46. def descend(params, fnl):
  47. delta = 1
  48. for i in range(100):
  49. best = fnl(params, i, True)
  50. bestparams = params
  51. for j in range(2 * len(params)):
  52. ix = j / 2
  53. sign = 1 - 2 * (ix & 1)
  54. newparams = params[:]
  55. newparams[ix] += delta * sign
  56. new = fnl(newparams, i)
  57. if (new < best):
  58. bestparams = newparams
  59. best = new
  60. if (bestparams == params):
  61. delta *= .5
  62. print '%', params, delta
  63. sys.stdout.flush()
  64. params = bestparams
  65. return bestparams
  66. def descend2(params, fnl):
  67. delta = 20
  68. for i in range(5):
  69. best = fnl(params, i, True)
  70. bestparams = params
  71. for j in range(100000):
  72. newparams = params[:]
  73. for ix in range(len(params)):
  74. newparams[ix] += delta * (2 * random.random() - 1)
  75. new = fnl(newparams, i)
  76. if (new < best):
  77. bestparams = newparams
  78. best = new
  79. if (bestparams == params):
  80. delta *= .5
  81. params = bestparams
  82. print '%', params, best, delta
  83. sys.stdout.flush()
  84. return bestparams
  85. def desc_eval(params, dfdp, fnl, i, x):
  86. newparams = params[:]
  87. for ix in range(len(params)):
  88. newparams[ix] += x * dfdp[ix]
  89. return fnl(newparams, i)
  90. def descend3(params, fnl):
  91. dp = 1e-6
  92. for i in range(1000):
  93. base = fnl(params, i, True)
  94. dfdp = []
  95. for ix in range(len(params)):
  96. newparams = params[:]
  97. newparams[ix] += dp
  98. new = fnl(newparams, i)
  99. dfdp.append((new - base) / dp)
  100. print '% dfdp = ', dfdp
  101. xr = 0.
  102. yr = base
  103. xm = -1e-3
  104. ym = desc_eval(params, dfdp, fnl, i, xm)
  105. if ym > yr:
  106. while ym > yr:
  107. xl, yl = xm, ym
  108. xm = .618034 * xl
  109. ym = desc_eval(params, dfdp, fnl, i, xm)
  110. else:
  111. xl = 1.618034 * xm
  112. yl = desc_eval(params, dfdp, fnl, i, xl)
  113. while ym > yl:
  114. xm, ym = xl, yl
  115. xl = 1.618034 * xm
  116. yl = desc_eval(params, dfdp, fnl, i, xl)
  117. # We have initial bracket; ym < yl and ym < yr
  118. x0, x3 = xl, xr
  119. if abs(xr - xm) > abs(xm - xl):
  120. x1, y1 = xm, ym
  121. x2 = xm + .381966 * (xr - xm)
  122. y2 = desc_eval(params, dfdp, fnl, i, x2)
  123. else:
  124. x2, y2 = xm, ym
  125. x1 = xm + .381966 * (xl - xm)
  126. y1 = desc_eval(params, dfdp, fnl, i, x1)
  127. for j in range(30):
  128. if y2 < y1:
  129. x0, x1, x2 = x1, x2, x2 + .381966 * (x3 - x2)
  130. y0, y1 = y1, y2
  131. y2 = desc_eval(params, dfdp, fnl, i, x2)
  132. else:
  133. x1, x2, x3 = x1 + .381966 * (x0 - x1), x1, x2
  134. y1 = desc_eval(params, dfdp, fnl, i, x1)
  135. if y1 < y2:
  136. xbest = x1
  137. ybest = y1
  138. else:
  139. xbest = x2
  140. ybest = y2
  141. for ix in range(len(params)):
  142. params[ix] += xbest * dfdp[ix]
  143. print '%', params, xbest, ybest
  144. sys.stdout.flush()
  145. return params
  146. def mk_mvc_fnl(th0, th1):
  147. def fnl(params, i, do_print = False):
  148. k, k1, k2, k3, C = params
  149. ks, cost, x, y, th = run_mvc(k, k1, k2, k3, C, 100)
  150. cost *= hypot(y, x) ** 3
  151. actual_th0 = atan2(y, x)
  152. actual_th1 = th - actual_th0
  153. if do_print: print '%', x, y, actual_th0, actual_th1, cost
  154. err = (th0 - actual_th0) ** 2 + (th1 - actual_th1) ** 2
  155. multiplier = 1000
  156. return cost + err * multiplier
  157. return fnl
  158. def mk_mec_fnl(th0, th1):
  159. def fnl(params, i, do_print = False):
  160. k, lam1, lam2 = params
  161. ks, cost, x, y, th = run_mec_cos(k, lam1, lam2)
  162. cost *= hypot(y, x)
  163. actual_th0 = atan2(y, x)
  164. actual_th1 = th - actual_th0
  165. if do_print: print '%', x, y, actual_th0, actual_th1, cost
  166. err = (th0 - actual_th0) ** 2 + (th1 - actual_th1) ** 2
  167. multiplier = 10
  168. return cost + err * multiplier
  169. return fnl
  170. #ks, cost, x, y, th = run_mvc(0, 10, -10, 10, 200)
  171. #print '%', cost, x, y
  172. #print 'stroke showpage'
  173. def mvc_test():
  174. fnl = mk_mvc_fnl(-pi, pi/4)
  175. params = [0, 0, 0, 0, 0]
  176. params = descend3(params, fnl)
  177. k, k1, k2, k3, C = params
  178. run_mvc(k, k1, k2, k3, C, 100, True)
  179. print 'stroke showpage'
  180. print '%', params
  181. def mec_test():
  182. th0, th1 = pi/2, pi/2
  183. fnl = mk_mec_fnl(th0, th1)
  184. params = [0, 0, 0]
  185. params = descend2(params, fnl)
  186. k, lam1, lam2 = params
  187. run_mec_cos(k, lam1, lam2, 1000, True)
  188. print 'stroke showpage'
  189. print '%', params
  190. mvc_test()