diff --git a/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/RegretInsertion.java b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/RegretInsertion.java
new file mode 100644
index 00000000..008b8784
--- /dev/null
+++ b/jsprit-core/src/main/java/jsprit/core/algorithm/recreate/RegretInsertion.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (C) 2014 Stefan Schroeder
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3.0 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
Basically calculates the insertion cost of the firstBest and the secondBest alternative. The score is then calculated as difference +* between secondBest and firstBest, plus additional scoring variables that can defined in this.ScoringFunction. +* The idea is that if the cost of the secondBest alternative is way higher than the first best, it seems to be important to insert this +* customer immediatedly. If difference is not that high, it might not impact solution if this customer is inserted later. +* +* @author stefan schroeder +* +*/ +public class RegretInsertion implements InsertionStrategy{ + + + /** + * Scorer to include other impacts on score such as time-window length or distance to depot. + * + * @author schroeder + * + */ + static interface ScoringFunction { + + public double score(Job job); + + } + + /** + * Scorer that includes the length of the time-window when scoring a job. The wider the time-window, the lower the score. + * + *
This is the default scorer, i.e.: score = (secondBest - firstBest) + this.TimeWindowScorer.score(job) + * + * @author schroeder + * + */ + static class TimeWindowScorer implements ScoringFunction { + + private double tw_scoringParam = - 0.1; + + @Override + public double score(Job job) { + double twStart = 0.0; + double twEnd = 0.0; +// if(job instanceof Shipment){ +// twStart = ((Shipment) job).getDeliveryTW().getStart(); +// twEnd = ((Shipment) job).getDeliveryTW().getEnd(); +// } +// else + if(job instanceof Service){ + twStart = ((Service) job).getTimeWindow().getStart(); + twEnd = ((Service) job).getTimeWindow().getEnd(); + } + return (twEnd-twStart)*tw_scoringParam; + } + + @Override + public String toString() { + return "[name=timeWindowScorer][scoringParam="+tw_scoringParam+"]"; + } + + } + + public static RegretInsertion newInstance(RouteAlgorithm routeAlgorithm) { + return new RegretInsertion(routeAlgorithm); + } + + private Logger logger = Logger.getLogger(RegretInsertion.class); + + private RouteAlgorithm routeAlgorithm; + + private ScoringFunction scoringFunction = new TimeWindowScorer(); + + /** + * Sets the scoring function. + * + *
By default, the this.TimeWindowScorer is used. + * + * @param scoringFunction + */ + public void setScoringFunction(ScoringFunction scoringFunction) { + this.scoringFunction = scoringFunction; + } + + public RegretInsertion(RouteAlgorithm routeAlgorithm) { + super(); + this.routeAlgorithm = routeAlgorithm; + logger.info("initialise " + this); + } + + @Override + public String toString() { + return "[name=regretInsertion][additionalScorer="+scoringFunction+"]"; + } + + public RouteAlgorithm getRouteAlgorithm(){ + return routeAlgorithm; + } + + /** + * Runs insertion. + * + *
Before inserting a job, all unassigned jobs are scored according to its best- and secondBest-insertion plus additional scoring variables.
+ *
+ */
+ @Override
+ public void insertJobs(Collection