📄 orthogonalscaler.cpp
字号:
//-------------------------------------------------------------------// Author........: Aleksander 豩rn// Date..........: 960307// Description...:// Revisions.....://===================================================================#include <stdafx.h> // Precompiled headers.#include <copyright.h>#include <kernel/algorithms/orthogonalscaler.h>#include <kernel/algorithms/keyword.h>#include <kernel/structures/decisiontable.h>#include <kernel/structures/dictionary.h>#include <kernel/structures/attribute.h>#include <kernel/structures/floatattribute.h>#include <kernel/structures/integerattribute.h>#include <kernel/structures/stringattribute.h>#include <kernel/utilities/creator.h>#include <kernel/utilities/mathkit.h>#include <kernel/utilities/iokit.h>#include <kernel/basic/interval.h>#include <kernel/basic/vector.h>#include <kernel/basic/algorithm.h>#include <kernel/basic/message.h>#include <kernel/system/fstream.h>#include <kernel/system/math.h>#include <common/configuration.h>//-------------------------------------------------------------------// Static methods (file scope).//===================================================================//-------------------------------------------------------------------// Method........: StaticLoadCuts// Author........: Aleksander 豩rn// Date..........:// Description...: Loads cuts from file, returns them in-place.// Comments......: Partial overlap with code elsewhere, generalize// later. Note masked/unmasked conversion.// Called from CreateDictionary method.// Revisions.....://===================================================================static boolStaticLoadCuts(const String &filename, const DecisionTable &table, bool masked, Vector(OrthogonalScaler::Cuts) &cuts) { int no_attributes = table.GetNoAttributes(masked); // Initialize vector of all cuts. cuts.erase(cuts.begin(), cuts.end()); cuts.reserve(no_attributes); int i; for (i = 0; i < no_attributes; i++) cuts.push_back(OrthogonalScaler::Cuts()); ifstream cutfile; if (!IOKit::Open(cutfile, filename)) { Message::Error("Could not open file with cuts."); return false; } // Read contents of cut file. while (!IOKit::IsEOF(cutfile)) { String line; // Get index (virtual) and cut of attribute. if (!IOKit::Load(cutfile, line, false)) return false; // Allow for blank lines. if (line.IsEmpty()) continue; if (line.GetNoTokens(" \t") != 2) { Message::Error("Expected two tokens (index, cut)."); return false; } // Split string into (index, cut) pair. String istr = line.Before('\t'); String cstr = line.After('\t'); // Verify types. if (!istr.IsInteger() || !cstr.IsFloat()) { Message::Error("Error reading (index, cut) pair from cut file."); return false; } // Extract values. int index = istr.GetInteger(); float cut = cstr.GetFloat(); // Convert from virtual (masked) to actual (unmasked) indexing scheme. index = table.GetUnmaskedAttribute(index); // Make sure the index is in range. if ((index < 0) || (index >= cuts.size())) { Message::Error("Index in (index, cut) pair in cutfile out of range."); return false; } // Insert cut into appropriate cut vector. cuts[index].push_back(cut); } // Sort the cuts. for (i = 0; i < cuts.size(); i++) std::sort(cuts[i].begin(), cuts[i].end()); return true;}//-------------------------------------------------------------------// Method........: StaticCreateDummyDictionary// Author........: Aleksander 豩rn// Date..........:// Description...: Creates a dummy dictionary.// Comments......: Called from CreateDictionary method.// Revisions.....://===================================================================static boolStaticCreateDummyDictionary(DecisionTable &table, Dictionary &dictionary) { int no_attributes_unmasked = table.GetNoAttributes(false); // Clear present dictionary. dictionary.RemoveAllAttributes(); int i; // Create dummy dictionary. for (i = 0; i < no_attributes_unmasked; i++) { // Create an integer attribute. Handle<Attribute> attribute = Creator::IntegerAttribute(); // Set dummy name/unit. attribute->SetName("A" + String::Format(i)); attribute->SetUnit(Undefined::String()); // Append to dictionary. if (!dictionary.AppendAttribute(attribute.GetPointer())) return false; } // Assign new dictionary. table.SetDictionary(&dictionary); Message::Warning("A dummy dictionary was created."); return true;}//-------------------------------------------------------------------// Method........: StaticHasEqualMasking// Author........: Aleksander 豩rn// Date..........:// Description...: Returns true if the two tables have the same// masking.// Comments......: Called from CreateDictionary method.// Revisions.....://===================================================================static boolStaticHasEqualMasking(const DecisionTable &table1, const DecisionTable &table2, bool masked) { int no_attributes1 = table1.GetNoAttributes(masked); int no_attributes2 = table2.GetNoAttributes(masked); if (no_attributes1 != no_attributes2) return false; int i; for (i = 0; i < no_attributes1; i++) { if (table1.GetAttributeMask(i) != table2.GetAttributeMask(i)) return false; } return true;}//-------------------------------------------------------------------// Method........: StaticHasChanged// Author........: Aleksander 豩rn// Date..........:// Description...: Returns true if the entries in the two tables// differ on the given attribute.// Comments......: Called from CreateDictionary method.// Revisions.....://===================================================================static boolStaticHasChanged(const DecisionTable &table1, const DecisionTable &table2, int attribute_no, bool masked) { int no_objects1 = table1.GetNoObjects(masked); int no_objects2 = table2.GetNoObjects(masked); if (no_objects1 != no_objects2) return true; int i; for (i = 0; i < no_objects1; i++) { if (table1.GetEntry(i, attribute_no, masked) != table2.GetEntry(i, attribute_no, masked)) return true; } return false;}//-------------------------------------------------------------------// Methods for class OrthogonalScaler.//===================================================================//-------------------------------------------------------------------// Constructors/destructor.//===================================================================OrthogonalScaler::OrthogonalScaler() {}OrthogonalScaler::~OrthogonalScaler() {}//-------------------------------------------------------------------// Methods inherited from Identifier.//===================================================================IMPLEMENTIDMETHODS(OrthogonalScaler, ORTHOGONALSCALER, Scaler)//-------------------------------------------------------------------// Methods inherited from Algorithm.//===================================================================//-------------------------------------------------------------------// Method........: Apply// Author........: Aleksander 豩rn// Date..........:// Description...:// Comments......:// Revisions.....://===================================================================Structure *OrthogonalScaler::Apply(Structure &structure) const { // Check if input is of expected type. if (!IsApplicable(structure)) return NULL; // Cast to verified type. Handle<DecisionTable> input = dynamic_cast(DecisionTable *, &structure); Vector(DecisionTable::Mask) original_masks; Vector(DecisionTable::Mask) temporary_masks; if (!GetAttributeMasks(*input, original_masks)) return NULL; // Temporarily hide away non-numerical attributes if specified. if (MaskSymbolic()) { if (!GetTemporaryAttributeMasks(*input, temporary_masks)) return NULL; if (!SetAttributeMasks(*input, temporary_masks)) return NULL; } Handle<DecisionTable> output; // If possible, do the actual discretization. (Assuming the output table "inherits" the masking of the input table.) if (input->GetNoAttributes(true) > 1) { output = Discretize(*input); } else { if (MaskSymbolic()) { Message::Warning("Table has no condition attributes after masking.", false); SetAttributeMasks(*input, original_masks); return &structure; } else { Message::Error("Table has no condition attributes.", false); return NULL; } } if (output == NULL) { if (MaskSymbolic()) SetAttributeMasks(*input, original_masks); return NULL; } // Construct a new dictionary. (Masking of both tables should be the same and seen as by the // discretization method.) if (!CreateDictionary(*input, *output, GetFilename())) { Message::Error("Failed to create dictionary."); if (MaskSymbolic()) SetAttributeMasks(*input, original_masks); return NULL; } // Reset masking. if (MaskSymbolic()) { if (!SetAttributeMasks(*input, original_masks)) return NULL; if (!SetAttributeMasks(*output, original_masks)) return NULL; } // Append string to table name. output->SetName(input->GetName() + ", discretized"); return output.Release();}//-------------------------------------------------------------------// Dictionary creation methods.//===================================================================//-------------------------------------------------------------------// Method........: CreateDictionary// Author........: Aleksander 豩rn// Date..........:// Description...: After a decision table has been scaled, the old// dictionary may no longer be 100% valid as the result// of e.g. a float attribute having been transformed// to an "interval" attribute.//// This method takes as input the decision tables before// and after scaling, and on the basis of these and the// dictionary associated with the before table, creates a// new dictionary which in turn is assigned to the after// table.//// The filename refers to the file where the cut-values// are stored.//// Comments......: Note that the dictionary is indexed with actual (i.e.// unmasked) attributes indices, while the tables are indexed// with virtual (i.e. masked) attribute indices. That is,// dictionaries associated with decision tables have the// dimension of the unmasked table.//// Revisions.....: A
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -