mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Implemented UnusedFunctionArgumentPruner
This commit is contained in:
parent
767d06b297
commit
e2fd41f097
@ -41,7 +41,7 @@ struct OptimiserSettings
|
|||||||
|
|
||||||
// should have good "compilability" property here.
|
// should have good "compilability" property here.
|
||||||
|
|
||||||
"eul" // Run functional expression inliner
|
"Tpeul" // Run functional expression inliner
|
||||||
"xarulrul" // Prune a bit more in SSA
|
"xarulrul" // Prune a bit more in SSA
|
||||||
"xarrcL" // Turn into SSA again and simplify
|
"xarrcL" // Turn into SSA again and simplify
|
||||||
"gvif" // Run full inliner
|
"gvif" // Run full inliner
|
||||||
|
@ -209,6 +209,13 @@ std::map<V, K> invertMap(std::map<K, V> const& originalMap)
|
|||||||
return inverseMap;
|
return inverseMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a set of keys of a map.
|
||||||
|
template <typename K, typename V>
|
||||||
|
std::set<K> keys(std::map<K, V> const& _map)
|
||||||
|
{
|
||||||
|
return applyMap(_map, [](auto const& _elem) { return _elem.first; }, std::set<K>{});
|
||||||
|
}
|
||||||
|
|
||||||
// String conversion functions, mainly to/from hex/nibble/byte representations.
|
// String conversion functions, mainly to/from hex/nibble/byte representations.
|
||||||
|
|
||||||
enum class WhenError
|
enum class WhenError
|
||||||
|
@ -156,6 +156,9 @@ add_library(yul
|
|||||||
optimiser/SyntacticalEquality.h
|
optimiser/SyntacticalEquality.h
|
||||||
optimiser/TypeInfo.cpp
|
optimiser/TypeInfo.cpp
|
||||||
optimiser/TypeInfo.h
|
optimiser/TypeInfo.h
|
||||||
|
optimiser/UnusedFunctionParameterPruner.cpp
|
||||||
|
optimiser/UnusedFunctionParameterPruner.h
|
||||||
|
optimiser/UnusedFunctionsCommon.h
|
||||||
optimiser/UnusedPruner.cpp
|
optimiser/UnusedPruner.cpp
|
||||||
optimiser/UnusedPruner.h
|
optimiser/UnusedPruner.h
|
||||||
optimiser/VarDeclInitializer.cpp
|
optimiser/VarDeclInitializer.cpp
|
||||||
|
@ -60,6 +60,8 @@ public:
|
|||||||
void operator()(FunctionCall& _funCall) override;
|
void operator()(FunctionCall& _funCall) override;
|
||||||
void operator()(Block& _block) override;
|
void operator()(Block& _block) override;
|
||||||
|
|
||||||
|
std::map<YulString, YulString> const& translations() const { return m_translations; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Check if the newly introduced identifier @a _name has to be replaced.
|
/// Check if the newly introduced identifier @a _name has to be replaced.
|
||||||
void checkAndReplaceNew(YulString& _name);
|
void checkAndReplaceNew(YulString& _name);
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include <libyul/optimiser/ForLoopInitRewriter.h>
|
#include <libyul/optimiser/ForLoopInitRewriter.h>
|
||||||
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
|
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
|
||||||
#include <libyul/optimiser/Rematerialiser.h>
|
#include <libyul/optimiser/Rematerialiser.h>
|
||||||
|
#include <libyul/optimiser/UnusedFunctionParameterPruner.h>
|
||||||
#include <libyul/optimiser/UnusedPruner.h>
|
#include <libyul/optimiser/UnusedPruner.h>
|
||||||
#include <libyul/optimiser/ExpressionSimplifier.h>
|
#include <libyul/optimiser/ExpressionSimplifier.h>
|
||||||
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
|
#include <libyul/optimiser/CommonSubexpressionEliminator.h>
|
||||||
@ -185,6 +186,7 @@ map<string, unique_ptr<OptimiserStep>> const& OptimiserSuite::allSteps()
|
|||||||
SSAReverser,
|
SSAReverser,
|
||||||
SSATransform,
|
SSATransform,
|
||||||
StructuralSimplifier,
|
StructuralSimplifier,
|
||||||
|
UnusedFunctionParameterPruner,
|
||||||
UnusedPruner,
|
UnusedPruner,
|
||||||
VarDeclInitializer
|
VarDeclInitializer
|
||||||
>();
|
>();
|
||||||
@ -221,6 +223,7 @@ map<string, char> const& OptimiserSuite::stepNameToAbbreviationMap()
|
|||||||
{SSAReverser::name, 'V'},
|
{SSAReverser::name, 'V'},
|
||||||
{SSATransform::name, 'a'},
|
{SSATransform::name, 'a'},
|
||||||
{StructuralSimplifier::name, 't'},
|
{StructuralSimplifier::name, 't'},
|
||||||
|
{UnusedFunctionParameterPruner::name, 'p'},
|
||||||
{UnusedPruner::name, 'u'},
|
{UnusedPruner::name, 'u'},
|
||||||
{VarDeclInitializer::name, 'd'},
|
{VarDeclInitializer::name, 'd'},
|
||||||
};
|
};
|
||||||
|
127
libyul/optimiser/UnusedFunctionParameterPruner.cpp
Normal file
127
libyul/optimiser/UnusedFunctionParameterPruner.cpp
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
/**
|
||||||
|
* UnusedFunctionParameterPruner: Optimiser step that removes unused parameters from function
|
||||||
|
* definition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libyul/optimiser/UnusedFunctionParameterPruner.h>
|
||||||
|
#include <libyul/optimiser/UnusedFunctionsCommon.h>
|
||||||
|
#include <libyul/optimiser/OptimiserStep.h>
|
||||||
|
#include <libyul/optimiser/NameCollector.h>
|
||||||
|
#include <libyul/optimiser/NameDisplacer.h>
|
||||||
|
#include <libyul/optimiser/NameDispenser.h>
|
||||||
|
#include <libyul/YulString.h>
|
||||||
|
#include <libyul/AsmData.h>
|
||||||
|
|
||||||
|
#include <libsolutil/CommonData.h>
|
||||||
|
|
||||||
|
#include <boost/algorithm/cxx11/all_of.hpp>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace solidity::util;
|
||||||
|
using namespace solidity::yul;
|
||||||
|
using namespace solidity::yul::unusedFunctionsCommon;
|
||||||
|
|
||||||
|
void UnusedFunctionParameterPruner::run(OptimiserStepContext& _context, Block& _ast)
|
||||||
|
{
|
||||||
|
map<YulString, size_t> references = ReferencesCounter::countReferences(_ast);
|
||||||
|
auto used = [&](auto v) -> bool { return references.count(v.name); };
|
||||||
|
|
||||||
|
// Function name and a pair of boolean masks, the first corresponds to parameters and the second
|
||||||
|
// corresponds to returnVariables.
|
||||||
|
//
|
||||||
|
// For the first vector in the pair, a value `false` at index `i` indicates that the function
|
||||||
|
// argument at index `i` in `FunctionDefinition::parameters` is unused inside the function body.
|
||||||
|
//
|
||||||
|
// Similarly for the second vector in the pair, a value `false` at index `i` indicates that the
|
||||||
|
// return parameter at index `i` in `FunctionDefinition::returnVariables` is unused inside
|
||||||
|
// function body.
|
||||||
|
map<YulString, pair<vector<bool>, vector<bool>>> usedParametersAndReturnVariables;
|
||||||
|
|
||||||
|
// Step 1 of UnusedFunctionParameterPruner: Find functions whose parameters (both arguments and
|
||||||
|
// return-parameters) are not used in its body.
|
||||||
|
for (auto const& statement: _ast.statements)
|
||||||
|
if (holds_alternative<FunctionDefinition>(statement))
|
||||||
|
{
|
||||||
|
FunctionDefinition const& f = std::get<FunctionDefinition>(statement);
|
||||||
|
|
||||||
|
if (tooSimpleToBePruned(f) || boost::algorithm::all_of(f.parameters + f.returnVariables, used))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
usedParametersAndReturnVariables[f.name] = {
|
||||||
|
applyMap(f.parameters, used),
|
||||||
|
applyMap(f.returnVariables, used)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
set<YulString> functionNamesToFree = util::keys(usedParametersAndReturnVariables);
|
||||||
|
|
||||||
|
// Step 2 of UnusedFunctionParameterPruner: Renames the function and replaces all references to
|
||||||
|
// the function, say `f`, by its new name, say `f_1`.
|
||||||
|
NameDisplacer replace{_context.dispenser, functionNamesToFree};
|
||||||
|
replace(_ast);
|
||||||
|
|
||||||
|
// Inverse-Map of the above translations. In the above example, this will store an element with
|
||||||
|
// key `f_1` and value `f`.
|
||||||
|
std::map<YulString, YulString> newToOriginalNames = invertMap(replace.translations());
|
||||||
|
|
||||||
|
// Step 3 of UnusedFunctionParameterPruner: introduce a new function in the block with body of
|
||||||
|
// the old one. Replace the body of the old one with a function call to the new one with reduced
|
||||||
|
// parameters.
|
||||||
|
//
|
||||||
|
// For example: introduce a new 'linking' function `f` with the same the body as `f_1`, but with
|
||||||
|
// reduced parameters, i.e., `function f() -> y { y := 1 }`. Now replace the body of `f_1` with
|
||||||
|
// a call to `f`, i.e., `f_1(x) -> y { y := f() }`.
|
||||||
|
iterateReplacing(_ast.statements, [&](Statement& _s) -> optional<vector<Statement>> {
|
||||||
|
if (holds_alternative<FunctionDefinition>(_s))
|
||||||
|
{
|
||||||
|
// The original function except that it has a new name (e.g., `f_1`)
|
||||||
|
FunctionDefinition& originalFunction = get<FunctionDefinition>(_s);
|
||||||
|
if (newToOriginalNames.count(originalFunction.name))
|
||||||
|
{
|
||||||
|
|
||||||
|
YulString linkingFunctionName = originalFunction.name;
|
||||||
|
YulString originalFunctionName = newToOriginalNames.at(linkingFunctionName);
|
||||||
|
pair<vector<bool>, vector<bool>> used =
|
||||||
|
usedParametersAndReturnVariables.at(originalFunctionName);
|
||||||
|
|
||||||
|
FunctionDefinition linkingFunction = createLinkingFunction(
|
||||||
|
originalFunction,
|
||||||
|
used,
|
||||||
|
originalFunctionName,
|
||||||
|
linkingFunctionName,
|
||||||
|
_context.dispenser
|
||||||
|
);
|
||||||
|
|
||||||
|
originalFunction.name = originalFunctionName;
|
||||||
|
originalFunction.parameters =
|
||||||
|
filter(originalFunction.parameters, used.first);
|
||||||
|
originalFunction.returnVariables =
|
||||||
|
filter(originalFunction.returnVariables, used.second);
|
||||||
|
|
||||||
|
return make_vector<Statement>(move(originalFunction), move(linkingFunction));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullopt;
|
||||||
|
});
|
||||||
|
}
|
52
libyul/optimiser/UnusedFunctionParameterPruner.h
Normal file
52
libyul/optimiser/UnusedFunctionParameterPruner.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libyul/optimiser/OptimiserStep.h>
|
||||||
|
|
||||||
|
namespace solidity::yul
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UnusedFunctionParameterPruner: Optimiser step that removes unused parameters in a function.
|
||||||
|
*
|
||||||
|
* If a parameter is unused, like `c` and `y` in, `function f(a,b,c) -> x, y { x := div(a,b) }`
|
||||||
|
*
|
||||||
|
* We remove the parameter and create a new "linking" function as follows:
|
||||||
|
*
|
||||||
|
* `function f(a,b) -> x { x := div(a,b) }`
|
||||||
|
* `function f2(a,b,c) -> x, y { x := f(a,b) }`
|
||||||
|
*
|
||||||
|
* and replace all references to `f` by `f2`.
|
||||||
|
* The inliner should be run afterwards to make sure that all references to `f2` are replaced by
|
||||||
|
* `f`.
|
||||||
|
*
|
||||||
|
* Prerequisites: Disambiguator, FunctionHoister, LiteralRematerialiser
|
||||||
|
*
|
||||||
|
* The step LiteralRematerialiser is not required for correctness. It helps deal with cases such as:
|
||||||
|
* `function f(x) -> y { revert(y, y} }` where the literal `y` will be replaced by its value `0`,
|
||||||
|
* allowing us to rewrite the function.
|
||||||
|
*/
|
||||||
|
struct UnusedFunctionParameterPruner
|
||||||
|
{
|
||||||
|
static constexpr char const* name{"UnusedFunctionParameterPruner"};
|
||||||
|
static void run(OptimiserStepContext& _context, Block& _ast);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
103
libyul/optimiser/UnusedFunctionsCommon.h
Normal file
103
libyul/optimiser/UnusedFunctionsCommon.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
This file is part of solidity.
|
||||||
|
|
||||||
|
solidity is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
solidity is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <libyul/optimiser/Metrics.h>
|
||||||
|
#include <libyul/optimiser/NameDispenser.h>
|
||||||
|
#include <libyul/AsmData.h>
|
||||||
|
#include <libyul/Dialect.h>
|
||||||
|
#include <libyul/Exceptions.h>
|
||||||
|
|
||||||
|
#include <liblangutil/SourceLocation.h>
|
||||||
|
|
||||||
|
#include <libsolutil/CommonData.h>
|
||||||
|
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
namespace solidity::yul::unusedFunctionsCommon
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::vector<T> filter(std::vector<T> const& _vec, std::vector<bool> const& _mask)
|
||||||
|
{
|
||||||
|
yulAssert(_vec.size() == _mask.size(), "");
|
||||||
|
|
||||||
|
std::vector<T> ret;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < _mask.size(); ++i)
|
||||||
|
if (_mask[i])
|
||||||
|
ret.push_back(_vec[i]);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if applying UnusedFunctionParameterPruner is not helpful or redundant because the
|
||||||
|
/// inliner will be able to handle it anyway.
|
||||||
|
bool tooSimpleToBePruned(FunctionDefinition const& _f)
|
||||||
|
{
|
||||||
|
return _f.body.statements.size() <= 1 && CodeSize::codeSize(_f.body) <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionDefinition createLinkingFunction(
|
||||||
|
FunctionDefinition const& _original,
|
||||||
|
std::pair<std::vector<bool>, std::vector<bool>> const& _usedParametersAndReturns,
|
||||||
|
YulString const& _originalFunctionName,
|
||||||
|
YulString const& _linkingFunctionName,
|
||||||
|
NameDispenser& _nameDispenser
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto generateTypedName = [&](TypedName t)
|
||||||
|
{
|
||||||
|
return TypedName{
|
||||||
|
t.location,
|
||||||
|
_nameDispenser.newName(t.name),
|
||||||
|
t.type
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
langutil::SourceLocation loc = _original.location;
|
||||||
|
|
||||||
|
FunctionDefinition linkingFunction{
|
||||||
|
loc,
|
||||||
|
_linkingFunctionName,
|
||||||
|
util::applyMap(_original.parameters, generateTypedName),
|
||||||
|
util::applyMap(_original.returnVariables, generateTypedName),
|
||||||
|
{loc, {}} // body
|
||||||
|
};
|
||||||
|
|
||||||
|
FunctionCall call{loc, Identifier{loc, _originalFunctionName}, {}};
|
||||||
|
for (auto const& p: filter(linkingFunction.parameters, _usedParametersAndReturns.first))
|
||||||
|
call.arguments.emplace_back(Identifier{loc, p.name});
|
||||||
|
|
||||||
|
Assignment assignment{loc, {}, nullptr};
|
||||||
|
|
||||||
|
for (auto const& r: filter(linkingFunction.returnVariables, _usedParametersAndReturns.second))
|
||||||
|
assignment.variableNames.emplace_back(Identifier{loc, r.name});
|
||||||
|
|
||||||
|
if (assignment.variableNames.empty())
|
||||||
|
linkingFunction.body.statements.emplace_back(ExpressionStatement{loc, std::move(call)});
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assignment.value = std::make_unique<Expression>(std::move(call));
|
||||||
|
linkingFunction.body.statements.emplace_back(std::move(assignment));
|
||||||
|
}
|
||||||
|
|
||||||
|
return linkingFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -49,6 +49,7 @@
|
|||||||
#include <libyul/optimiser/NameDisplacer.h>
|
#include <libyul/optimiser/NameDisplacer.h>
|
||||||
#include <libyul/optimiser/Rematerialiser.h>
|
#include <libyul/optimiser/Rematerialiser.h>
|
||||||
#include <libyul/optimiser/ExpressionSimplifier.h>
|
#include <libyul/optimiser/ExpressionSimplifier.h>
|
||||||
|
#include <libyul/optimiser/UnusedFunctionParameterPruner.h>
|
||||||
#include <libyul/optimiser/UnusedPruner.h>
|
#include <libyul/optimiser/UnusedPruner.h>
|
||||||
#include <libyul/optimiser/ExpressionJoiner.h>
|
#include <libyul/optimiser/ExpressionJoiner.h>
|
||||||
#include <libyul/optimiser/OptimiserStep.h>
|
#include <libyul/optimiser/OptimiserStep.h>
|
||||||
@ -241,6 +242,13 @@ TestCase::TestResult YulOptimizerTest::run(ostream& _stream, string const& _line
|
|||||||
ExpressionJoiner::run(*m_context, *m_object->code);
|
ExpressionJoiner::run(*m_context, *m_object->code);
|
||||||
ExpressionJoiner::run(*m_context, *m_object->code);
|
ExpressionJoiner::run(*m_context, *m_object->code);
|
||||||
}
|
}
|
||||||
|
else if (m_optimizerStep == "unusedFunctionParameterPruner")
|
||||||
|
{
|
||||||
|
disambiguate();
|
||||||
|
FunctionHoister::run(*m_context, *m_object->code);
|
||||||
|
LiteralRematerialiser::run(*m_context, *m_object->code);
|
||||||
|
UnusedFunctionParameterPruner::run(*m_context, *m_object->code);
|
||||||
|
}
|
||||||
else if (m_optimizerStep == "unusedPruner")
|
else if (m_optimizerStep == "unusedPruner")
|
||||||
{
|
{
|
||||||
disambiguate();
|
disambiguate();
|
||||||
|
@ -130,7 +130,7 @@ BOOST_AUTO_TEST_CASE(output_operator_should_create_concise_and_unambiguous_strin
|
|||||||
|
|
||||||
BOOST_TEST(chromosome.length() == allSteps.size());
|
BOOST_TEST(chromosome.length() == allSteps.size());
|
||||||
BOOST_TEST(chromosome.optimisationSteps() == allSteps);
|
BOOST_TEST(chromosome.optimisationSteps() == allSteps);
|
||||||
BOOST_TEST(toString(chromosome) == "flcCUnDvejsxIOoighTLMrmVatud");
|
BOOST_TEST(toString(chromosome) == "flcCUnDvejsxIOoighTLMrmVatpud");
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(randomOptimisationStep_should_return_each_step_with_same_probability)
|
BOOST_AUTO_TEST_CASE(randomOptimisationStep_should_return_each_step_with_same_probability)
|
||||||
|
@ -103,10 +103,10 @@ BOOST_AUTO_TEST_CASE(geneAddition_should_iterate_over_gene_positions_and_insert_
|
|||||||
SimulationRNG::reset(1);
|
SimulationRNG::reset(1);
|
||||||
// f c C U n D v e j s
|
// f c C U n D v e j s
|
||||||
BOOST_TEST(mutation01(chromosome) == Chromosome(stripWhitespace(" f c C UC n D v e jx s"))); // 20% more
|
BOOST_TEST(mutation01(chromosome) == Chromosome(stripWhitespace(" f c C UC n D v e jx s"))); // 20% more
|
||||||
BOOST_TEST(mutation05(chromosome) == Chromosome(stripWhitespace("j f cu C U ne D v eI j sf"))); // 50% more
|
BOOST_TEST(mutation05(chromosome) == Chromosome(stripWhitespace("s f cu C U nj D v eI j sf"))); // 50% more
|
||||||
SimulationRNG::reset(2);
|
SimulationRNG::reset(2);
|
||||||
BOOST_TEST(mutation01(chromosome) == Chromosome(stripWhitespace(" f cu C U n D v e j s"))); // 10% more
|
BOOST_TEST(mutation01(chromosome) == Chromosome(stripWhitespace(" f cu C U n D v e j s"))); // 10% more
|
||||||
BOOST_TEST(mutation05(chromosome) == Chromosome(stripWhitespace("L f ce Cv U n D v e jO s"))); // 40% more
|
BOOST_TEST(mutation05(chromosome) == Chromosome(stripWhitespace("M f ce Cv U n D v e jo s"))); // 40% more
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(geneAddition_should_be_able_to_insert_before_first_position)
|
BOOST_AUTO_TEST_CASE(geneAddition_should_be_able_to_insert_before_first_position)
|
||||||
|
Loading…
Reference in New Issue
Block a user