diff --git a/src/mlpack/methods/ann/layer/multiply_constant.hpp b/src/mlpack/methods/ann/layer/multiply_constant.hpp index 7ce5c1248a..baa4744c23 100644 --- a/src/mlpack/methods/ann/layer/multiply_constant.hpp +++ b/src/mlpack/methods/ann/layer/multiply_constant.hpp @@ -39,6 +39,18 @@ class MultiplyConstant */ MultiplyConstant(const double scalar = 1.0); + //! Copy Constructor. + MultiplyConstant(const MultiplyConstant& layer); + + //! Move Constructor. + MultiplyConstant(MultiplyConstant&& layer); + + //! Copy assignment operator. + MultiplyConstant& operator=(const MultiplyConstant& layer); + + //! Move assignment operator. + MultiplyConstant& operator=(MultiplyConstant&& layer); + /** * Ordinary feed forward pass of a neural network. Multiply the input with the * specified constant scalar value. diff --git a/src/mlpack/methods/ann/layer/multiply_constant_impl.hpp b/src/mlpack/methods/ann/layer/multiply_constant_impl.hpp index 7b8cf13e0c..4c02fbd1fa 100644 --- a/src/mlpack/methods/ann/layer/multiply_constant_impl.hpp +++ b/src/mlpack/methods/ann/layer/multiply_constant_impl.hpp @@ -26,6 +26,46 @@ MultiplyConstant::MultiplyConstant( // Nothing to do here. } +template +MultiplyConstant::MultiplyConstant( + const MultiplyConstant& layer) : + scalar(layer.scalar) +{ + // Nothing to do here. +} + +template +MultiplyConstant::MultiplyConstant( + MultiplyConstant&& layer) : + scalar(std::move(layer.scalar)) +{ + // Nothing to do here. +} + +template +MultiplyConstant& +MultiplyConstant::operator=( + const MultiplyConstant& layer) +{ + if (this != &layer) + { + scalar = layer.scalar; + } + return *this; +} + +template +MultiplyConstant& +MultiplyConstant::operator=( + MultiplyConstant&& layer) +{ + if (this != &layer) + { + scalar = std::move(layer.scalar); + } + return *this; +} + template template void MultiplyConstant::Forward( diff --git a/src/mlpack/methods/ann/layer/multiply_merge.hpp b/src/mlpack/methods/ann/layer/multiply_merge.hpp index d79818653d..5c3d9ba6c0 100644 --- a/src/mlpack/methods/ann/layer/multiply_merge.hpp +++ b/src/mlpack/methods/ann/layer/multiply_merge.hpp @@ -50,6 +50,18 @@ class MultiplyMerge */ MultiplyMerge(const bool model = false, const bool run = true); + //! Copy Constructor. + MultiplyMerge(const MultiplyMerge& layer); + + //! Move Constructor. + MultiplyMerge(MultiplyMerge&& layer); + + //! Copy assignment operator. + MultiplyMerge& operator=(const MultiplyMerge& layer); + + //! Move assignment operator. + MultiplyMerge& operator=(MultiplyMerge&& layer); + //! Destructor to release allocated memory. ~MultiplyMerge(); diff --git a/src/mlpack/methods/ann/layer/multiply_merge_impl.hpp b/src/mlpack/methods/ann/layer/multiply_merge_impl.hpp index ee4c8ed917..29cd111482 100644 --- a/src/mlpack/methods/ann/layer/multiply_merge_impl.hpp +++ b/src/mlpack/methods/ann/layer/multiply_merge_impl.hpp @@ -32,6 +32,66 @@ MultiplyMerge::MultiplyMerge( // Nothing to do here. } +template +MultiplyMerge::MultiplyMerge( + const MultiplyMerge& layer) : + model(layer.model), + run(layer.run), + ownsLayer(layer.ownsLayer), + network(layer.network), + weights(layer.weights) +{ + // Nothing to do here. +} + +template +MultiplyMerge::MultiplyMerge( + MultiplyMerge&& layer) : + model(std::move(layer.model)), + run(std::move(layer.run)), + ownsLayer(std::move(layer.ownsLayer)), + network(std::move(layer.network)), + weights(std::move(layer.weights)) +{ + // Nothing to do here. +} + +template +MultiplyMerge& +MultiplyMerge::operator=( + const MultiplyMerge& layer) +{ + if (this != &layer) + { + model = layer.model; + run = layer.run; + ownsLayer = layer.ownsLayer; + network = layer.network; + weights = layer.weights; + } + return *this; +} + +template +MultiplyMerge& +MultiplyMerge::operator=( + MultiplyMerge&& layer) +{ + if (this != &layer) + { + model = std::move(layer.model); + run = std::move(layer.run); + ownsLayer = std::move(layer.ownsLayer); + network = std::move(layer.network); + weights = std::move(layer.weights); + } + return *this; +} + template MultiplyMerge::~MultiplyMerge() diff --git a/src/mlpack/methods/ann/rnn_impl.hpp b/src/mlpack/methods/ann/rnn_impl.hpp index 2852dcceef..5077eb9896 100644 --- a/src/mlpack/methods/ann/rnn_impl.hpp +++ b/src/mlpack/methods/ann/rnn_impl.hpp @@ -87,10 +87,10 @@ RNN::RNN( targetSize(std::move(network.targetSize)), reset(std::move(network.reset)), single(std::move(network.single)), + network(std::move(network.network)), parameter(std::move(network.parameter)), numFunctions(std::move(network.numFunctions)), - deterministic(std::move(network.deterministic)), - network(std::move(network.network)) + deterministic(std::move(network.deterministic)) { // Nothing to do here. } diff --git a/src/mlpack/tests/ann_layer_test.cpp b/src/mlpack/tests/ann_layer_test.cpp index 00376fd0a2..57514ccd44 100644 --- a/src/mlpack/tests/ann_layer_test.cpp +++ b/src/mlpack/tests/ann_layer_test.cpp @@ -897,6 +897,39 @@ TEST_CASE("JacobianMultiplyConstantLayerTest", "[ANNLayerTest]") } } +/** + * Check whether copying and moving network with MultiplyConstant is working or + * not. + */ +TEST_CASE("CheckCopyMoveMultiplyConstantTest", "[ANNLayerTest]") +{ + arma::mat input(2, 1000); + input.randu(); + + arma::mat output1; + arma::mat output2; + arma::mat output3; + arma::mat output4; + + MultiplyConstant<> *module1 = new MultiplyConstant<>(3.0); + module1->Forward(input, output1); + + MultiplyConstant<> module2 = *module1; + delete module1; + + module2.Forward(input, output2); + CheckMatrices(output1, output2); + + MultiplyConstant<> *module3 = new MultiplyConstant<>(3.0); + module3->Forward(input, output3); + + MultiplyConstant<> module4(std::move(*module3)); + delete module3; + + module4.Forward(input, output4); + CheckMatrices(output3, output4); +} + /** * Jacobian HardTanH module test. */ @@ -2593,6 +2626,56 @@ TEST_CASE("SimpleMultiplyMergeLayerTest", "[ANNLayerTest]") } } +/** + * Check whether copying and moving network with MultiplyMerge is working or + * not. + */ +TEST_CASE("CheckCopyMoveMultiplyMergeTest", "[ANNLayerTest]") +{ + arma::mat input(10, 1); + input.randu(); + + arma::mat output1; + arma::mat output2; + arma::mat output3; + arma::mat output4; + + const size_t numMergeModules = math::RandInt(2, 10); + + MultiplyMerge<> *module1 = new MultiplyMerge<>(true, false); + for (size_t m = 0; m < numMergeModules; ++m) + { + IdentityLayer<> identityLayer; + identityLayer.Forward(input, identityLayer.OutputParameter()); + + module1->Add >(identityLayer); + } + + module1->Forward(input, output1); + + MultiplyMerge<> module2 = *module1; + delete module1; + + module2.Forward(input, output2); + CheckMatrices(output1, output2); + + MultiplyMerge<> *module3 = new MultiplyMerge<>(true, false); + for (size_t m = 0; m < numMergeModules; ++m) + { + IdentityLayer<> identityLayer; + identityLayer.Forward(input, identityLayer.OutputParameter()); + + module3->Add >(identityLayer); + } + module3->Forward(input, output3); + + MultiplyMerge<> module4(std::move(*module3)); + delete module3; + + module4.Forward(input, output4); + CheckMatrices(output3, output4); +} + /** * Simple Atrous Convolution layer test. */