def _rough_shake(self, x, normals, values, error):
counter = <NUM_LIT:0><EOL>while error > self.threshold and counter < self.max_iter:<EOL><INDENT>dxs = []<EOL>for i in range(len(normals)):<EOL><INDENT>dx = -normals[i]*values[i]/np.dot(normals[i], normals[i])<EOL>dxs.append(dx)<EOL><DEDENT>dxs = np.array(dxs)<EOL>dx = dxs[abs(values).argmax()]<EOL>x = x+dx<EOL>self.lock[:] = False<EOL>normals, values, error = self._compute_equations(x)[:-<NUM_LIT:1>]<EOL>counter += <NUM_LIT:1><EOL><DEDENT>return x, normals, values, error<EOL>
Take a robust, but not very efficient step towards the constraints.

           Arguments:
            | ``x`` -- The unknowns.
            | ``normals`` -- A numpy array with the gradients of the active
                             constraints. Each row is one gradient.
            | ``values`` -- A numpy array with the values of the constraint
                            functions.
            | ``error`` -- The square root of the constraint cost function.