Index: doc/userguide/userguide.xml
===================================================================
--- doc/userguide/userguide.xml	(revision 78ea3cd9ca6cec043a55baf5de54c1feeb6b7609)
+++ doc/userguide/userguide.xml	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -879,4 +879,19 @@
         <link linkend='geometry'>Geometry</link>.</para>
         </section>
+        <section xml:id="atoms.random-perturbation">
+          <title xml:id="atoms.random-perturbation.title">Randomly perturb atoms</title>
+          <para>The positions of a set of selected atom(s) can be randomly 
+          perturbed by giving a maximum noise level..</para>
+          <programlisting>
+          ... --random-number-distribution "uniform_01"
+      --random-perturbation 0.1</programlisting>
+          <para>This will perturb all atomic positions by adding a vector
+          with components chosen randomly from the interval [-level, level].</para>
+          <para>Note that the manner these random numbers are picked depends
+          on the current random number distribution (and also on the engine),
+          see <link linkend='randomization'>Randomization</link>. The default
+          one will not give good results, therefore the example uses the 
+          uniform_01 distribution</para>
+        </section>
         <section xml:id="atoms.remove-atom">
           <title xml:id="atoms.remove-atom.title">Removing atoms</title>
Index: src/Actions/AtomAction/RandomPerturbationAction.cpp
===================================================================
--- src/Actions/AtomAction/RandomPerturbationAction.cpp	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
+++ src/Actions/AtomAction/RandomPerturbationAction.cpp	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -0,0 +1,123 @@
+/*
+ * Project: MoleCuilder
+ * Description: creates and alters molecular systems
+ * Copyright (C)  2017 Frederik Heber. All rights reserved.
+ * 
+ *
+ *   This file is part of MoleCuilder.
+ *
+ *    MoleCuilder 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 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    MoleCuilder 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 MoleCuilder.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * RandomPerturbationAction.cpp
+ *
+ *  Created on: Apr 2, 2017
+ *      Author: heber
+ */
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+//#include "CodePatterns/MemDebug.hpp"
+
+#include "CodePatterns/Log.hpp"
+#include "CodePatterns/Verbose.hpp"
+#include "LinearAlgebra/Vector.hpp"
+
+#include "Actions/UndoRedoHelpers.hpp"
+#include "Atom/atom.hpp"
+#include "Atom/AtomicInfo.hpp"
+#include "RandomNumbers/RandomNumberGenerator.hpp"
+#include "RandomNumbers/RandomNumberGeneratorFactory.hpp"
+#include "World.hpp"
+
+#include <iostream>
+#include <map>
+#include <string>
+
+#include "Actions/AtomAction/RandomPerturbationAction.hpp"
+
+using namespace MoleCuilder;
+
+// and construct the stuff
+#include "RandomPerturbationAction.def"
+#include "Action_impl_pre.hpp"
+/** =========== define the function ====================== */
+ActionState::ptr AtomRandomPerturbationAction::performCall() {
+  // check preconditions
+  if (World::getInstance().countSelectedAtoms() == 0) {
+    STATUS("No atoms are selected whose positions to randomly perturb.");
+    return Action::failure;
+  }
+
+  // create undo state
+  std::vector<AtomicInfo> Walkers;
+  for (World::AtomSelectionConstIterator iter = World::getInstance().beginAtomSelection();
+      iter != World::getInstance().endAtomSelection();
+      ++iter) {
+    Walkers.push_back(AtomicInfo(*(iter->second)));
+  }
+
+  // prepare noise generator
+  RandomNumberGenerator &random = RandomNumberGeneratorFactory::getInstance().makeRandomNumberGenerator();
+  const double rng_min = random.min();
+  const double rng_max = random.max();
+  const double range = (rng_max - rng_min);
+  const double offset = rng_min;
+
+  std::vector<AtomicInfo> NewWalkers;
+  for (World::AtomSelectionIterator iter = World::getInstance().beginAtomSelection(); iter != World::getInstance().endAtomSelection(); ++iter) {
+    atom *first = iter->second;
+    double noisecomponents[NDIM];
+    for (size_t i=0;i<NDIM;++i)
+      noisecomponents[i] = params.noise.get()*((random()-offset)*2./range - 1.);
+    const Vector noisevector(noisecomponents);
+    LOG(3, "DEBUG: Changing atom " << *first << "'s position by " << noisevector << ".");
+    first->setPosition(first->getPosition() + noisevector);
+    NewWalkers.push_back(AtomicInfo(*first));
+  }
+
+  AtomRandomPerturbationState *UndoState = new AtomRandomPerturbationState(Walkers, NewWalkers, params);
+  return ActionState::ptr(UndoState);
+}
+
+ActionState::ptr AtomRandomPerturbationAction::performUndo(ActionState::ptr _state) {
+  AtomRandomPerturbationState *state = assert_cast<AtomRandomPerturbationState*>(_state.get());
+
+  // set stored old state
+  SetAtomsFromAtomicInfo(state->Walkers);
+
+  return ActionState::ptr(_state);
+}
+
+ActionState::ptr AtomRandomPerturbationAction::performRedo(ActionState::ptr _state){
+  AtomRandomPerturbationState *state = assert_cast<AtomRandomPerturbationState*>(_state.get());
+
+  // perturb with same noise vectors
+  SetAtomsFromAtomicInfo(state->NewWalkers);
+
+  return ActionState::ptr(_state);
+}
+
+bool AtomRandomPerturbationAction::canUndo() {
+  return true;
+}
+
+bool AtomRandomPerturbationAction::shouldUndo() {
+  return true;
+}
+/** =========== end of function ====================== */
Index: src/Actions/AtomAction/RandomPerturbationAction.def
===================================================================
--- src/Actions/AtomAction/RandomPerturbationAction.def	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
+++ src/Actions/AtomAction/RandomPerturbationAction.def	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -0,0 +1,34 @@
+/*
+ * RandomPerturbationAction.def
+ *
+ *  Created on: Apr 02, 2017
+ *      Author: heber
+ */
+
+// all includes and forward declarations necessary for non-integral types below
+#include "Parameters/Validators/DummyValidator.hpp"
+
+// i.e. there is an integer with variable name Z that can be found in
+// ValueStorage by the token "Z" -> first column: int, Z, "Z"
+// "undefine" if no parameters are required, use (NOPARAM_DEFAULT) for each (undefined) default value
+#define paramtypes (double)
+#define paramtokens ("random-perturbation")
+#define paramdescriptions ("maximum strength of random perturbation")
+#define paramdefaults (NOPARAM_DEFAULTS())
+#define paramreferences (noise)
+#define paramvalids \
+(DummyValidator<double>())
+
+#define statetypes (std::vector<AtomicInfo>)(std::vector<AtomicInfo>)
+#define statereferences (Walkers)(NewWalkers)
+
+// some defines for all the names, you may use ACTION, STATE and PARAMS
+#define CATEGORY Atom
+#define MENUNAME "atom"
+#define MENUPOSITION 9
+#define ACTIONNAME RandomPerturbation
+#define TOKEN "random-perturbation"
+
+// finally the information stored in the ActionTrait specialization
+#define DESCRIPTION "randomly perturb the position of all selected atoms up to a given strength"
+#undef SHORTFORM
Index: src/Actions/AtomAction/RandomPerturbationAction.hpp
===================================================================
--- src/Actions/AtomAction/RandomPerturbationAction.hpp	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
+++ src/Actions/AtomAction/RandomPerturbationAction.hpp	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -0,0 +1,21 @@
+/*
+ * RandomPerturbationAction.hpp
+ *
+ *  Created on: Apr 2, 2017
+ *      Author: heber
+ */
+
+#ifndef RANDOMPERTURBATIONACTION_HPP_
+#define RANDOMPERTURBATIONACTION_HPP_
+
+// include config.h
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "Actions/Action.hpp"
+
+#include "RandomPerturbationAction.def"
+#include "Action_impl_header.hpp"
+
+#endif /* RANDOMPERTURBATIONACTION_HPP_ */
Index: src/Actions/GlobalListOfActions.hpp
===================================================================
--- src/Actions/GlobalListOfActions.hpp	(revision 78ea3cd9ca6cec043a55baf5de54c1feeb6b7609)
+++ src/Actions/GlobalListOfActions.hpp	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -33,4 +33,5 @@
   (AtomChangeElement) \
   (AtomMirror) \
+  (AtomRandomPerturbation) \
   (AtomRemove) \
   (AtomRotateAroundOriginByAngle) \
Index: src/Actions/Makefile.am
===================================================================
--- src/Actions/Makefile.am	(revision 78ea3cd9ca6cec043a55baf5de54c1feeb6b7609)
+++ src/Actions/Makefile.am	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -152,4 +152,5 @@
   Actions/AtomAction/ChangeElementAction.cpp \
   Actions/AtomAction/MirrorAction.cpp \
+  Actions/AtomAction/RandomPerturbationAction.cpp \
   Actions/AtomAction/RemoveAction.cpp \
   Actions/AtomAction/RotateAroundOriginByAngleAction.cpp \
@@ -163,4 +164,5 @@
   Actions/AtomAction/MirrorAction.hpp \
   Actions/AtomAction/RemoveAction.hpp \
+  Actions/AtomAction/RandomPerturbationAction.hpp \
   Actions/AtomAction/RotateAroundOriginByAngleAction.hpp \
   Actions/AtomAction/SaturateAction.hpp \
@@ -172,4 +174,5 @@
   Actions/AtomAction/ChangeElementAction.def \
   Actions/AtomAction/MirrorAction.def \
+  Actions/AtomAction/RandomPerturbationAction.def \
   Actions/AtomAction/RemoveAction.def \
   Actions/AtomAction/RotateAroundOriginByAngleAction.def \
Index: tests/Python/AllActions/options.dat
===================================================================
--- tests/Python/AllActions/options.dat	(revision 78ea3cd9ca6cec043a55baf5de54c1feeb6b7609)
+++ tests/Python/AllActions/options.dat	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -163,4 +163,5 @@
 random-number-distribution-parameters	"max=20;"
 random-number-engine-parameters	"seed=2;"
+random-perturbation	"0.1"
 remove-geometry	"named_vector"
 repeat-box	"1 1 1"
Index: tests/regression/Atoms/RandomPerturbation/post/water.xyz
===================================================================
--- tests/regression/Atoms/RandomPerturbation/post/water.xyz	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
+++ tests/regression/Atoms/RandomPerturbation/post/water.xyz	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -0,0 +1,5 @@
+3
+	Created by molecuilder on Sun Apr  2 21:55:57 2017, time step 0
+O	9.9	9.9	10.1
+H	9.2	10.1	9.9
+H	10.6	10.1	10.1
Index: tests/regression/Atoms/RandomPerturbation/pre/water.xyz
===================================================================
--- tests/regression/Atoms/RandomPerturbation/pre/water.xyz	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
+++ tests/regression/Atoms/RandomPerturbation/pre/water.xyz	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -0,0 +1,5 @@
+3
+	created for AtomsRandomPerturbation on 2017-04-02 21:27
+O	10	10	10
+H	9.3	10	10
+H	10.7	10	10
Index: tests/regression/Atoms/RandomPerturbation/testsuite-atoms-random-perturbation.at
===================================================================
--- tests/regression/Atoms/RandomPerturbation/testsuite-atoms-random-perturbation.at	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
+++ tests/regression/Atoms/RandomPerturbation/testsuite-atoms-random-perturbation.at	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -0,0 +1,43 @@
+#
+#    MoleCuilder - creates and alters molecular systems
+#    Copyright (C) 2017 Frederik Heber
+#
+#    This program 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.
+#
+#    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+### randomly perturb atom
+
+AT_SETUP([Atoms - random perturbation])
+AT_KEYWORDS([atoms random-perturbation])
+file=water.xyz
+AT_CHECK([cp -f ${abs_top_srcdir}/tests/regression/Atoms/RandomPerturbation/pre/water.xyz $file], 0, [ignore], [ignore])
+AT_CHECK([../../molecuilder -i water.xyz --set-random-number-distribution "uniform_int" --random-number-distribution-parameters "max=1;" --select-all-atoms --random-perturbation 0.1], 0, [ignore], [ignore])
+AT_CHECK([diff -I '.*reated' $file ${abs_top_srcdir}/tests/regression/Atoms/RandomPerturbation/post/water.xyz], 0, [ignore], [ignore])
+AT_CLEANUP
+
+AT_SETUP([Atoms - random perturbation with Undo])
+AT_KEYWORDS([atoms random-perturbation undo])
+file=water.xyz
+AT_CHECK([cp -f ${abs_top_srcdir}/tests/regression/Atoms/RandomPerturbation/pre/water.xyz $file], 0, [ignore], [ignore])
+AT_CHECK([../../molecuilder -i water.xyz --set-random-number-distribution "uniform_int" --random-number-distribution-parameters "max=1;" --select-all-atoms --random-perturbation 0.1 --undo], 0, [ignore], [ignore])
+AT_CHECK([diff -I '.*reated' $file ${abs_top_srcdir}/tests/regression/Atoms/RandomPerturbation/pre/water.xyz], 0, [ignore], [ignore])
+AT_CLEANUP
+
+
+AT_SETUP([Atoms - random perturbation with Redo])
+AT_KEYWORDS([atoms random-perturbation redo])
+file=water.xyz
+AT_CHECK([cp -f ${abs_top_srcdir}/tests/regression/Atoms/RandomPerturbation/pre/water.xyz $file], 0, [ignore], [ignore])
+AT_CHECK([../../molecuilder -i water.xyz --set-random-number-distribution "uniform_int" --random-number-distribution-parameters "max=1;" --select-all-atoms --random-perturbation 0.1 --undo --redo], 0, [ignore], [ignore])
+AT_CHECK([diff -I '.*reated' $file ${abs_top_srcdir}/tests/regression/Atoms/RandomPerturbation/post/water.xyz], 0, [ignore], [ignore])
+AT_CLEANUP
Index: tests/regression/Atoms/testsuite-atoms.at
===================================================================
--- tests/regression/Atoms/testsuite-atoms.at	(revision 78ea3cd9ca6cec043a55baf5de54c1feeb6b7609)
+++ tests/regression/Atoms/testsuite-atoms.at	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -49,2 +49,5 @@
 m4_include([Atoms/Saturate/testsuite-atoms-saturate-atoms-nitrogen.at])
 m4_include([Atoms/Saturate/testsuite-atoms-saturate-atoms-bonded_atoms.at])
+
+# mirror atoms
+m4_include([Atoms/RandomPerturbation/testsuite-atoms-random-perturbation.at])
Index: tests/regression/Makefile.am
===================================================================
--- tests/regression/Makefile.am	(revision 78ea3cd9ca6cec043a55baf5de54c1feeb6b7609)
+++ tests/regression/Makefile.am	(revision 310445ae3f74d3bff54d4b01f5f6129317e83a7e)
@@ -60,4 +60,5 @@
 	$(srcdir)/Atoms/ChangeElement/testsuite-atoms-change-element.at \
 	$(srcdir)/Atoms/Mirror/testsuite-atoms-mirror.at \
+	$(srcdir)/Atoms/RandomPerturbation/testsuite-atoms-random-perturbation.at \
 	$(srcdir)/Atoms/Remove/testsuite-atoms-remove.at \
 	$(srcdir)/Atoms/RemoveCuboid/testsuite-atoms-remove-cuboid.at \
