Skip to content

Instantly share code, notes, and snippets.

@janisozaur
Created December 4, 2011 23:08
Show Gist options
  • Save janisozaur/1431587 to your computer and use it in GitHub Desktop.
Save janisozaur/1431587 to your computer and use it in GitHub Desktop.
coś function
#include "Cos.h"
Cos::Cos(int _r, int _n) :
mR(_r), mN(_n)
{
}
void Cos::init(int _r, int _n)
{
mR = _r;
mN = _n;
}
QVector<float> Cos::calculateVec(const FeatureVector *vector, const QVector<float> &params) const
{
QVector<float> ret_vec(mN);
QVector<float> tmpvector = multiplication(vector);
int offset = 0;
for(int i = 0; i < mN; i++)
{
for(int j = 0; j < tmpvector.size(); j++)
{
ret_vec[i] += params.at(offset++) * tmpvector.at(j);
}
}
return ret_vec;
}
FeatureVector *Cos::calculate(const FeatureVector *vector, const QVector<float> &params) const
{
QVector<float> ret_vec = calculateVec(vector, params);
FeatureVector *result = new FeatureVector(ret_vec.size());
for (int i = 0; i < ret_vec.size(); i++) {
(*result)[i] = ret_vec.at(i);
}
return result;
}
QVector<float> Cos::multiplication(const FeatureVector *features) const
{
int N = features->length();
int new_length = howManyElements(N, mR);
QVector<float> ret_vec(new_length);
for( int z = 1; z <= mR; z++)
{
//cout<< "test numer "<<z<<endl;
int *positions = new int[z];
memset(positions, 0, z * sizeof(int));
advance(positions, 0, 0, z, features, ret_vec);
delete [] positions;
}
return ret_vec;
}
QVector<float> Cos::multiplication2(const QVector<float> &features) const
{
QVector<float> ret_vec;
int N= features.size();
int new_length = howManyElements(N,mR);
ret_vec.resize(new_length);
for( int z =1; z<=mR; z++){
//cout<< "test numer "<<z<<endl;
int *positions = new int[z];
memset(positions, 0, z*sizeof(int));
advance(positions, 0, 0, z, features, ret_vec);
delete [] positions;
}
return ret_vec;
}
void Cos::advance(int *positions, const int &k, const int &j, const int &x,
const FeatureVector *features, QVector<float> &ret_vec) const
{
if(j == x)
{
float a=1;
// cout << p << ". ";
for(int i = 0; i < x; i++)
{
// cout << ' ' << positions[i];
a=a*(*features)[positions[i]].re();
if(i+1 == x) {
ret_vec.append(a);
}
//cout<<"\t wynik mnożenia to: "<<a;
//cout << endl;
//p++;
return;
}
for(quint32 l = k; l < features->length(); l++)
{
positions[j] = l;
advance(positions, l, j + 1, x, features, ret_vec);
}
}
}
void Cos::advance(int *positions, const int &k, const int &j, const int &x,
const QVector<float> &features, QVector<float> &ret_vec) const
{
if(j == x)
{
float a=1;
//cout << p << ". ";
for(int i = 0; i < x; i++){
//cout << ' ' << positions[i];
a=a*features.at(positions[i]);
if(i+1 == x) {
ret_vec.append(a);
}
//cout << endl;
//p++;
return;
}
for(int l = k; l < features.size(); l++)
{
positions[j] = l;
advance(positions, l, j + 1, x, features, ret_vec);
}
}
}
int Cos::factorial(const int &n) const
{
int z =1;
for(int i=1;i<=n;i++)
{
z=z*i;
}
return z;
}
int Cos::howManyElements(const int &n, const int &k) const
{
int z=0;
for(int i=1;i<=k;i++){
int suma = (factorial(n+i-1)) / (factorial(i) * factorial(n-1));
z=z+suma;
}
return z;
}
int Cos::n() const
{
return mN;
}
#ifndef COS_H
#define COS_H
#include "FeatureVector.h"
#include <QVector>
class Cos
{
private:
int mR;
int mN;
public:
Cos(int mR = 0, int mN = 0);
void init(int r, int n);
QVector<float> calculateVec(const FeatureVector *vector, const QVector<float> &params) const; // funkcja saka
FeatureVector *calculate(const FeatureVector *vector, const QVector<float> &params) const; // funkcja saka zwracająca fv
QVector<float> multiplication(const FeatureVector *features) const; // funkcja marcina
QVector<float> multiplication2(const QVector<float> &features) const;//funkcja do mnożenia ale na wektorze floatów
int factorial(const int &n) const;//silnia
int howManyElements(const int &n, const int &k) const;//funkcja obliczająca ile elementów ma mieć wektor wyjściowy kombinacji z powtórzeniami
void advance(int *positions, const int &k, const int &j, const int &x, const QVector<float> &features, QVector<float> &ret_vec) const;
void advance(int *positions, const int &k, const int &j, const int &x, const FeatureVector *features, QVector<float> &ret_vec) const;
int n() const;
};
#endif // COS_H
#include "CosOptimizer.h"
#include "CosQualityFunction.h"
#include "IFeatureExtractor.h"
#include "ExtractorFactory.h"
#include "Cos.h"
#include "Vertex.h"
#include <QPointer>
#include <cmath>
#include <QDebug>
#include <cfloat>
CosOptimizer::CosOptimizer(const QString &extractorName,
const QStringList &parameters,
const SurveyResults *results, const Cos *cos,
uint iterations, float reflection, float expansion,
float contraction, float reduction) :
m_bestResult(1), m_iterations(iterations), m_reflection(reflection), m_expansion(expansion),
m_contraction(contraction), m_reduction(reduction)
{
IFeatureExtractor * extractor = 0;
extractor = ExtractorFactory::get(extractorName, parameters);
if(extractor == 0)
qCritical()<< QString("Error while creating extractor");
m_vectorSize = cos->n();
m_qualityFunction = new CosQualityFunction(results, extractor);
m_startingPoints.resize(m_vectorSize + 1);
for(uint i = 0; i <= m_vectorSize; i++)
{
m_startingPoints[i].resize(m_vectorSize);
for(uint j = 0; j < m_vectorSize; j++)
m_startingPoints[i][j] = (float)qrand() / (float)RAND_MAX * 2.0f - 1.0f;
}
}
CosOptimizer::~CosOptimizer()
{
delete m_qualityFunction;
}
QVector<float> CosOptimizer::optimize(int passes, float &minError)
{
minError = FLT_MAX;
QVector<float> result = m_bestResult;
for(int i = 0; i < passes; i++)
{
for(uint j = 0; j <= m_vectorSize; j++)
for(uint k = 0; k < m_vectorSize; k++)
m_startingPoints[j][k] = (float)qrand() / (float)RAND_MAX * 2.0f - 1.0f;
optimize();
float error = m_qualityFunction->evaluate(m_bestResult);
qDebug()<<error;
if(error < minError)
{
minError = error;
result = m_bestResult;
}
}
return result;
}
void CosOptimizer::optimize()
{
QVector<QPointer<Vertex> > simplex(m_vectorSize + 1);
for(uint i = 0; i <= m_vectorSize; i++)
{
simplex[i] = new Vertex(m_vectorSize);
for(uint j = 0; j < m_vectorSize; j++) {
simplex[i]->p[j] = (float)qrand() / (float)RAND_MAX * 2.0f - 1.0f;
}
simplex[i]->p = m_startingPoints.at(i);
simplex[i]->f = m_qualityFunction->evaluate(simplex[i]->p);
}
Vertex center(m_vectorSize), reflected, expanded, contracted;
uint iteration = 0;
while(iteration < m_iterations)
{
qSort(simplex);
// obliczenie srodka ciezkosci
center.zeros();
for(uint i = 0; i < m_vectorSize; i++)
center = center + (*simplex[i]);
center = (1.0f / (float)m_vectorSize) * center;
// odbicie
reflected = center + m_reflection * (center - (*simplex[m_vectorSize]));
reflected.f = m_qualityFunction->evaluate(reflected.p);
if(reflected.f < simplex[m_vectorSize - 1]->f)
{
if(reflected.f < simplex[0]->f)
{
// ekspansja
expanded = center + m_expansion * (center - (*simplex[m_vectorSize]));
expanded.f = m_qualityFunction->evaluate(expanded.p);
if(expanded.f < reflected.f)
(*simplex[m_vectorSize]) = expanded;
else
(*simplex[m_vectorSize]) = reflected;
}
else
{
(*simplex[m_vectorSize]) = reflected;
}
}
else
{
contracted = (*simplex[m_vectorSize]) + m_contraction * (center - (*simplex[m_vectorSize]));
contracted.f = m_qualityFunction->evaluate(contracted.p);
if(contracted.f < simplex[m_vectorSize]->f)
(*simplex[m_vectorSize]) = contracted;
else
// redukcja
for(uint i = 1; i <= m_vectorSize; i++)
(*simplex[i]) = (*simplex[0]) + m_reduction * ((*simplex[i]) - (*simplex[0]));
}
float d = simplex[0]->distance(*simplex[m_vectorSize]);
for(uint i = 0; i < m_vectorSize; i++)
d += simplex[i]->distance(*simplex[i + 1]);
if(d < 0.01)
iteration = m_iterations;
else
iteration++;
}
center.zeros();
for(uint i = 0; i <= m_vectorSize; i++)
center = center + (*simplex[i]);
center = (1.0f / (m_vectorSize + 1.0f)) * center;
m_bestResult = center.p;
for(uint i = 0; i <= m_vectorSize; i++)
delete simplex[i];
}
void CosOptimizer::setStartingPoints(const QVector<QVector<float> > &startingPoints)
{
m_startingPoints = startingPoints;
}
QVector<float> CosOptimizer::bestResult() const
{
return m_bestResult;
}
CosQualityFunction* CosOptimizer::qualityFunction() const {
return m_qualityFunction;
}
#ifndef COSOPTIMIZER_H
#define COSOPTIMIZER_H
#include <QString>
#include <QVector>
#include <QStringList>
#include "SurveyResults.h"
class CosQualityFunction;
class Cos;
class CosOptimizer {
public:
CosOptimizer(const QString &extractorName, const QStringList &parameters,
const SurveyResults* results, const Cos *cos,
uint iterations = 100, float reflection = 0.1,
float expansion = 0.2, float contraction = 0.05f,
float reduction = 0.05);
~CosOptimizer();
void optimize();
QVector<float> optimize(int passes, float &minError);
QVector<float> bestResult() const;
void setStartingPoints(const QVector<QVector<float> > &startingPoints);
CosQualityFunction* qualityFunction() const;
private:
CosQualityFunction * m_qualityFunction;
QVector<float> m_bestResult;
uint m_vectorSize;
uint m_iterations;
float m_reflection, m_expansion, m_contraction, m_reduction;
QVector<QVector<float> > m_startingPoints;
};
#endif // COSOPTIMIZER_H
#include "CosQualityFunction.h"
#include "SurveyResults.h"
#include "Cos.h"
#include <cmath>
#include <cfloat>
#include <QDebug>
#include <QPointF>
#include <QPair>
#include <QFile>
#include <QTextStream>
CosQualityFunction::CosQualityFunction(const SurveyResults *_results,
IFeatureExtractor *_extractor,
const Cos *cos) :
results(_results),
extractor(_extractor),
mCos(cos)
{
}
float CosQualityFunction::distance(const FeatureVector &first, const FeatureVector &second) const
{
if(first.length() != second.length())
return FLT_MAX;
double result = 0.0f;
for(quint32 i = 0; i < first.length(); i++)
{
double d = (first[i].re() - second[i].re());
d *= d;
result += d;
}
return sqrt(result);
}
float CosQualityFunction::evaluate(const QVector<float> &params) {
QList<QPair<QString, QString> > shapePairs = results->getShapePairs();
distances.clear();
QPair<QString, QString> p;
foreach(p, shapePairs) {
Shape* shapeA = results->getShape(p.first);
Shape* shapeB = results->getShape(p.second);
float surveySimilarity = results->getShapePairSimilarity(p);
FeatureVector* featureVectorA = extractor->extract(shapeA);
FeatureVector* featureVectorB = extractor->extract(shapeB);
FeatureVector *fvA = mCos->calculate(featureVectorA, params);
FeatureVector *fvB = mCos->calculate(featureVectorB, params);
float dist = distance(*fvA, *fvB);
delete featureVectorA;
delete featureVectorB;
delete fvA;
delete fvB;
QPointF res(surveySimilarity, dist);
distances.push_back(res);
}
double a,b;
return leastSquares(a,b);
}
void CosQualityFunction::dumpResults(QString filename, const QVector<float> &params) {
QFile file(filename);
file.open(QFile::WriteOnly);
QTextStream stream(&file);
QList<QPair<QString, QString> > shapePairs = results->getShapePairs();
double a,b;
leastSquares(a,b);
QPair<QString, QString> p;
foreach(p, shapePairs) {
Shape* shapeA = results->getShape(p.first);
Shape* shapeB = results->getShape(p.second);
float surveySimilarity = results->getShapePairSimilarity(p);
FeatureVector* featureVectorA = extractor->extract(shapeA);
FeatureVector* featureVectorB = extractor->extract(shapeB);
FeatureVector *fvA = mCos->calculate(featureVectorA, params);
FeatureVector *fvB = mCos->calculate(featureVectorB, params);
float dist = distance(*fvA, *fvB);
delete featureVectorA;
delete featureVectorB;
delete fvA;
delete fvB;
QPointF res(surveySimilarity, dist);
stream<<res.x()<<" "<<res.y()<<" "<<res.x()*a+b<<endl;
}
file.close();
}
float CosQualityFunction::leastSquares(double& a, double& b) {
int n = distances.count();
double S, Sx, Sy, Sxx, Sxy, Syy;
S=Sx=Sy=Sxx=Sxy=Syy=0.0;
S = n;
for(int i=0;i<n;i++) {
Sx += distances.at(i).x();
Sy += distances.at(i).y();
Sxx += distances.at(i).x()*distances.at(i).x();
Sxy += distances.at(i).x()*distances.at(i).y();
Syy += distances.at(i).y()*distances.at(i).y();
}
double delta = S*Sxx - Sx*Sx;
a = (S*Sxy - Sx*Sy)/delta;
b = (Sxx*Sy - Sx*Sxy)/delta;
double error = 0;
for(int i=0;i<distances.count();i++) {
error += (distances.at(i).y() - a*distances.at(i).x()-b)/(-a*distances.at(i).x()-b)*(distances.at(i).y() - a*distances.at(i).x()-b)/(-a*distances.at(i).x()-b);
}
return error;
}
#ifndef COSQUALITYFUNCTION_H
#define COSQUALITYFUNCTION_H
#include <QVector>
class SurveyResults;
class QPointF;
class Cos;
#include "IFeatureExtractor.h"
#include "FeatureVector.h"
class CosQualityFunction
{
public:
CosQualityFunction(const SurveyResults* _results,
IFeatureExtractor* extractor,
const Cos *cos = NULL);
/*Wyznacza wartość funkcji dla zadanych parametrów*/
float evaluate(const QVector<float> &params);
void dumpResults(QString filename, const QVector<float> &params);
private:
/*oblicza odległość od dwóch wektorów cech*/
float distance(const FeatureVector& first, const FeatureVector& second) const;
/*Liczy błąd metodą najmniejszych kwadratów*/
float leastSquares(double& a, double& b);
const SurveyResults *results;
IFeatureExtractor *extractor;
/*Przechowuje tymczasowe wyniki gdzie pierwszy element pary to podobieństwo z ankiety,
a drugi to odległość wektrów cech*/
QVector<QPointF> distances;
/* funkcja "coś" z task6 */
const Cos *mCos;
};
#endif // COSQUALITYFUNCTION_H
#include "Vertex.h"
#include <QPointer>
bool operator< (const QPointer<Vertex> &first, const QPointer<Vertex> &second)
{
return (*first) < (*second);
}
Vertex operator* (const float a, const Vertex &v)
{
Vertex result(v.p.size());
for(int i = 0; i < v.p.size(); i++)
result.p[i] = a * v.p[i];
return result;
}
Vertex operator+ (const Vertex &v1, const Vertex &v2)
{
Vertex result(v1.p.size());
for(int i = 0; i < v1.p.size(); i++)
result.p[i] = v1.p[i] + v2.p[i];
return result;
}
Vertex operator- (const Vertex &v1, const Vertex &v2)
{
Vertex result(v1.p.size());
for(int i = 0; i < v1.p.size(); i++)
result.p[i] = v1.p[i] - v2.p[i];
return result;
}
Vertex operator- (const Vertex &v)
{
Vertex result(v.p.size());
for(int i = 0; i < v.p.size(); i++)
result = -v.p[i];
return result;
}
#ifndef VERTEX_H
#define VERTEX_H
#include <QVector>
#include <QObject>
#include <cmath>
class Vertex : public QObject
{
Q_OBJECT
public:
QVector<float> p;
float f;
friend Vertex operator* (const float a, const Vertex &v);
friend Vertex operator+ (const Vertex &v1, const Vertex &v2);
friend Vertex operator- (const Vertex &v1, const Vertex &v2);
friend Vertex operator- (const Vertex &v);
Vertex(uint size = 1) :
p(size), f(0.0f)
{
zeros();
}
Vertex(const Vertex &other) :
QObject(other.parent()), p(other.p.size()), f(other.f)
{
for(int i = 0; i < other.p.size(); i++)
p[i] = other.p[i];
}
Vertex &operator= (const Vertex &other)
{
f = other.f;
p.resize(other.p.size());
for(int i = 0; i < p.size(); i++)
p[i] = other.p[i];
return *this;
}
float distance(const Vertex &other)
{
float d = 0.0f;
for(int i = 0; i < p.size(); i++)
{
float dd = p[i] - other.p[i];
d += dd*dd;
}
return sqrt(d);
}
bool operator< (const Vertex &other)
{
return f < other.f;
}
void zeros()
{
for(int i = 0; i < p.size(); i++)
p[i] = 0.0f;
}
};
#endif // VERTEX_H
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment