Skip to content

Commit

Permalink
1.3 Arbitrary alphabet size support
Browse files Browse the repository at this point in the history
asalib now supports arbilitrarily large alphabet sizes, while preserving multithreaded capability.
New classes include types::word to represent words, rather than std::string, and types::parihkVector has been upgraded to support arbitrary alphabet sizes.
  • Loading branch information
jamesrswift committed Jun 23, 2019
1 parent e0fe35a commit 2913e37
Show file tree
Hide file tree
Showing 11 changed files with 248 additions and 260 deletions.
19 changes: 8 additions & 11 deletions Analysis/analysis_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
#include <common/tclap/CmdLine.h>
#include <iostream>

using json = nlohmann::json;
using namespace AbelianSquaresAnalysis::morphism;
using namespace AbelianSquaresAnalysis::prefix;
using namespace AbelianSquaresAnalysis::utility;
using namespace AbelianSquaresAnalysis;

#define asalib_VERBOSE(v,...) if (v) printf(##__VA_ARGS__)

Expand All @@ -41,27 +38,27 @@ int main(int argc, char* argv[]) {

// Load input from json
asalib_VERBOSE(verboseOption, "Loading into program from file \"%s\"\n", input_file.c_str());
morphismOutput input_cpp = LoadClassFromFile<morphismOutput>(input_file);
morphism::morphismOutput input_cpp = utility::LoadClassFromFile<morphism::morphismOutput>(input_file);

// Analyse prefix
asalib_VERBOSE(verboseOption, "Analysing prefix . . .\n");
prefixAnalysisOutput analysisOutput(input_cpp);
AnalysePrefix(analysisOutput.generatedPrefix, analysisOutput);
prefix::prefixAnalysisOutput analysisOutput(input_cpp);
prefix::AnalysePrefix(analysisOutput.generatedPrefix, analysisOutput);
asalib_VERBOSE(verboseOption, "Analysis complete!\n");

// Prepare output directory
asalib_VERBOSE(verboseOption, "Preparing output directory\n");
std::string parent_directory = GetParentDirectory(input_file);
std::string parent_directory = utility::GetParentDirectory(input_file);
if (outputRelativityOption) {
asalib_VERBOSE(verboseOption, "Output is relative to executable\n");
parent_directory = CurrentExecutablePath();
parent_directory = utility::CurrentExecutablePath();
}
std::string outputDirectory = PrepareSubdirectory(parent_directory, output_directory);
std::string outputDirectory = utility::PrepareSubdirectory(parent_directory, output_directory);

// Output to file
std::string file_location = outputDirectory + "\\" + analysisOutput.input.morphismName + analysisOutput.input.startWord + ".json";
printf("Generating output file \"%s\"\n", file_location.c_str());
SaveClassToFile<prefixAnalysisOutput>(file_location, analysisOutput);
utility::SaveClassToFile<prefix::prefixAnalysisOutput>(file_location, analysisOutput);

asalib_VERBOSE(verboseOption, "Program completed successfull\n");
asalib_wait_debug();
Expand Down
16 changes: 7 additions & 9 deletions Morphism/morphism_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
#include <common/tclap/CmdLine.h>
#include <iostream>

using json = nlohmann::json;
using namespace AbelianSquaresAnalysis::morphism;
using namespace AbelianSquaresAnalysis::utility;
using namespace AbelianSquaresAnalysis;

#define asalib_VERBOSE(v,...) if (v) printf(##__VA_ARGS__)

Expand All @@ -41,11 +39,11 @@ int main(int argc, char* argv[]) {

// Load input from json
asalib_VERBOSE(verboseOption, "Loading into program from file \"%s\"\n", input_file.c_str());
morphismInput input_cpp = LoadClassFromFile<morphismInput>(input_file);
morphism::morphismInput input_cpp = utility::LoadClassFromFile<morphism::morphismInput>(input_file);

// Run morphism!
asalib_VERBOSE(verboseOption, "Running morphisms . . .\n");
std::vector<morphismOutput> output = RunMorphisms(input_cpp);
std::vector<morphism::morphismOutput> output = morphism::RunMorphisms(input_cpp);
#ifdef _WIN64
asalib_VERBOSE(verboseOption, "%llu morphisms iterated\n", output.size());
#else
Expand All @@ -54,20 +52,20 @@ int main(int argc, char* argv[]) {

// Prepare output directory
asalib_VERBOSE(verboseOption, "Preparing output directory\n");
std::string parent_directory = GetParentDirectory(input_file);
std::string parent_directory = utility::GetParentDirectory(input_file);
if (outputRelativityOption) {
asalib_VERBOSE(verboseOption, "Output is relative to executable\n");
parent_directory = CurrentExecutablePath();
parent_directory = utility::CurrentExecutablePath();
}
std::string outputDirectory = PrepareSubdirectory(parent_directory, output_directory);
std::string outputDirectory = utility::PrepareSubdirectory(parent_directory, output_directory);

// for each generated prefix
for (const auto& output_entry : output) {

// Output to file
std::string file_location = outputDirectory + "\\" + output_entry.input.morphismName + output_entry.input.startWord + ".out";
asalib_VERBOSE(verboseOption, "Generating output file \"%s\"\n", file_location.c_str());
SaveClassToFile<morphismOutput>(file_location, output_entry);
utility::SaveClassToFile<morphism::morphismOutput>(file_location, output_entry);

}

Expand Down
10 changes: 5 additions & 5 deletions SingleWord/singleword_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

#include <asalib/public/library.h>
#include <asalib/public/prefix.hpp>
#include <asalib/public/types.hpp>
#include <common/tclap/CmdLine.h>
#include <iostream>
#include <string>

using json = nlohmann::json;
using namespace AbelianSquaresAnalysis;

#define asalib_VERBOSE(v,...) if (v) printf(##__VA_ARGS__)
Expand All @@ -20,18 +20,18 @@ using namespace AbelianSquaresAnalysis;
#define asalib_singleword_dictionary_found "\tFound %llu "
#define asalib_singleword_dictionary_ofwhich "\t\tOf which %llu trivial and %llu non-trivial.\n"
#define asalib_singleword_dictionary_detailedinformation "\t\tOutputing detailed information:\n"
#define asalib_singleword_dictionary_detail "\t\t\t\"%s\" at position %zu, (%llu,%llu)\n"
#define asalib_singleword_dictionary_detail "\t\t\t\"%s\" at position %zu, %s\n"
#else
#define asalib_singleword_dictionary_found "\tFound %lu "
#define asalib_singleword_dictionary_ofwhich "\t\tOf which %lu trivial and %lu non-trivial.\n"
#define asalib_singleword_dictionary_detailedinformation "\t\tOutputing detailed information on total squares:\n"
#define asalib_singleword_dictionary_detailed "\t\t\t\"%s\" at position %zu, (%lu,%lu)\n"
#define asalib_singleword_dictionary_detail "\t\t\t\"%s\" at position %zu, %s\n"
#endif

inline void PrintDetailedInformationOnType(prefix::prefixAnalysisOutputSquareType& typeOutput) {
printf(asalib_singleword_dictionary_detailedinformation);
for (const auto& square : typeOutput.list) {
printf(asalib_singleword_dictionary_detail, square.word.c_str(), square.position, square.vector.a, square.vector.b);
for (auto& square : typeOutput.list) {
printf(asalib_singleword_dictionary_detail, square.word.c_str(), square.position, ((std::string)square.vector).c_str());
}
}

Expand Down
4 changes: 4 additions & 0 deletions asalib/asalib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<GenerateXMLDocumentationFiles>false</GenerateXMLDocumentationFiles>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -125,6 +126,7 @@
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
<GenerateXMLDocumentationFiles>false</GenerateXMLDocumentationFiles>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -141,6 +143,7 @@
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpplatest</LanguageStandard>
<GenerateXMLDocumentationFiles>false</GenerateXMLDocumentationFiles>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand All @@ -160,6 +163,7 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<GenerateXMLDocumentationFiles>false</GenerateXMLDocumentationFiles>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<FloatingPointModel>Fast</FloatingPointModel>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
Expand Down
2 changes: 1 addition & 1 deletion asalib/private/asalib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@

#include <asalib/public/library.h>

asalib const char* AbelianSquaresAnalysis::BUILD = __TIMESTAMP__;
asalib const char* AbelianSquaresAnalysis::BUILD = "1.3";
72 changes: 37 additions & 35 deletions asalib/private/prefix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,28 @@
#include <algorithm>
#include <common/json.hpp>

#define asalib_prefix_MULTITHREAD

using namespace AbelianSquaresAnalysis;

asalib AbelianSquaresAnalysis::prefix::substringAnalysisOutput::substringAnalysisOutput()
: vector()
{
}

asalib AbelianSquaresAnalysis::prefix::substringAnalysisOutput::substringAnalysisOutput(const prefix::substringAnalysisInput& base)
: prefix::substringAnalysisInput(base), vector()
{
}

asalib AbelianSquaresAnalysis::prefix::prefixAnalysisOutput::prefixAnalysisOutput(const morphism::morphismOutput& base)
: morphism::morphismOutput(base)
{
// Copy construct prefixAnalysisOutput
}

asalib AbelianSquaresAnalysis::prefix::prefixAnalysisOutput::prefixAnalysisOutput(const morphism::morphismOutput& base, const prefix::AnalysePrefixOutput& base2)
: morphism::morphismOutput(base), prefix::AnalysePrefixOutput(base2)
{
// Copy construct prefixAnalysisOutput
}

#define asalib_prefixanalysis_output_category(name, info)\
Expand All @@ -40,14 +50,14 @@ void asalib AbelianSquaresAnalysis::prefix::to_json(nlohmann::json& j, const pre
{"success", data.morphismSuccess},
{"startWord", data.input.startWord},
{"lengthBound", data.input.lengthBound},
{"generatedPrefix", data.generatedPrefix},
{"generatedPrefix",data.generatedPrefix},
{"generatedPrefixLength", data.generatedPrefixLength},
{"generatedPrefixRuns", data.runs},
{"prefixAnalysis",{
asalib_prefixanalysis_output_category("totalSquares", data.total),
asalib_prefixanalysis_output_category("distinctSquares", data.distinct),
asalib_prefixanalysis_output_category("nonequivalentSquares", data.nonequivalent),
{"totalN_less_than_length_over_four", (data.nonequivalent.trivial + data.nonequivalent.nontrivial) < floor(data.generatedPrefixLength / 4)}
{"totalN_less_than_length_over_four", ((long)data.nonequivalent.trivial + (long)data.nonequivalent.nontrivial) < floor((long)data.generatedPrefixLength / 4)}
}}
};
}
Expand All @@ -57,40 +67,25 @@ void asalib AbelianSquaresAnalysis::prefix::to_json(nlohmann::json& j, const pre
prefix::substringAnalysisOutput asalib AbelianSquaresAnalysis::prefix::AnalyseSubstring(substringAnalysisInput input) {

// Setup return information
prefix::substringAnalysisOutput output;
prefix::substringAnalysisOutput output = (prefix::substringAnalysisOutput) input;

// odd length substrings are not squares
if (input.word.length() % 2 != 0) {
return output; // isSqaure defaults to false
}

// Count first half
types::parihkVector firstHalf;
std::string firstHalfSubString = input.word.substr(0, input.length / 2);
firstHalf.a = asalib_prefix_substringanalysis_count_occurence(firstHalfSubString, 'a');
firstHalf.b = asalib_prefix_substringanalysis_count_occurence(firstHalfSubString, 'b');
//types::parihkVector firstHalf = substring.substr(0, substring.length() / 2).countOccurences();
types::parihkVector firstHalf = input.alphabet; // copy construct
input.word.countOccurences(0, input.length / 2, firstHalf);

// Count second half
types::parihkVector secondHalf;
std::string secondHalfSubString = input.word.substr(input.length / 2, std::string::npos);
secondHalf.a = asalib_prefix_substringanalysis_count_occurence(secondHalfSubString, 'a');
secondHalf.b = asalib_prefix_substringanalysis_count_occurence(secondHalfSubString, 'b');
//types::parihkVector secondHalf = substring.substr(substring.length() / 2).countOccurences();

// substring is square if vectors for each side are equal
if (firstHalf.a == secondHalf.a && firstHalf.b == secondHalf.b) {
output.isSquare = true;
output.vector.a = firstHalf.a;
output.vector.b = firstHalf.b;

if (firstHalf.a == 0 || firstHalf.b == 0) {
output.isTrivial = true;
}
types::parihkVector secondHalf = input.alphabet; // copy construct
input.word.countOccurences(input.length / 2, std::string::npos, secondHalf);

output.word = input.word;
output.position = input.position;
output.length = input.length;
if (firstHalf == secondHalf) {
output.isSquare = true;
output.vector = firstHalf;
output.isTrivial = firstHalf.isTrivial();
}

return output;
Expand All @@ -106,10 +101,11 @@ prefix::prefixAnalysisOutput asalib AbelianSquaresAnalysis::prefix::AnalysePrefi
void asalib AbelianSquaresAnalysis::prefix::AnalysePrefix(types::word input, prefix::AnalysePrefixOutput& output) {

// Prepare thread pool
#ifdef asalib_prefix_MULTITHREAD
AbelianSquaresAnalysis::ThreadPool<prefix::substringAnalysisInput, prefix::substringAnalysisOutput> pool;
#endif

// Sanitize input
std::transform(input.begin(), input.end(), input.begin(), ::tolower);
types::parihkVector alphabet = input.countAlphabetSize();

// For every even word length
for (unsigned int len = 2; len <= input.length(); len += 2) {
Expand All @@ -119,17 +115,26 @@ void asalib AbelianSquaresAnalysis::prefix::AnalysePrefix(types::word input, pre
AnalysisInput.word = input.substr(pos, len);
AnalysisInput.length = len;
AnalysisInput.position = pos;
AnalysisInput.alphabet = alphabet;

#ifdef asalib_prefix_MULTITHREAD
pool.AddTask(prefix::AnalyseSubstring, AnalysisInput);
#else
prefix::substringAnalysisOutput computation_output = prefix::AnalyseSubstring(AnalysisInput);
if (computation_output.isSquare)
output.total.list.push_back(computation_output);
#endif
}
}

#ifdef asalib_prefix_MULTITHREAD
pool.WaitForTasks();

for (auto& computation_output : pool.GetResults()) {
if (computation_output.isSquare)
output.total.list.push_back(computation_output);
}
#endif

prefix::SquaresCountTrivials(output.total);

Expand Down Expand Up @@ -160,15 +165,12 @@ bool asalib AbelianSquaresAnalysis::prefix::SquaresSortDistinctPredicate

bool asalib AbelianSquaresAnalysis::prefix::SquaresComparisonNoneqPredicate
(prefix::substringAnalysisOutput left, prefix::substringAnalysisOutput right) {
return (left.vector.a == right.vector.a && left.vector.b == right.vector.b);
return (left.vector == right.vector);
}

bool asalib AbelianSquaresAnalysis::prefix::SquaresSortNoneqPredicate
(prefix::substringAnalysisOutput left, prefix::substringAnalysisOutput right) {
if (left.vector.a != right.vector.a) {
return left.vector.a > right.vector.a;
}
return left.vector.b > right.vector.b;
return (left.vector > right.vector);
}

asalib AbelianSquaresAnalysis::prefix::SquaresCategoriseInput::SquaresCategoriseInput(std::vector<substringAnalysisOutput>& in, std::vector<substringAnalysisOutput>& out):
Expand Down
Loading

0 comments on commit 2913e37

Please sign in to comment.