#
# identical to backprop.pl, using pytorch
#

import torch
from random import random

# generate "test" data (a "known" model, Y = 23 - 50*X).

X = []
Y = []
for _ in range(100):
 x = (random()-0.5)*10
 y = 23 + -50 * x
 X.append(torch.tensor([x]))
 Y.append(torch.tensor([y]))

# these are the weights.
w1 = torch.randn(1)
w1.requires_grad=True

w2 = torch.randn(1)
w2.requires_grad=True

# do gradient descent.
last = torch.tensor([999999.0]);
for _ in range(100):
  lst = []
  for i in range(len(X)):
    y = w1 + w2 * X[i]
    e = (y - Y[i])**2
    lst.append(e)
  a = sum(lst)
  if (a - last)**2 < 0.001:
    break  # exit if stopped improving
  last = a 
  a.backward()  
  print(f"vals: w1={w1}, w2={w2}, err={a}, w1.grad={w1.grad}, w2.grad={w2.grad}")
  with torch.no_grad():  # turn off gradient tracking
    w1 -= 0.001 * w1.grad
    w2 -= 0.001 * w2.grad
  w1.grad.zero_()
  w2.grad.zero_()


