# Regression4.py

import time

# Set of samples [x1, x2, y]
# Used car price [years, km /1000, price SFr/1000]
samples = [[5, 57, 8.5], [4, 40, 10.3], [6, 77, 7], [5, 60, 8.2], 
           [5, 49, 8.9], [5, 47, 9.8], [6, 58, 6.6], [6, 39, 9.5], 
           [2, 8, 16.9], [7, 69, 7], [7, 89, 4.8]]
# Iteration step in both directions
ds = 0.00001

def f(x1, x2):
    return a1*x1 + a2*x2 + a0

def error():
    e = 0
    for sample in samples:
        de = (f(sample[0], sample[1]) - sample[2])**2 
        e += de
    return e
    
def gradient_a1():
    # Derivative with respect to a1
    s = 0 
    for sample in samples:
        x1i = sample[0]
        x2i = sample[1]
        yi = sample[2]
        s += (f(x1i, x2i) - yi) * x1i  
    return 2 * s

def gradient_a2():
    # Derivative with respect to a2
    s = 0 
    for sample in samples:
        x1i = sample[0]
        x2i = sample[1]
        yi = sample[2]
        s += (f(x1i, x2i) - yi) * x2i  
    return 2 * s

def gradient_a0():
    # Derivative with respect to a0
    s = 0
    for sample in samples:
        x1i = sample[0]
        x2i = sample[1]
        yi = sample[2]
        s += (f(x1i, x2i) - yi)  
    return 2 * s

# Start values
a1 = 0
a2 = 0
a0 = 0
iterationNb = 0
print "Learning now. Please wait..."
for i in range(500000): 
    iterationNb += 1
    a1new = a1 - ds * gradient_a1() # descent in a1 direction   
    a2new = a2 - ds * gradient_a2() # descent in a2 direction
    a0new = a0 - ds * gradient_a0() # descent in a0 direction   
    # updata a1, a2, a0
    a1 = a1new
    a2 = a2new
    a0 = a0new
    if iterationNb % 100000 == 0:
        print "%3d iters-> a1 a2 a0: %4.2f %4.2f %4.2f -- Error: %4.2f " \
               %(iterationNb, a1, a2, a0, error())
print "Learnig process terminated"
print "Prediction for a 7-years old car with 60'000 km:", \
       int(1000 * f(7, 60)), "SFr" 
