mirror of
https://github.com/graphhopper/jsprit.git
synced 2020-01-24 07:45:05 +01:00
Merge branch 'master' into prio-improvement
This commit is contained in:
commit
5fa1cea6af
4 changed files with 196 additions and 117 deletions
27
.travis.settings.xml
Normal file
27
.travis.settings.xml
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!--
|
||||||
|
~ Licensed to GraphHopper GmbH under one or more contributor
|
||||||
|
~ license agreements. See the NOTICE file distributed with this work for
|
||||||
|
~ additional information regarding copyright ownership.
|
||||||
|
~
|
||||||
|
~ GraphHopper GmbH licenses this file to you under the Apache License,
|
||||||
|
~ Version 2.0 (the "License"); you may not use this file except in
|
||||||
|
~ compliance with the License. You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
||||||
|
<servers>
|
||||||
|
<server>
|
||||||
|
<id>packagecloud-graphhopper</id>
|
||||||
|
<password>${env.PACKAGECLOUD_TOKEN}</password>
|
||||||
|
</server>
|
||||||
|
</servers>
|
||||||
|
</settings>
|
||||||
17
.travis.yml
17
.travis.yml
|
|
@ -4,3 +4,20 @@ jdk:
|
||||||
- oraclejdk7
|
- oraclejdk7
|
||||||
- oraclejdk8
|
- oraclejdk8
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
provider: script
|
||||||
|
script: "cp .travis.settings.xml $HOME/.m2/settings.xml && mvn deploy"
|
||||||
|
skip_cleanup: true
|
||||||
|
on:
|
||||||
|
tags: true
|
||||||
|
|
||||||
|
# do not install anything instead return true via unix command true
|
||||||
|
install: true
|
||||||
|
script: mvn clean test
|
||||||
|
notifications:
|
||||||
|
email:
|
||||||
|
- github@graphhopper.com
|
||||||
|
|
||||||
|
# enable container-based stack
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,121 +29,9 @@ import java.util.*;
|
||||||
*/
|
*/
|
||||||
public class UnassignedJobReasonTracker implements JobUnassignedListener {
|
public class UnassignedJobReasonTracker implements JobUnassignedListener {
|
||||||
|
|
||||||
Map<String, Frequency> reasons = new HashMap<>();
|
public static String getMostLikelyFailedConstraintName(Frequency failedConstraintNamesFrequency) {
|
||||||
|
if (failedConstraintNamesFrequency == null) return "no reason found";
|
||||||
Map<Integer, String> codesToReason = new HashMap<>();
|
Iterator<Map.Entry<Comparable<?>, Long>> entryIterator = failedConstraintNamesFrequency.entrySetIterator();
|
||||||
|
|
||||||
Map<String, Integer> failedConstraintNamesToCode = new HashMap<>();
|
|
||||||
|
|
||||||
Set<String> constraintsToBeIgnored = new HashSet<>();
|
|
||||||
|
|
||||||
public UnassignedJobReasonTracker() {
|
|
||||||
codesToReason.put(1, "cannot serve required skill");
|
|
||||||
codesToReason.put(2, "cannot be visited within time window");
|
|
||||||
codesToReason.put(3, "does not fit into any vehicle due to capacity");
|
|
||||||
codesToReason.put(4, "cannot be assigned due to max distance constraint of vehicle");
|
|
||||||
|
|
||||||
failedConstraintNamesToCode.put("HardSkillConstraint", 1);
|
|
||||||
failedConstraintNamesToCode.put("VehicleDependentTimeWindowConstraints", 2);
|
|
||||||
failedConstraintNamesToCode.put("ServiceLoadRouteLevelConstraint", 3);
|
|
||||||
failedConstraintNamesToCode.put("PickupAndDeliverShipmentLoadActivityLevelConstraint", 3);
|
|
||||||
failedConstraintNamesToCode.put("ServiceLoadActivityLevelConstraint", 3);
|
|
||||||
failedConstraintNamesToCode.put("MaxDistanceConstraint", 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ignore(String simpleNameOfConstraint) {
|
|
||||||
constraintsToBeIgnored.add(simpleNameOfConstraint);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void informJobUnassigned(Job unassigned, Collection<String> failedConstraintNames) {
|
|
||||||
if (!this.reasons.containsKey(unassigned.getId())) {
|
|
||||||
this.reasons.put(unassigned.getId(), new Frequency());
|
|
||||||
}
|
|
||||||
for (String r : failedConstraintNames) {
|
|
||||||
if (constraintsToBeIgnored.contains(r)) continue;
|
|
||||||
this.reasons.get(unassigned.getId()).addValue(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(String simpleNameOfFailedConstraint, int code, String reason) {
|
|
||||||
if (code <= 20)
|
|
||||||
throw new IllegalArgumentException("first 20 codes are reserved internally. choose a code > 20");
|
|
||||||
codesToReason.put(code, reason);
|
|
||||||
if (failedConstraintNamesToCode.containsKey(simpleNameOfFailedConstraint)) {
|
|
||||||
throw new IllegalArgumentException(simpleNameOfFailedConstraint + " already assigned to code and reason");
|
|
||||||
} else failedConstraintNamesToCode.put(simpleNameOfFailedConstraint, code);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For each job id, it returns frequency distribution of failed constraints (simple name of constraint) in an unmodifiable map.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Map<String, Frequency> getReasons() {
|
|
||||||
return Collections.unmodifiableMap(reasons);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an unmodifiable map of codes and reason pairs.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Map<Integer, String> getCodesToReason() {
|
|
||||||
return Collections.unmodifiableMap(codesToReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an unmodifiable map of constraint names (simple name of constraint) and reason code pairs.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Map<String, Integer> getFailedConstraintNamesToCode() {
|
|
||||||
return Collections.unmodifiableMap(failedConstraintNamesToCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most likely reason code i.e. the reason (failed constraint) being observed most often.
|
|
||||||
*
|
|
||||||
* 1 --> "cannot serve required skill
|
|
||||||
* 2 --> "cannot be visited within time window"
|
|
||||||
* 3 --> "does not fit into any vehicle due to capacity"
|
|
||||||
* 4 --> "cannot be assigned due to max distance constraint of vehicle"
|
|
||||||
*
|
|
||||||
* @param jobId
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public int getMostLikelyReasonCode(String jobId) {
|
|
||||||
if (!this.reasons.containsKey(jobId)) return -1;
|
|
||||||
Frequency reasons = this.reasons.get(jobId);
|
|
||||||
String mostLikelyReason = getMostLikely(reasons);
|
|
||||||
return toCode(mostLikelyReason);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most likely reason i.e. the reason (failed constraint) being observed most often.
|
|
||||||
*
|
|
||||||
* @param jobId
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getMostLikelyReason(String jobId) {
|
|
||||||
if (!this.reasons.containsKey(jobId)) return "no reason found";
|
|
||||||
Frequency reasons = this.reasons.get(jobId);
|
|
||||||
String mostLikelyReason = getMostLikely(reasons);
|
|
||||||
int code = toCode(mostLikelyReason);
|
|
||||||
if (code == -1) return mostLikelyReason;
|
|
||||||
else return codesToReason.get(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int toCode(String mostLikelyReason) {
|
|
||||||
if (failedConstraintNamesToCode.containsKey(mostLikelyReason))
|
|
||||||
return failedConstraintNamesToCode.get(mostLikelyReason);
|
|
||||||
else return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getMostLikely(Frequency reasons) {
|
|
||||||
if (reasons == null) return "no reason found";
|
|
||||||
Iterator<Map.Entry<Comparable<?>, Long>> entryIterator = reasons.entrySetIterator();
|
|
||||||
int maxCount = 0;
|
int maxCount = 0;
|
||||||
String mostLikely = null;
|
String mostLikely = null;
|
||||||
while (entryIterator.hasNext()) {
|
while (entryIterator.hasNext()) {
|
||||||
|
|
@ -156,5 +44,138 @@ public class UnassignedJobReasonTracker implements JobUnassignedListener {
|
||||||
return mostLikely;
|
return mostLikely;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<String, Frequency> failedConstraintNamesFrequencyMapping = new HashMap<>();
|
||||||
|
|
||||||
|
Map<Integer, String> codesToHumanReadableReason = new HashMap<>();
|
||||||
|
|
||||||
|
Map<String, Integer> failedConstraintNamesToCode = new HashMap<>();
|
||||||
|
|
||||||
|
Set<String> failedConstraintNamesToBeIgnored = new HashSet<>();
|
||||||
|
|
||||||
|
public UnassignedJobReasonTracker() {
|
||||||
|
codesToHumanReadableReason.put(1, "cannot serve required skill");
|
||||||
|
codesToHumanReadableReason.put(2, "cannot be visited within time window");
|
||||||
|
codesToHumanReadableReason.put(3, "does not fit into any vehicle due to capacity");
|
||||||
|
codesToHumanReadableReason.put(4, "cannot be assigned due to max distance constraint of vehicle");
|
||||||
|
|
||||||
|
failedConstraintNamesToCode.put("HardSkillConstraint", 1);
|
||||||
|
failedConstraintNamesToCode.put("VehicleDependentTimeWindowConstraints", 2);
|
||||||
|
failedConstraintNamesToCode.put("ServiceLoadRouteLevelConstraint", 3);
|
||||||
|
failedConstraintNamesToCode.put("PickupAndDeliverShipmentLoadActivityLevelConstraint", 3);
|
||||||
|
failedConstraintNamesToCode.put("ServiceLoadActivityLevelConstraint", 3);
|
||||||
|
failedConstraintNamesToCode.put("MaxDistanceConstraint", 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ignore(String simpleNameOfConstraint) {
|
||||||
|
failedConstraintNamesToBeIgnored.add(simpleNameOfConstraint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void informJobUnassigned(Job unassigned, Collection<String> failedConstraintNames) {
|
||||||
|
if (!this.failedConstraintNamesFrequencyMapping.containsKey(unassigned.getId())) {
|
||||||
|
this.failedConstraintNamesFrequencyMapping.put(unassigned.getId(), new Frequency());
|
||||||
|
}
|
||||||
|
for (String r : failedConstraintNames) {
|
||||||
|
if (failedConstraintNamesToBeIgnored.contains(r)) continue;
|
||||||
|
this.failedConstraintNamesFrequencyMapping.get(unassigned.getId()).addValue(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void put(String simpleNameOfFailedConstraint, int code, String reason) {
|
||||||
|
if (code <= 20)
|
||||||
|
throw new IllegalArgumentException("first 20 codes are reserved internally. choose a code > 20");
|
||||||
|
codesToHumanReadableReason.put(code, reason);
|
||||||
|
if (failedConstraintNamesToCode.containsKey(simpleNameOfFailedConstraint)) {
|
||||||
|
throw new IllegalArgumentException(simpleNameOfFailedConstraint + " already assigned to code and reason");
|
||||||
|
} else failedConstraintNamesToCode.put(simpleNameOfFailedConstraint, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each job id, it returns frequency distribution of failed constraints (simple name of constraint) in an unmodifiable map.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public Map<String, Frequency> getReasons() {
|
||||||
|
return Collections.unmodifiableMap(failedConstraintNamesFrequencyMapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each job id, it returns frequency distribution of failed constraints (simple name of constraint) in an unmodifiable map.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, Frequency> getFailedConstraintNamesFrequencyMapping() {
|
||||||
|
return Collections.unmodifiableMap(failedConstraintNamesFrequencyMapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an unmodifiable map of codes and reason pairs.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<Integer, String> getCodesToReason() {
|
||||||
|
return Collections.unmodifiableMap(codesToHumanReadableReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an unmodifiable map of constraint names (simple name of constraint) and reason code pairs.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Map<String, Integer> getFailedConstraintNamesToCode() {
|
||||||
|
return Collections.unmodifiableMap(failedConstraintNamesToCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCode(String failedConstraintName) {
|
||||||
|
return toCode(failedConstraintName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHumanReadableReason(int code) {
|
||||||
|
return getCodesToReason().get(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHumanReadableReason(String failedConstraintName) {
|
||||||
|
return getCodesToReason().get(getCode(failedConstraintName));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns the most likely reason code i.e. the reason (failed constraint) being observed most often.
|
||||||
|
*
|
||||||
|
* 1 --> "cannot serve required skill
|
||||||
|
* 2 --> "cannot be visited within time window"
|
||||||
|
* 3 --> "does not fit into any vehicle due to capacity"
|
||||||
|
* 4 --> "cannot be assigned due to max distance constraint of vehicle"
|
||||||
|
*
|
||||||
|
* @param jobId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getMostLikelyReasonCode(String jobId) {
|
||||||
|
if (!this.failedConstraintNamesFrequencyMapping.containsKey(jobId)) return -1;
|
||||||
|
Frequency reasons = this.failedConstraintNamesFrequencyMapping.get(jobId);
|
||||||
|
String mostLikelyReason = getMostLikelyFailedConstraintName(reasons);
|
||||||
|
return toCode(mostLikelyReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the most likely reason i.e. the reason (failed constraint) being observed most often.
|
||||||
|
*
|
||||||
|
* @param jobId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getMostLikelyReason(String jobId) {
|
||||||
|
if (!this.failedConstraintNamesFrequencyMapping.containsKey(jobId)) return "no reason found";
|
||||||
|
Frequency reasons = this.failedConstraintNamesFrequencyMapping.get(jobId);
|
||||||
|
String mostLikelyReason = getMostLikelyFailedConstraintName(reasons);
|
||||||
|
int code = toCode(mostLikelyReason);
|
||||||
|
if (code == -1) return mostLikelyReason;
|
||||||
|
else return codesToHumanReadableReason.get(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int toCode(String mostLikelyReason) {
|
||||||
|
if (failedConstraintNamesToCode.containsKey(mostLikelyReason))
|
||||||
|
return failedConstraintNamesToCode.get(mostLikelyReason);
|
||||||
|
else return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
18
pom.xml
18
pom.xml
|
|
@ -56,6 +56,7 @@
|
||||||
<tag>HEAD</tag>
|
<tag>HEAD</tag>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
|
|
||||||
<issueManagement>
|
<issueManagement>
|
||||||
<system>github</system>
|
<system>github</system>
|
||||||
<url>https://github.com/graphhopper/jsprit/issues</url>
|
<url>https://github.com/graphhopper/jsprit/issues</url>
|
||||||
|
|
@ -81,6 +82,15 @@
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
||||||
|
<extensions>
|
||||||
|
<extension>
|
||||||
|
<groupId>io.packagecloud.maven.wagon</groupId>
|
||||||
|
<artifactId>maven-packagecloud-wagon</artifactId>
|
||||||
|
<version>0.0.4</version>
|
||||||
|
</extension>
|
||||||
|
</extensions>
|
||||||
|
|
||||||
<sourceDirectory>src/main/java</sourceDirectory>
|
<sourceDirectory>src/main/java</sourceDirectory>
|
||||||
<testSourceDirectory>src/test/java</testSourceDirectory>
|
<testSourceDirectory>src/test/java</testSourceDirectory>
|
||||||
<directory>target</directory>
|
<directory>target</directory>
|
||||||
|
|
@ -180,9 +190,13 @@
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
|
<repository>
|
||||||
|
<id>packagecloud-graphhopper</id>
|
||||||
|
<url>packagecloud+https://packagecloud.io/graphhopper/jsprit</url>
|
||||||
|
</repository>
|
||||||
<snapshotRepository>
|
<snapshotRepository>
|
||||||
<id>ossrh</id>
|
<id>packagecloud-graphhopper</id>
|
||||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
<url>packagecloud+https://packagecloud.io/graphhopper/jsprit</url>
|
||||||
</snapshotRepository>
|
</snapshotRepository>
|
||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue