1import c3py # import the python interface to the c3 library
2import numpy as np
3import matplotlib.pyplot as plt
4
5## Define two functions
6def func1(x,param=None):
7    return np.sum(x,axis=1)
8
9def func1_grad(x,param=None):
10    return np.ones(x.shape[1])
11
12def func2(x,param=None):
13    return np.sin(np.sum(x,axis=1))
14
15def func2_grad(x):
16    return np.cos(np.sum(x,axis=1))
17
18dim = 2                                # number of features
19ndata = 100                            # number of data points
20x = np.random.rand(ndata,dim)*2.0-1.0  # training samples
21y1 = func1(x)                          # function values
22y2 = func2(x)                          # ditto
23
24lb = -1                                # lower bounds of features
25ub = 1                                 # upper bounds of features
26nparam = 2                             # number of parameters per univariate function
27
28
29## Run a rank-adaptive regression routine to approximate the first function
30ft = c3py.FunctionTrain(dim)
31for ii in range(dim):
32    ft.set_dim_opts(ii,"legendre",lb,ub,nparam)
33ft.build_data_model(ndata, x, y1, alg="AIO", obj="LS", adaptrank=1,
34                    kickrank=1, roundtol=1e-10, verbose=0, store_opt_info=False)
35
36
37## Run a fixed-rank regression routine to approximate the second function with stochastic gradient descent
38ft_sgd = c3py.FunctionTrain(dim)
39ranks = [2]*(dim+1)
40ranks[0] = 1
41ranks[dim] = 1
42ft_sgd.set_ranks(ranks)
43for ii in range(dim):
44    ft_sgd.set_dim_opts(ii,"legendre",lb,ub,nparam)
45ft_sgd.build_data_model(ndata,x,y2,alg="AIO",obj="LS",opt_type="SGD",verbose=0)
46
47## Run a fixed-rank regression routine to approximate the second function
48ft2 = c3py.FunctionTrain(dim)
49ranks = [2]*(dim+1)
50ranks[0] = 1
51ranks[dim] = 1
52ft2.set_ranks(ranks)
53for ii in range(dim):
54    ft2.set_dim_opts(ii,"legendre",lb,ub,nparam)
55ft2.build_data_model(ndata,x,y2,alg="AIO",obj="LS",verbose=0)
56
57# ## Select number of parameters through cross validation
58# # ftcv = c3py.FunctionTrain(dim)
59# # ranks = [4]*(dim+1)
60# # ranks[0] = 1
61# # ranks[dim] = 1
62# # ftcv.set_ranks(ranks)
63# # for ii in range(dim):
64# #     ftcv.set_dim_opts(ii,"legendre",lb,ub,nparam)
65# # ftcv.build_data_model(ndata,x,y2,alg="AIO",obj="LS_SPARSECORE",\
66# #                       cvregweight=[1e-10,1e-8,1e-6,1e-4],kfold=3,verbose=0,cvverbose=2)
67
68
69ft3 = ft + ft2  # add two function-trains
70ft4 = ft * ft2  # multiply to function-trains
71
72## Run adaptive sampling scheme
73ft_adapt = c3py.FunctionTrain(dim)
74for ii in range(dim):
75    ft_adapt.set_dim_opts(ii,"legendre",lb,ub,nparam)
76verbose=0
77init_rank=2
78adapt=1
79ft_adapt.build_approximation(func2,None,init_rank,verbose,adapt)
80
81ft_lin_adapt = c3py.FunctionTrain(dim)
82for ii in range(dim):
83    ft_lin_adapt.set_dim_opts(ii,"linelm",lb,ub,80)
84verbose=0
85init_rank=2
86adapt=1
87ft_lin_adapt.build_approximation(func2,None,init_rank,verbose,adapt)
88
89
90
91ft.save("saving.c3")
92ft_load = c3py.FunctionTrain(0)
93ft_load.load("saving.c3")
94## Generate test point
95test_pt = np.random.rand(dim)*2.0-1.0
96
97
98print("\n\n\n")
99
100print("test_pt = ", test_pt)
101grad = ft.grad_eval(test_pt)
102grad_should = func1_grad(test_pt.reshape((1,dim)))
103print("Grad = ", grad)
104print("should be = ",grad_should)
105
106print("\n\n\n")
107
108
109ft1eval = ft.eval(test_pt) # evaluate the function train
110floadeval = ft_load.eval(test_pt) # evaluate the function train
111ft2eval = ft2.eval(test_pt)
112ft_sgd_eval = ft_sgd.eval(test_pt)
113# ftcveval = ftcv.eval(test_pt)
114ft3eval = ft3.eval(test_pt)
115ft4eval = ft4.eval(test_pt)
116ft_adapt_eval = ft_adapt.eval(test_pt)
117ft_lin_adapt_eval = ft_lin_adapt.eval(test_pt)
118
119eval1s = func1(test_pt.reshape((1,dim)))
120eval2s = func2(test_pt.reshape((1,dim)))
121eval3s = eval1s + eval2s
122eval4s = eval1s * eval2s
123
124
125print("Fteval =",ft1eval, "Should be =",eval1s)
126print("Ft_loadeval =",floadeval, "Should be =",eval1s)
127print("Second function with BFGS: Fteval =",ft2eval, "Should be =",eval2s)
128print("Second function with SGD:  Fteval =",ft_sgd_eval, "Should be =",eval2s)
129print("Second function with CrossApproximation:  Fteval =",ft_adapt_eval, "Should be =",eval2s)
130print("Second function with CrossApproximation and linear elements:  Fteval =",ft_lin_adapt_eval, "Should be =",eval2s)
131# print("Second function with CV:   Fteval =",ftcveval, "Should be =",eval2s)
132print("Fteval =",ft3eval, "Should be =",eval3s)
133print("Fteval =",ft4eval, "Should be =",eval4s)
134
135
136print("\n\n\n")
137print("Now getting optimization trajectories, run interactively and then type plt.show()")
138
139dim = 5                                # number of features
140ndata = 10000                          # number of data points
141x = np.random.rand(ndata,dim)*2.0-1.0  # training samples
142y1 = func2(x) + np.random.randn(ndata)*0.01  # function values
143
144lb = -1                                # lower bounds of features
145ub = 1                                 # upper bounds of features
146nparam = 10                            # number of parameters per univariate function
147
148ranks = [2]*(dim+1)
149ranks[0] = 1
150ranks[dim] = 1
151
152ft = c3py.FunctionTrain(dim)
153ft.set_ranks(ranks)
154for ii in range(dim):
155    ft.set_dim_opts(ii,"legendre",lb,ub,nparam)
156opt_ft = ft.build_data_model(ndata, x, y1, alg="AIO", obj="LS", adaptrank=0, verbose=0, store_opt_info=True)
157
158ft_sgd = c3py.FunctionTrain(dim)
159ft_sgd.set_ranks(ranks)
160for ii in range(dim):
161    ft_sgd.set_dim_opts(ii,"legendre",lb,ub,nparam)
162opt_sgd = ft_sgd.build_data_model(ndata, x, y1, alg="AIO", obj="LS",
163                                  opt_type="SGD", opt_sgd_learn_rate=1e-4,
164                                  adaptrank=0, verbose=0, opt_maxiter=100, store_opt_info=True)
165
166ft_als = c3py.FunctionTrain(dim)
167ft_als.set_ranks(ranks)
168for ii in range(dim):
169    ft_als.set_dim_opts(ii,"legendre",lb,ub,nparam)
170opt_als = ft_als.build_data_model(ndata, x, y1, alg="ALS", obj="LS",
171                                  adaptrank=0, verbose=0,  store_opt_info=True)
172
173
174plt.figure()
175plt.plot(np.log10(opt_ft), label='AIO')
176plt.plot(np.log10(opt_sgd), label='SGD')
177plt.plot(np.log10(opt_als), label='ALS')
178# plt.semilogy(opt_als, label='ALS')
179plt.legend()
180
181
182# Test serialization
183
184
185# clean up memory for each function train
186# ft.close()
187# ft2.close()
188# ft_sgd.close()
189# ft3.close()
190# ft4.close()
191
192
193