⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 reductcostfilter.cpp

📁 粗糙集应用软件
💻 CPP
字号:
//-------------------------------------------------------------------
// Author........: Aleksander 豩rn
// Date..........:
// Description...:
// Revisions.....:
//===================================================================

#include <stdafx.h> // Precompiled headers.
#include <copyright.h>

#include <kernel/algorithms/reductcostfilter.h>
#include <kernel/algorithms/keyword.h>

#include <kernel/structures/reduct.h>
#include <kernel/structures/reducts.h>
#include <kernel/structures/decisiontable.h>

#include <kernel/utilities/iokit.h>
#include <kernel/utilities/mathkit.h>

#include <kernel/basic/algorithm.h>
#include <kernel/basic/message.h>

#include <kernel/system/fstream.h>

//-------------------------------------------------------------------
// Methods for class ReductCostFilter.
//===================================================================

//-------------------------------------------------------------------
// Constructors/destructor.
//===================================================================

ReductCostFilter::ReductCostFilter() {
	SetCostFilename(Undefined::String());
	SetThreshold(100.0);
	SetDefaultCost(0.0);
	SetLogFilename(Undefined::String());
}

ReductCostFilter::~ReductCostFilter() {
}

//-------------------------------------------------------------------
// Methods inherited from Identifier.
//===================================================================

IMPLEMENTIDMETHODS(ReductCostFilter, REDUCTCOSTFILTER, ReductFilter)

//-------------------------------------------------------------------
// Methods inherited from Algorithm.
//===================================================================

//-------------------------------------------------------------------
// Method........: GetParameters
// Author........: Aleksander 豩rn
// Date..........:
// Description...:
// Comments......:
// Revisions.....:
//===================================================================

String
ReductCostFilter::GetParameters() const {

	String parameters;

	// Cost, filename.
	parameters += Keyword::Cost() + Keyword::Dot() + Keyword::Filename();
	parameters += Keyword::Assignment();
	parameters += GetCostFilename();

	parameters += Keyword::Separator();

	// Default.
	parameters += Keyword::Default();
	parameters += Keyword::Assignment();
	parameters += String::Format(GetDefaultCost());

	parameters += Keyword::Separator();

	// Threshold.
	parameters += Keyword::Threshold();
	parameters += Keyword::Assignment();
	parameters += String::Format(GetThreshold());

	parameters += Keyword::Separator();

	// Log, filename.
	parameters += Keyword::Log() + Keyword::Dot() + Keyword::Filename();
	parameters += Keyword::Assignment();
	parameters += GetLogFilename();

	parameters += Keyword::Separator();

	return parameters + ReductFilter::GetParameters();

}

//-------------------------------------------------------------------
// Method........: SetParameter
// Author........: Aleksander 豩rn
// Date..........:
// Description...:
// Comments......:
// Revisions.....:
//===================================================================

bool
ReductCostFilter::SetParameter(const String &keyword, const String &value) {

	// Cost, filename,
	if (keyword == Keyword::Cost() + Keyword::Dot() + Keyword::Filename())
		return SetCostFilename(value);

	// Cost, filename (for backwards compatibility).
	if (keyword == Keyword::Filename())
		return SetCostFilename(value);

	// Threshold.
	if (keyword == Keyword::Threshold() && value.IsFloat())
		return SetThreshold(value.GetFloat());

	// Default.
	if (keyword == Keyword::Default() && value.IsFloat())
		return SetDefaultCost(value.GetFloat());

	// Log, filename,
	if (keyword == Keyword::Log() + Keyword::Dot() + Keyword::Filename())
		return SetLogFilename(value);

	return ReductFilter::SetParameter(keyword, value);

}

//-------------------------------------------------------------------
// Method........: GetOutputFilenames
// Author........: Aleksander 豩rn
// Date..........:
// Description...:
// Comments......:
// Revisions.....:
//===================================================================

bool
ReductCostFilter::GetOutputFilenames(Vector(String) &filenames) const {

	if (!Algorithm::GetOutputFilenames(filenames))
		return false;

	filenames.push_back(GetLogFilename());

	return true;

}

//-------------------------------------------------------------------
// Method........: Apply
// Author........: Aleksander 豩rn
// Date..........:
// Description...:
// Comments......:
// Revisions.....:
//===================================================================

Structure *
ReductCostFilter::Apply(Structure &structure) const {

	// This method is conceptually const only.
	ReductCostFilter *self = const_cast(ReductCostFilter *, this);

	Handle<DecisionTable> table = dynamic_cast(DecisionTable *, structure.FindParent(DECISIONTABLE));

	// Load cost information.
	if (!self->costs_.Load(GetCostFilename(), *table, GetDefaultCost())) {
		Message::Error("Failed to load cost information.");
		return NULL;
	}

	// Erase mutable bookkeeping stuff.
	(self->statistics_).erase((self->statistics_).begin(), (self->statistics_).end());
	(self->rankings_).erase((self->rankings_).begin(), (self->rankings_).end());
	(self->reducts_).erase((self->reducts_).begin(), (self->reducts_).end());

	(self->statistics_).reserve(structure.GetNoStructures());
	(self->rankings_).reserve(structure.GetNoStructures());
	(self->reducts_).reserve(structure.GetNoStructures());

	// Do the filtering.
	Handle<Structure> result = Filter::Apply(structure);

	// Save log, calculate and print statistics.
	if (!self->SaveLog(*table))
		Message::Warning("Failed to save log file.");

	// Clean up in general.
	(self->statistics_).erase((self->statistics_).begin(), (self->statistics_).end());
	(self->rankings_).erase((self->rankings_).begin(), (self->rankings_).end());
	(self->reducts_).erase((self->reducts_).begin(), (self->reducts_).end());

	return result.Release();

}

//-------------------------------------------------------------------
// Methods inherited from Filter.
//===================================================================

//-------------------------------------------------------------------
// Method........: Remove
// Author........: Aleksander 豩rn
// Date..........:
// Description...: Returns true if the specified reduct should be removed
//                 from the reduct set.
// Comments......:
// Revisions.....:
//===================================================================

bool
ReductCostFilter::Remove(const Structures &structures, int i) const {

	if (!structures.IsA(REDUCTS))
		return false;

	Handle<Reducts> reducts = dynamic_cast(Reducts *, const_cast(Structures *, &structures));
	Handle<Reduct>  reduct  = reducts->GetReduct(i);

	// Compute total cost.
	float cost = costs_.GetCost(*reduct);

	String formatted;
	bool   masked = true;

	// Format reduct.
	if (!reduct->Format(formatted, dynamic_cast(DecisionTable *, reducts->FindParent(DECISIONTABLE)), masked))
		formatted = Undefined::String();

	// Update bookkeeping structures.
	ReductCostFilter *self = const_cast(ReductCostFilter *, this);

	// Update bookkeeping structures.
	(self->statistics_).push_back(cost);
	(self->rankings_).push_back(std::make_pair(i, cost));
	(self->reducts_).push_back(ISPair(i, formatted) /* std::make_pair(i, formatted) */);

	// Return removal decision.
	return (cost > GetThreshold());

}

//-------------------------------------------------------------------
// Local methods.
//===================================================================

//-------------------------------------------------------------------
// Method........: SaveLog
// Author........: Aleksander 豩rn
// Date..........:
// Description...:
// Comments......:
// Revisions.....:
//===================================================================

bool
ReductCostFilter::SaveLog(const DecisionTable &table) const {

	// Compute statistics.
	float mean    = MathKit::Mean(statistics_);
	float median  = MathKit::Median(statistics_);
	float stddev  = MathKit::StandardDeviation(statistics_);
	float minimum = MathKit::Minimum(statistics_);
	float maximum = MathKit::Maximum(statistics_);

	Message message;

	// Output to user.
	message.Notify("Cost.Mean    = " + (mean    == Undefined::Float() ? Undefined::String() : String::Format(mean)));
	message.Notify("Cost.Median  = " + (median  == Undefined::Float() ? Undefined::String() : String::Format(median)));
	message.Notify("Cost.StdDev  = " + (stddev  == Undefined::Float() ? Undefined::String() : String::Format(stddev)));
	message.Notify("Cost.Minimum = " + (minimum == Undefined::Float() ? Undefined::String() : String::Format(minimum)));
	message.Notify("Cost.Maximum = " + (maximum == Undefined::Float() ? Undefined::String() : String::Format(maximum)));

	ofstream stream;

	if (!IOKit::Open(stream, GetLogFilename())) {
		Message::Error("Failed to open " + GetLogFilename() + ".");
		return false;
	}

	bool masked = true;

	// Save log header.
	stream << "% Output from ROSETTA, " + SystemKit::GetUser() + " " + SystemKit::GetTimestamp() << endl;
	stream << "%" << endl;
	stream << "% " + IdHolder::GetClassname(GetId()) << endl;
	stream << "% {" + GetParameters() + "}" << endl;
	stream << "%" << endl;
	stream << "% Note that the indices below are 0-based." << endl;
	stream << "%" << endl;

	int i, longest = 0;

	for (i = 0; i < table.GetNoAttributes(masked); i++) {
		/*
		if (costs_.GetCost(i) == GetDefaultCost())
			continue;
		*/
		String name = table.GetAttributeName(i, masked);
		if (name.GetLength() > longest)
			longest = name.GetLength();
	}

	for (i = 0; i < table.GetNoAttributes(masked); i++) {
		/*
		if (costs_.GetCost(i) == GetDefaultCost())
			continue;
		*/
		String name = table.GetAttributeName(i, masked);
		name = "Cost(" + name + ")";
		name.Pad(' ', longest + 6);
		stream << "% " << name << " = " << costs_.GetCost(i) << endl;
	}

	stream << endl;

	// Save cost statistics.
	stream << "Cost.Mean    = " << (mean    == Undefined::Float() ? Undefined::String() : String::Format(mean)) << endl;
	stream << "Cost.Median  = " << (median  == Undefined::Float() ? Undefined::String() : String::Format(median)) << endl;
	stream << "Cost.StdDev  = " << (stddev  == Undefined::Float() ? Undefined::String() : String::Format(stddev)) << endl;
	stream << "Cost.Minimum = " << (minimum == Undefined::Float() ? Undefined::String() : String::Format(minimum)) << endl;
	stream << "Cost.Maximum = " << (maximum == Undefined::Float() ? Undefined::String() : String::Format(maximum)) << endl << endl;

	// We need to update (sort) the mutable bookkeeping stuff.
	ReductCostFilter *self = const_cast(ReductCostFilter *, this);

	IFPairCompareSecondDescending comparator1;
	ISPairCompareFirstAscending   comparator2;

	message.Notify("Sorting costs...");

	// Sort rankings and formatted reducts.
	std::sort((self->rankings_).begin(), (self->rankings_).end(), comparator1);
	std::sort((self->reducts_).begin(),  (self->reducts_).end(),  comparator2);

	message.Notify("Saving costs to log...");

	// Save rankings.
	for (i = 0; i < rankings_.size(); i++) {

		int   index = rankings_[i].first;
		float value = rankings_[i].second;

		String formatted_i;
		String formatted_v;
		String formatted_r;

		// Format output.
		formatted_i = "Reduct #" + String::Format(index);

		formatted_v = (value == Undefined::Float()) ? Undefined::String() : String::Format(value);
		formatted_v.Pad(' ', 11);

		formatted_r = reducts_[index].second;

		// Save to stream.
		stream << formatted_v << formatted_i << " = " << formatted_r << endl;

	}

	return true;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -