Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

  • adfc2e5
  • /
  • ScorerLib
  • /
  • ScorerManager.cpp
Raw File Download

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
content badge Iframe embedding
swh:1:cnt:f9a8ab6fbafbe63869e48f360cb428467ddb0d81
directory badge Iframe embedding
swh:1:dir:c635832c07bb0f28337c2b5951f21be98346eb63

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
ScorerManager.cpp
#include "ScorerManager.h"
#include "../topo-blend/topo-blend.h"
#include "Scheduler.h"

#include "GlobalReflectionSymmScorer.h"

#include "PairRelationDetector.h"
#include "ConnectivityScorer.h"
//#include "PairRelationScorer.h"
#include "GroupRelationScorer.h"

QTextStream& operator << (QTextStream& os, const ScorerManager::PathScore& pr)
{    
	os << "Min connectivity " << pr.connectivity.minCoeff() << "\n";
	os << "Min localSymmetry " << pr.localSymmetry.minCoeff() << "\n";
	os << "Min globalSymmetry " << pr.globalSymmetry.minCoeff() << "\n";
	//int N = pr.connectivity.size();
	//os << "Connectivity \n";
	//for(int i = 0; i < N; ++i)
	//{
	//	os << pr.connectivity[i] << "\n";
	//}
	//os << "local symm \n";
	//for(int i = 0; i < N; ++i)
	//{
	//	os << pr.localSymmetry[i] << "\n";
	//}
	//os << "global symm \n";
	//for(int i = 0; i < N; ++i)
	//{
	//	os << pr.globalSymmetry[i] << "\n";
	//}
    return os;
}

void saveScore(QString filename, QVector<double> scores, QString headline)
{
	QFile file(filename);
	if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return;		
	QTextStream out(&file);	
	if ( !headline.isEmpty() )
		out << headline;
	
	int size = scores.size();
	out << size << "\n";
	for (int i = 0; i < size; ++i)
    {
		out << scores[i] << "\n";
    }
	file.close();
}

ScorerManager::ScorerManager( GraphCorresponder * graph_corresponder, 
	Scheduler * scheduler, QVector<Structure::Graph*> input_graphs, int logLevel )
{
	this->logLevel_ = logLevel;
	this->isUseSourceCenter_ = false;
	this->isUseLink_ = false;
	this->bUsePart_ = true;
	init( graph_corresponder, scheduler, input_graphs);
}

void ScorerManager::init(GraphCorresponder * graph_corresponder, Scheduler * scheduler, QVector<Structure::Graph*> input_graphs)
{
	this->gcorr_ = graph_corresponder;
	this->scheduler_ = scheduler;
	this->normalizeCoef_ = 0.0;
	for ( int i = 0; i < input_graphs.size(); ++i)
	{
		this->actualInputGraphs_.push_back(Structure::Graph::actualGraph( input_graphs[i] ));
		normalizeCoef_ += this->actualInputGraphs_[i]->bbox().diagonal().norm();
	}
	normalizeCoef_ *= 0.5;

	maxGlobalSymmScore_ = -1;	
}


void ScorerManager::parseConstraintPair()
{
    emit( message("Parse constraint pair starts: ") );

	this->connectPairs_.clear();	this->otherPairs_.clear();
	for ( int i = 0; i < this->actualInputGraphs_.size(); ++i)
	{
		PairRelationDetector cpd(this->actualInputGraphs_[i], i, normalizeCoef_, this->isUseLink_, true, logLevel_);
		cpd.detect(this->actualInputGraphs_[(i+1)%this->actualInputGraphs_.size()], this->gcorr_->correspondences);
		this->connectPairs_.push_back(cpd.connectedPairs_);
		this->otherPairs_.push_back(cpd.otherPairs_);

		if (this->logLevel_)
		{
			saveToFile("pair_relation-" + QString::number(i) + ".txt", cpd.otherPairs_);
		}
	}

    emit( message("Parse constraint pairs end. ") );
}
void ScorerManager::evaluateTopology()
{
	/////////////////
    emit( message("Evaluate topology starts: ") );

	if ( connectPairs_.empty() )
	{
		emit( message("Parse topology first! ") );
		return;
	}

	int idx(0);
	Structure::Graph* g = getCurrentGraph(idx);
	ConnectivityScorer cs(g, idx, this->normalizeCoef_, this->isUseLink_, this->logLevel_);	
	cs.evaluate(this->connectPairs_, this->gcorr_->correspondences);

    emit( message("Evaluate topology end. ") );
}
QVector<double> ScorerManager::evaluateTopology( QVector<Structure::Graph*> const &graphs )
{
	QVector<double> topoScore;
	int logLevel = 0;
	double score;
    for (int i = 0; i < graphs.size(); ++i)
    {
		Structure::Graph * g = Structure::Graph::actualGraph(graphs[i] );
		ConnectivityScorer cs(g, i, this->normalizeCoef_, this->isUseLink_, logLevel);	
		score = cs.evaluate(this->connectPairs_, this->gcorr_->correspondences);
		topoScore.push_back(score);
    }
	return topoScore;
}
void ScorerManager::evaluateTopologyAuto()
{
    emit( message("Evaluate topology auto starts: ") );

	if ( connectPairs_.empty() )
	{
		emit( message("Parse topology first! ") );
		return;
	}
	QVector<double> topoScore = evaluateTopology(this->scheduler_->allGraphs);
    saveScore(QString("evaluate_connectivity_auto.txt"), topoScore, QString());

    emit( message("Evaluate topology auto end. ") );
}

void ScorerManager::parseConstraintGroup()
{
	//////////////////
    emit( message("Parse constraint group starts: ") );
	if ( this->otherPairs_.size() < 2)
	{
		emit( message("Parse pairs first!") );
		return;
	}

	///////////////////////
	groupRelations_.clear();
	for ( int i = 0; i < this->actualInputGraphs_.size(); ++i)
	{
		Structure::Graph * g = Structure::Graph::actualGraph( this->actualInputGraphs_[i] );
		GroupRelationDetector grd(g, i, this->normalizeCoef_, this->logLevel_);
		grd.detect(this->otherPairs_[i]);
		this->groupRelations_.push_back(grd.groupRelations_);
		if (this->logLevel_)
		{
			saveToFile("group_relation-" + QString::number(i) + ".txt", this->groupRelations_[i]);
			saveToFile("pair_relation-" + QString::number(i) + ".txt", this->otherPairs_[i]);
		}
	}	

    emit( message("Parse constraint group end. ") );
}
void ScorerManager::evaluateGroups()
{
	/////////////////
    emit( message("Evaluate group starts: ") );

	if ( this->groupRelations_.empty() )
	{
		emit( message("Parse constraint group first! ") );
		return;
	}

	int idx(0);
	Structure::Graph* g = getCurrentGraph(idx);
	GroupRelationScorer grs(g, idx, this->normalizeCoef_, this->logLevel_);
	grs.evaluate(groupRelations_, this->gcorr_->correspondences);

    emit( message("Evaluate group end. ") );
}
QVector<double> ScorerManager::evaluateGroups( QVector<Structure::Graph*> const &graphs )
{
	QVector<double> groupScore;
	int logLevel = 0;
	double score;
    for (int i = 0; i < graphs.size(); ++i)
    {
		Structure::Graph * g = Structure::Graph::actualGraph(graphs[i] );
		GroupRelationScorer grs(g, i, this->normalizeCoef_, logLevel);
		score = grs.evaluate(groupRelations_, this->gcorr_->correspondences);
		groupScore.push_back(score);
    }
	return groupScore;
}
void ScorerManager::evaluateGroupsAuto()
{
    emit( message("Evaluate group auto starts: ") );

	if ( groupRelations_.empty() )
	{
		emit( message("Parse constraint group first! ") );
		return;
	}


	QVector<double> groupScore = evaluateGroups(this->scheduler_->allGraphs);
	saveScore(QString("evaluate_group_auto.txt"), groupScore, QString());	

    emit( message("Evaluate group auto end. ") );
	return;
}

void ScorerManager::parseGlobalReflectionSymm()
{
	//////////////////
    emit( message("Parse global symmetry starts: ") );
	if ( this->actualInputGraphs_.size() < 2)
	{
		emit( ("Two graphs needed!") );
		return;
	}

    double symmScore[2];
    for (int i = 0; i < this->actualInputGraphs_.size(); ++i)
    {
		Structure::Graph * g = Structure::Graph::actualGraph( this->actualInputGraphs_[i] );
		GlobalReflectionSymmScorer gss(g, i, this->normalizeCoef_, this->bUsePart_, this->logLevel_);
        symmScore[i] = gss.evaluate();
		if ( i == 0)
		{
			this->refCenter_ = gss.center_;
			this->refNormal_ = gss.normal_;
		}
    }

    this->maxGlobalSymmScore_ = std::max(symmScore[0], symmScore[1]);
	//this->maxGlobalSymmScore_ = symmScore[0];
    emit( message("Parse global symmetry end. ") );
}
void ScorerManager::evaluateGlobalReflectionSymm()
{
	/////////////////
    emit( message("Evaluate global symmetry starts: ") );

	if ( !isGlobalReflectionSymmParsed() )
	{
		emit( message("Parse global symmetry first! ") );
		return;
	}

	int idx(0);
	Structure::Graph* g = getCurrentGraph(idx);
	GlobalReflectionSymmScorer gss(g, idx, this->normalizeCoef_, this->bUsePart_, this->logLevel_);

	double symmScore;
	if (isUseSourceCenter_)
		symmScore = gss.evaluate( this->refCenter_, this->refNormal_, this->maxGlobalSymmScore_);
	else
		symmScore = gss.evaluate( gss.center_, this->refNormal_, this->maxGlobalSymmScore_);

    emit( message("Evaluate global symmetry end. ") );
}
QVector<double> ScorerManager::evaluateGlobalReflectionSymm( QVector<Structure::Graph*> const &graphs )
{
	QVector<double> symmScore;
	int logLevel = 0;
	double score;
    for (int i = 0; i < graphs.size(); ++i)
    {
		Structure::Graph * g = Structure::Graph::actualGraph(graphs[i] );
        GlobalReflectionSymmScorer gss(g, i, this->normalizeCoef_, this->bUsePart_, logLevel);

		if (isUseSourceCenter_)
			score = gss.evaluate( this->refCenter_, this->refNormal_, this->maxGlobalSymmScore_);
		else
			score = gss.evaluate( gss.center_, this->refNormal_, this->maxGlobalSymmScore_);

		symmScore.push_back(score);
    }
	return symmScore;
}
void ScorerManager::evaluateGlobalReflectionSymmAuto()
{
	///////////////// pre-condition
    emit( message("Evaluate global symmetry auto starts: ") );

	if ( !isGlobalReflectionSymmParsed() )
	{
		emit( message("Parse global symmetry first! ") );
		return;
	}

	///////////////// compute
	QVector<double> symmScore = evaluateGlobalReflectionSymm(this->scheduler_->allGraphs);    

	QString headline = "is use source center: ";
	if ( isUseSourceCenter_)
	{
		headline.append("true");
	}
	else
	{
		headline.append("false");
	}
	headline.append("\n");
	saveScore(QString("evaluate_global_symm_auto.txt"), symmScore, headline);		

    emit( message("Evaluate global symmetry auto end. ") );
}


void ScorerManager::setIsUseSourceCenter(bool bUse)
{
	isUseSourceCenter_ = bUse;
	if (isUseSourceCenter_)
		emit( message("use source center") );
	else
		emit( message("not use source center") );
}
void ScorerManager::setIsUsePart(bool bUse)
{
	this->bUsePart_ = bUse;
	if (bUsePart_)
		emit( message("use part for global symm") );
	else
		emit( message("not use part for global symm") );
}

void ScorerManager::setIsUseLink(bool bUse)
{
	isUseLink_ = bUse;
	if (isUseLink_)
		emit( message("use link for connectivity") );
	else
		emit( message("not link for connectivity") );
}
Structure::Graph * ScorerManager::getCurrentGraph(int& idx)
{
	int ct = this->scheduler_->slider->currentTime();
	idx = this->scheduler_->allGraphs.size() * (double(ct) / this->scheduler_->totalExecutionTime());
	
	Structure::Graph * g = Structure::Graph::actualGraph(this->scheduler_->allGraphs[idx]);
	return g;
}

ScorerManager::PathScore ScorerManager::pathScore( QVector<Structure::Graph*> graphs )
{
	ScorerManager::PathScore score;

	int N = graphs.size();
	int logLevel = 0;

	QVector<double> connectivity, localSymmetry, globalSymmetry;

	// Compute all scores at once
	for (int i = 0; i < N; ++i)
	{
		Structure::Graph * g = Structure::Graph::actualGraph(graphs[i] );

		// Connectivity
		ConnectivityScorer cs(g, i, this->normalizeCoef_, this->isUseLink_, logLevel);	
		connectivity.push_back( cs.evaluate(this->connectPairs_, this->gcorr_->correspondences) );

		// Local symmetry
		GroupRelationScorer grs(g, i, this->normalizeCoef_, logLevel);
		localSymmetry.push_back( grs.evaluate(groupRelations_, this->gcorr_->correspondences) );

		// Global symmetry
		GlobalReflectionSymmScorer gss(g, i, this->normalizeCoef_, logLevel);
		if (isUseSourceCenter_)
			globalSymmetry.push_back( gss.evaluate( this->refCenter_, this->refNormal_, this->maxGlobalSymmScore_) );
		else
			globalSymmetry.push_back( gss.evaluate( gss.center_, this->refNormal_, this->maxGlobalSymmScore_) );

		// Clean up
		delete g;
	}

	// Fill scores into vectors
	score.connectivity = VectorXd::Zero(N);
	score.localSymmetry = VectorXd::Zero(N);
	score.globalSymmetry = VectorXd::Zero(N);

	for(int i = 0; i < N; i++)
	{
		score.connectivity[i] = connectivity[i];
		score.localSymmetry[i] = localSymmetry[i];
		score.globalSymmetry[i] = globalSymmetry[i];

		graphs[i]->property["scoreConnectivity"] = 1 - connectivity[i];
		graphs[i]->property["scoreSymLocal"] = 1 - localSymmetry[i];
		graphs[i]->property["scoreSymGlobal"] = 1 - globalSymmetry[i];

		double error = qMax(qMax(connectivity[i], localSymmetry[i]), globalSymmetry[i]);
		graphs[i]->property["score"] = -error;
	}

	return score;
}

MatrixXd ScorerManager::PathScore::computeRange()
{
	// Columns: min, max, range, average
	MatrixXd R(3, 4);

	R(0,0) = connectivity.minCoeff();	R(0,1) = connectivity.maxCoeff();	R(0,2) = R(0,1) - R(0,0); R(0,3) = connectivity.mean();
	R(1,0) = localSymmetry.minCoeff();	R(1,1) = localSymmetry.maxCoeff();	R(1,2) = R(1,1) - R(1,0); R(1,3) = localSymmetry.mean();
	R(2,0) = globalSymmetry.minCoeff(); R(2,1) = globalSymmetry.maxCoeff(); R(2,2) = R(2,1) - R(2,0); R(2,3) = globalSymmetry.mean();

	return R;
}

double ScorerManager::PathScore::score()
{
	int N = connectivity.size();

	double errConnect = 0, errLocal = 0, errSymmetry = 0;

	for(int i = 0; i < N; i++)
	{
		errConnect += 1.0 - connectivity[i];
		errLocal += 1.0 - localSymmetry[i];
		errSymmetry +=  1.0 - globalSymmetry[i];
	}

	double error = qMax(qMax(errConnect, errLocal), errSymmetry);

	return -error;
}

back to top

Software Heritage — Copyright (C) 2015–2025, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API