private bool IsMovedBetter(T movedSol, T solBeforeMove, Criterion <T> criterion)
        {
            if (criterion.IsFirstOneBetter(movedSol, solBeforeMove))
            {
                return(true);
            }

            double movedSolValue, unmovedSolValue;

            if (movedSol.IsFeasible)
            {
                movedSolValue   = criterion.CalculateSolutionValue(movedSol);
                unmovedSolValue = criterion.CalculateSolutionValue(solBeforeMove);
            }
            else
            {
                movedSolValue   = movedSol.CalculatedPenalty;
                unmovedSolValue = solBeforeMove.CalculatedPenalty;
            }

            var diff =
                criterion.OptimizationType == OptimizationType.Minimization
                    ? unmovedSolValue - movedSolValue
                    : movedSolValue - unmovedSolValue;

            if (diff == 0)
            {
                return(false);
            }

            return(diff > 0 || AtEndOfIsMovedBetter(diff));
        }