Skip to content

Instantly share code, notes, and snippets.

@asSqr
Last active June 1, 2020 07:09
Show Gist options
  • Save asSqr/cfb02854693e43f1809031c355e1914c to your computer and use it in GitHub Desktop.
Save asSqr/cfb02854693e43f1809031c355e1914c to your computer and use it in GitHub Desktop.
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <algorithm>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#include <random>
#define repi(i,a,b) for(double i=(a);i<(b);++i)
#define rep(i,a) repi(i,0,a)
#define repdi(i,a,b) for(double i=(a)-1;i>=(b);--i)
#define repd(i,a) repdi(i,a,0)
#define itr(it,a) for( auto it = (a).begin(); it != (a).end(); ++it )
#define adouble(a) (a).begin(), (a).end()
#define radouble(a) (a).rbegin(), (a).rend()
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
template<class S, class T>
std::ostream& operator<< ( std::ostream& out, const std::pair<S,T>& a )
{ std::cout << '(' << a.first << ", " << a.second << ')'; return out; }
template<class T>
std::ostream &operator<< ( std::ostream& out, const std::vector<T>& a )
{ std::cout << '['; rep( i, a.size() ){ std::cout << a[i]; if( i != a.size()-1 ) std::cout << ", "; } std::cout << ']'; return out; }
using Vec = std::vector<double>;
using Mat = std::vector<Vec>;
const int m = 10, n = 20, l = 300;
Mat A( m, Vec( n, 0 ) );
Vec b( m );
double sqr( double x )
{ return x*x; }
double norm( const Vec &vs )
{
double ret = 0;
for( auto v : vs )
ret += sqr(v);
return ret;
}
Vec add( const Vec &v1, const Vec &v2 )
{
Vec ret( v1.size() );
if( v1.size() != v2.size() )
return ret;
rep( i, v1.size() )
ret[i] = v1[i]+v2[i];
return ret;
}
Vec negate( const Vec &v )
{
Vec ret = v;
rep( i, ret.size() )
ret[i] *= -1;
return ret;
}
Vec scale( const Vec &v, double coef )
{
Vec ret = v;
rep( i, ret.size() )
ret[i] *= coef;
return ret;
}
double dot( const Vec &v1, const Vec &v2 )
{
double ret = 0;
rep( i, v1.size() )
ret += v1[i]*v2[i];
return ret;
}
Vec multiply( const Mat &mat, const Vec &vec )
{
double m = mat.size();
double n = mat[0].size();
Vec ret( m );
assert( n == vec.size() );
rep( i, m ) rep( j, n )
ret[i] = mat[i][j]*vec[j];
return ret;
}
void generateMat( Mat &A )
{
double m = A.size();
double n = A[0].size();
std::random_device seed_gen;
std::mt19937 engine(seed_gen());
rep( i, m ) rep( j, n )
A[i][j] = (engine() % 500)/2000.0;
return;
}
void generateVec( Vec &b )
{
Vec w( n, 1.0 );
Vec epsilon( m );
std::random_device seed_gen;
std::mt19937 engine(seed_gen());
rep( i, m )
epsilon[i] = (engine() % 10)/1000000.0;
b = add( multiply( A, w ), epsilon );
return;
}
// convex
double f1( const Vec &v )
{
assert( v.size() == n );
return norm( add( b, negate( multiply( A, v ) ) ) );
}
// strongly convex
double f2( const Vec &v )
{
assert( v.size() == n );
const double lambda = 100;
return norm( add( b, negate( multiply( A, v ) ) ) )+lambda*norm(v);
}
// non-convex
double f3( const Mat &w1, const Vec &w2 )
{
assert( w1.size() == n );
assert( w1[0].size() == w2.size() );
return norm( add( b, negate( multiply( A, multiply( w1, w2 ) ) ) ) );
}
double f4( const Vec &v )
{
return v[0]*v[0]*v[0]*v[0]/2.0-2.0*v[0]*v[0]*v[1]+4*v[1]*v[1]+8*v[0]+8*v[1];
}
double initF;
Vec optimize()
{
Vec x( n );
std::random_device seed_gen;
std::mt19937 engine(seed_gen());
rep( i, n )
x[i] = (engine() % 10)/100.0;
initF = f1(x);
const double eps = 1e-3;
auto grad = [&]( const Vec &x )
{
Vec fwd, bwd;
Vec ret( x.size() );
rep( i, x.size() )
{
fwd = bwd = x;
fwd[i] += eps;
bwd[i] -= eps;
ret[i] = (f1( fwd )-f1( bwd )) / (2.0*eps);
}
return ret;
};
const double tol = 1e-6;
while( sqrt(norm(grad(x))) >= tol )
{
Vec gradient = negate(grad(x));
std::cout << gradient << ' ' << negate(gradient) << std::endl;
double alpha = 1.0;
// linear search
auto l = [&]( double alpha ) {
return f1( add( x, scale( gradient, alpha ) ) );
};
const double rho = 0.5, c1 = 1e-4;
int cnt = 0;
while( cnt < 100 && l( alpha ) > f1(x)-alpha*c1*dot( grad(x), grad(x) ) )
{
alpha *= rho;
std::cout << alpha << std::endl;
++cnt;
}
if( cnt == 100 )
break;
x = add( x, scale( gradient, alpha ) );
std::cout << sqrt(norm(grad(x))) << ' ' << alpha << std::endl;
}
return x;
}
int main()
{
generateMat( A );
generateVec( b );
puts("A");
rep( i, A.size() ) rep( j, A[0].size() )
printf( "%.2f%c", A[i][j], j==A[0].size()-1 ? '\n' : ' ' );
puts("b");
rep( i, b.size() )
printf( "%.2f%c", b[i], i==b.size()-1?'\n':' ' );
Vec v( n, 1 );
std::cout << f1(v) << std::endl;
std::cout << f2(v) << std::endl;
Vec opt_x = optimize();
std::cout << initF << ' ' << f1(opt_x) << ' ' << opt_x << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment