diff --git a/jsprit-core/src/main/java/jsprit/core/problem/io/JsonConstants.java b/jsprit-core/src/main/java/jsprit/core/problem/io/JsonConstants.java index 9b312297..8f51a679 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/io/JsonConstants.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/io/JsonConstants.java @@ -34,6 +34,15 @@ public class JsonConstants { public static final String VEHICLE_TYPES = "vehicle_types"; + public static final String META = "meta-info"; + + public static class MetaInfo { + + public static final String DISTANCE_UNIT = "distance-unit"; + + public static final String TIME_UNIT = "time-unit"; + } + public static class Solution { public static final String COSTS = "costs"; diff --git a/jsprit-core/src/main/java/jsprit/core/problem/io/VrpJsonReader.java b/jsprit-core/src/main/java/jsprit/core/problem/io/VrpJsonReader.java index 39457f8a..eb838d4d 100644 --- a/jsprit-core/src/main/java/jsprit/core/problem/io/VrpJsonReader.java +++ b/jsprit-core/src/main/java/jsprit/core/problem/io/VrpJsonReader.java @@ -33,7 +33,6 @@ import jsprit.core.problem.vehicle.VehicleTypeImpl; import jsprit.core.util.Coordinate; import java.io.File; -import java.io.FileReader; import java.io.IOException; import java.util.HashMap; import java.util.Iterator; @@ -69,7 +68,7 @@ public class VrpJsonReader { parse(root); } - public void parse(JsonNode problemRoot) { + private void parse(JsonNode problemRoot) { setFleetSize(problemRoot); parse_and_map_vehicle_types(problemRoot); parse_vehicles(problemRoot); @@ -92,7 +91,7 @@ public class VrpJsonReader { JsonNode node = null; try { ObjectMapper objectMapper = new ObjectMapper(); - node = objectMapper.readTree(new FileReader(jsonFile)).path(JsonConstants.PROBLEM); + node = objectMapper.readTree(jsonFile).path(JsonConstants.PROBLEM); } catch (IOException e) { e.printStackTrace(); System.exit(1); diff --git a/jsprit-core/src/main/java/jsprit/core/util/DistanceUnit.java b/jsprit-core/src/main/java/jsprit/core/util/DistanceUnit.java new file mode 100644 index 00000000..18accdbb --- /dev/null +++ b/jsprit-core/src/main/java/jsprit/core/util/DistanceUnit.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * 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 . + ******************************************************************************/ + +package jsprit.core.util; + +/** +* Created by schroeder on 04.12.14. +*/ +public enum DistanceUnit { + + Meter("m"), Kilometer("km"); + + private String abbr; + + DistanceUnit(String abbr) { + this.abbr = abbr; + } + + public String abbreviation(){ + return abbr; + } +} diff --git a/jsprit-core/src/main/java/jsprit/core/util/GreatCircleCosts.java b/jsprit-core/src/main/java/jsprit/core/util/GreatCircleCosts.java index 5c9166af..046f387e 100644 --- a/jsprit-core/src/main/java/jsprit/core/util/GreatCircleCosts.java +++ b/jsprit-core/src/main/java/jsprit/core/util/GreatCircleCosts.java @@ -51,7 +51,7 @@ public class GreatCircleCosts extends AbstractForwardVehicleRoutingTransportCost private Locations locations; - private GreatCircleDistanceCalculator.DistanceUnit distanceUnit = GreatCircleDistanceCalculator.DistanceUnit.Kilometer; + private DistanceUnit distanceUnit = DistanceUnit.Kilometer; public GreatCircleCosts(Locations locations) { super(); @@ -59,7 +59,7 @@ public class GreatCircleCosts extends AbstractForwardVehicleRoutingTransportCost } - public GreatCircleCosts(Locations locations, GreatCircleDistanceCalculator.DistanceUnit distanceUnit) { + public GreatCircleCosts(Locations locations, DistanceUnit distanceUnit) { super(); this.locations = locations; this.distanceUnit = distanceUnit; diff --git a/jsprit-core/src/main/java/jsprit/core/util/GreatCircleDistanceCalculator.java b/jsprit-core/src/main/java/jsprit/core/util/GreatCircleDistanceCalculator.java index 50b71c84..67188d28 100644 --- a/jsprit-core/src/main/java/jsprit/core/util/GreatCircleDistanceCalculator.java +++ b/jsprit-core/src/main/java/jsprit/core/util/GreatCircleDistanceCalculator.java @@ -22,12 +22,6 @@ package jsprit.core.util; */ public class GreatCircleDistanceCalculator { - public enum DistanceUnit { - - Meter, Kilometer - - } - private static final double R = 6372.8; // km /** diff --git a/jsprit-core/src/main/java/jsprit/core/util/TimeUnit.java b/jsprit-core/src/main/java/jsprit/core/util/TimeUnit.java new file mode 100644 index 00000000..5d5015bc --- /dev/null +++ b/jsprit-core/src/main/java/jsprit/core/util/TimeUnit.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * 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 . + ******************************************************************************/ + +package jsprit.core.util; + +/** + * Created by schroeder on 04.12.14. + */ +public enum TimeUnit { + + SEC("sec"), MIN("min"), HOUR("hour"); + + String abbr; + + TimeUnit(String abbr) { + this.abbr = abbr; + } + + public String abbreviation() { + return abbr; + } +} diff --git a/jsprit-core/src/test/java/jsprit/core/problem/io/VrpJsonReaderTest.java b/jsprit-core/src/test/java/jsprit/core/problem/io/VrpJsonReaderTest.java new file mode 100644 index 00000000..b7020105 --- /dev/null +++ b/jsprit-core/src/test/java/jsprit/core/problem/io/VrpJsonReaderTest.java @@ -0,0 +1,185 @@ +/******************************************************************************* + * 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 . + ******************************************************************************/ + +package jsprit.core.problem.io; + + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import jsprit.core.problem.VehicleRoutingProblem; +import jsprit.core.problem.job.Job; +import jsprit.core.problem.job.Service; +import jsprit.core.problem.vehicle.Vehicle; +import jsprit.core.util.DistanceUnit; +import jsprit.core.util.TimeUnit; +import junit.framework.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; + +public class VrpJsonReaderTest { + + private File jsonFile; + + VehicleRoutingProblem vrp; + + @Before + public void setup(){ + jsonFile = new File("src/test/resources/vrp.json"); + VehicleRoutingProblem.Builder vrpBuilder = VehicleRoutingProblem.Builder.newInstance(); + new VrpJsonReader(vrpBuilder).read(jsonFile); + vrp = vrpBuilder.build(); + } + + @Test + public void noVehiclesShouldBeCorrect(){ + Assert.assertEquals(2,vrp.getVehicles().size()); + } + + @Test + public void noJobsShouldBeCorrect(){ + Assert.assertEquals(2, vrp.getJobs().size()); + } + + @Test + public void noTypesShouldBeCorrect(){ + Assert.assertEquals(2, vrp.getTypes().size()); + } + + @Test + public void vehicle1ShouldBeOfTypeSmall(){ + Assert.assertEquals("small",getVehicle("v1").getType().getTypeId()); + } + + @Test + public void vehicle2ShouldBeOfTypeMedium(){ + Assert.assertEquals("medium",getVehicle("v2").getType().getTypeId()); + } + + @Test + public void vehicle1ShouldHaveCorrectStartAddress(){ + Assert.assertEquals("startLoc", getVehicle("v1").getStartLocationId()); + } + + @Test + public void vehicle1ShouldHaveCorrectEndAddress(){ + Assert.assertEquals("endLoc",getVehicle("v1").getEndLocationId()); + } + + @Test + public void vehicle1ShouldHaveCorrectEndLocCoordinate(){ + Assert.assertEquals(12.,getVehicle("v1").getEndLocationCoordinate().getX(),0.01); + Assert.assertEquals(13.,getVehicle("v1").getEndLocationCoordinate().getY(),0.01); + } + + @Test + public void vehicle1ShouldHaveCorrectEarliestStart(){ + Assert.assertEquals(0.,getVehicle("v1").getEarliestDeparture()); + } + + @Test + public void vehicle1ShouldHaveCorrectLatestStart(){ + Assert.assertEquals(1000., getVehicle("v1").getLatestArrival()); + } + + @Test + public void vehicle1ShouldHaveCorrectSkills(){ + Assert.assertEquals("screw-driver", getVehicle("v1").getSkills().values().iterator().next()); + } + + @Test + public void fleetSizeShouldBeCorrect(){ + Assert.assertTrue(VehicleRoutingProblem.FleetSize.FINITE.equals(vrp.getFleetSize())); + } + + @Test + public void returnToDepotShouldBeCorrect(){ + Assert.assertTrue(getVehicle("v1").isReturnToDepot()); + } + + @Test + public void serviceTypeShouldBeCorrect(){ + Assert.assertEquals("pickup", getService("pickup2").getType()); + } + + @Test + public void serviceNameShouldBeCorrect(){ + Assert.assertEquals("no-name", getService("pickup2").getName()); + } + + @Test + public void startLocShouldBeCorrect(){ + Assert.assertEquals("s2_loc", getService("pickup2").getLocationId()); + } + + @Test + public void coordinateShouldBeCorrect(){ + Assert.assertEquals(40., getService("pickup2").getCoord().getX()); + Assert.assertEquals(10., getService("pickup2").getCoord().getY()); + } + + @Test + public void serviceDurationShouldBeCorrect(){ + Assert.assertEquals(2., getService("pickup2").getServiceDuration()); + } + + @Test + public void serviceTWShouldBeCorrect(){ + Assert.assertEquals(10., getService("pickup2").getTimeWindow().getStart()); + Assert.assertEquals(200., getService("pickup2").getTimeWindow().getEnd()); + } + + @Test + public void sizeShouldBeCorrect(){ + Assert.assertEquals(10, getService("pickup2").getSize().get(0)); + Assert.assertEquals(30, getService("pickup2").getSize().get(1)); + } + + @Test + public void skillsShouldBeCorrect(){ + Assert.assertEquals("screw-driver", getService("pickup2").getRequiredSkills().values().iterator().next()); + } + + private Service getService(String jobId) { + for(Job s : vrp.getJobs().values()){ + if(s.getId().equals(jobId)) return (Service)s; + } + return null; + } + + @Test + public void readMetaInfo(){ + ObjectMapper om = new ObjectMapper(); + try { + JsonNode meta = om.readTree(jsonFile).path(JsonConstants.META); + Assert.assertEquals(DistanceUnit.Meter.abbreviation(),meta.path(JsonConstants.MetaInfo.DISTANCE_UNIT).asText()); + Assert.assertEquals(TimeUnit.SEC.abbreviation(),meta.path(JsonConstants.MetaInfo.TIME_UNIT).asText()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private Vehicle getVehicle(String id) { + for(Vehicle v : vrp.getVehicles()){ + if(v.getId().equals(id)) return v; + } + return null; + } + +} diff --git a/jsprit-core/src/test/java/jsprit/core/util/GreatCircleDistanceCalculatorTest.java b/jsprit-core/src/test/java/jsprit/core/util/GreatCircleDistanceCalculatorTest.java index 72669430..59a9b3b0 100644 --- a/jsprit-core/src/test/java/jsprit/core/util/GreatCircleDistanceCalculatorTest.java +++ b/jsprit-core/src/test/java/jsprit/core/util/GreatCircleDistanceCalculatorTest.java @@ -36,7 +36,7 @@ public class GreatCircleDistanceCalculatorTest { double greatCircle = GreatCircleDistanceCalculator.calculateDistance( Coordinate.newInstance(lon1,lat1), Coordinate.newInstance(lon2,lat2), - GreatCircleDistanceCalculator.DistanceUnit.Kilometer + DistanceUnit.Kilometer ); Assert.assertEquals(600,greatCircle,30.); } @@ -52,7 +52,7 @@ public class GreatCircleDistanceCalculatorTest { double greatCircle = GreatCircleDistanceCalculator.calculateDistance( Coordinate.newInstance(lon1,lat1), Coordinate.newInstance(lon2,lat2), - GreatCircleDistanceCalculator.DistanceUnit.Meter + DistanceUnit.Meter ); Assert.assertEquals(600000,greatCircle,30000.); } diff --git a/jsprit-core/src/test/resources/vrp.json b/jsprit-core/src/test/resources/vrp.json new file mode 100644 index 00000000..b9907a95 --- /dev/null +++ b/jsprit-core/src/test/resources/vrp.json @@ -0,0 +1,85 @@ +{ + "meta-info" : { + "distance-unit" : "m", + "time-unit" : "sec" + }, + "vrp" : { + "fleet_size" : "FINITE", + "vehicles" : [ { + "id" : "v1", + "start_address" : { + "id" : "startLoc", + "lon" : 0.0, + "lat" : 0.0 + }, + "return_to_depot" : true, + "end_address" : { + "id" : "endLoc", + "lon" : 12.0, + "lat" : 13.0 + }, + "earliest_start" : 0.0, + "latest_end" : 1000.0, + "type_id" : "small", + "skills" : [ "screw-driver" ] + }, { + "id" : "v2", + "start_address" : { + "id" : "startLoc", + "lon" : 0.0, + "lat" : 0.0 + }, + "return_to_depot" : false, + "earliest_start" : 0.0, + "latest_end" : 1.7976931348623157E308, + "type_id" : "medium", + "skills" : [ "joo" ] + } ], + "vehicle_types" : [ { + "id" : "medium", + "capacity" : [ 1000, 4000 ], + "fixed_costs" : 1000.0, + "distance_dependent_costs" : 1.0, + "time_dependent_costs" : 200.0 + }, { + "id" : "small", + "capacity" : [ 100, 400 ], + "fixed_costs" : 0.0, + "distance_dependent_costs" : 1.0, + "time_dependent_costs" : 20.0 + } ], + "services" : [ { + "id" : "s1", + "type" : "service", + "name" : "no-name", + "address" : { + "id" : "s1_loc", + "lon" : 40.0, + "lat" : 10.0 + }, + "service_duration" : 1.0, + "time_window" : { + "start" : 0.0, + "end" : 1.7976931348623157E308 + }, + "size" : [ 20, 40 ], + "required_skills" : [ "joo-foo" ] + }, { + "id" : "pickup2", + "type" : "pickup", + "name" : "no-name", + "address" : { + "id" : "s2_loc", + "lon" : 40.0, + "lat" : 10.0 + }, + "service_duration" : 2.0, + "time_window" : { + "start" : 10.0, + "end" : 200.0 + }, + "size" : [ 10, 30 ], + "required_skills" : [ "screw-driver" ] + } ] + } +} \ No newline at end of file