From 0637bdb4b6182e3b6146eedfdea8cc8b4aafe8f5 Mon Sep 17 00:00:00 2001 From: oblonski <4sschroeder@gmail.com> Date: Wed, 2 Jul 2014 23:43:35 +0200 Subject: [PATCH] added SkillConstraint --- .../problem/constraint/SkillConstraint.java | 36 ++++++ .../constraint/SkillConstraintTest.java | 107 ++++++++++++++++++ 2 files changed, 143 insertions(+) create mode 100644 jsprit-core/src/main/java/jsprit/core/problem/constraint/SkillConstraint.java create mode 100644 jsprit-core/src/test/java/jsprit/core/problem/constraint/SkillConstraintTest.java diff --git a/jsprit-core/src/main/java/jsprit/core/problem/constraint/SkillConstraint.java b/jsprit-core/src/main/java/jsprit/core/problem/constraint/SkillConstraint.java new file mode 100644 index 00000000..9459e350 --- /dev/null +++ b/jsprit-core/src/main/java/jsprit/core/problem/constraint/SkillConstraint.java @@ -0,0 +1,36 @@ +package jsprit.core.problem.constraint; + +import jsprit.core.problem.Skills; +import jsprit.core.problem.misc.JobInsertionContext; +import jsprit.core.problem.solution.route.state.RouteAndActivityStateGetter; +import jsprit.core.problem.solution.route.state.StateFactory; + +/** + * SkillConstraint that ensures that only vehicles with according skills can serve route and job to be inserted. + * + */ +public class SkillConstraint implements HardRouteStateLevelConstraint{ + + private RouteAndActivityStateGetter states; + + public SkillConstraint(RouteAndActivityStateGetter states) { + this.states = states; + } + + @Override + public boolean fulfilled(JobInsertionContext insertionContext) { + for(String skill : insertionContext.getJob().getRequiredSkills().values()){ + if(!insertionContext.getRoute().getVehicle().getSkills().containsSkill(skill)){ + return false; + } + } + Skills requiredSkillsForRoute = states.getRouteState(insertionContext.getRoute(), StateFactory.SKILLS, Skills.class); + for(String skill : requiredSkillsForRoute.values()){ + if(!insertionContext.getRoute().getVehicle().getSkills().containsSkill(skill)){ + return false; + } + } + return true; + } + +} diff --git a/jsprit-core/src/test/java/jsprit/core/problem/constraint/SkillConstraintTest.java b/jsprit-core/src/test/java/jsprit/core/problem/constraint/SkillConstraintTest.java new file mode 100644 index 00000000..8dd07676 --- /dev/null +++ b/jsprit-core/src/test/java/jsprit/core/problem/constraint/SkillConstraintTest.java @@ -0,0 +1,107 @@ +package jsprit.core.problem.constraint; + +import jsprit.core.algorithm.state.StateManager; +import jsprit.core.algorithm.state.UpdateSkills; +import jsprit.core.problem.Skills; +import jsprit.core.problem.cost.VehicleRoutingTransportCosts; +import jsprit.core.problem.job.Service; +import jsprit.core.problem.misc.JobInsertionContext; +import jsprit.core.problem.solution.route.VehicleRoute; +import jsprit.core.problem.vehicle.Vehicle; +import org.junit.Before; +import org.junit.Test; + +import java.util.Arrays; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +public class SkillConstraintTest { + + private HardRouteStateLevelConstraint skillConstraint; + + private StateManager stateManager; + + private VehicleRoute route; + + private Vehicle vehicle; + + @Before + public void doBefore(){ + vehicle = mock(Vehicle.class); + Service service = mock(Service.class); + Service service2 = mock(Service.class); + Service service3 = mock(Service.class); + when(service.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").build()); + when(service2.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").addSkill("skill2") + .addSkill("skill3").build()); + when(service3.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4") + .addSkill("skill5").build()); + route = VehicleRoute.Builder.newInstance(vehicle).addService(service).addService(service2).addService(service3).build(); + stateManager = new StateManager(mock(VehicleRoutingTransportCosts.class)); + stateManager.addStateUpdater(new UpdateSkills(stateManager)); + stateManager.update(route); + skillConstraint = new SkillConstraint(stateManager); + } + + @Test + public void whenJobToBeInsertedRequiresSkillsThatVehicleDoesNotHave_itShouldReturnFalse(){ + Service s4 = mock(Service.class); + when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill5").build()); + when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance() + .addAllSkills(Arrays.asList("skill1","skill2","skill3","skill4")).build()); + JobInsertionContext insertionContext = new JobInsertionContext(route,s4,vehicle,route.getDriver(),0.); + assertFalse(skillConstraint.fulfilled(insertionContext)); + } + + @Test + public void whenJobToBeInsertedRequiresSkillsThatVehicleHave_itShouldReturnTrue(){ + Service s4 = mock(Service.class); + when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4").build()); + when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance() + .addAllSkills(Arrays.asList("skill1","skill2","skill3","skill4","skill5")).build()); + JobInsertionContext insertionContext = new JobInsertionContext(route,s4,vehicle,route.getDriver(),0.); + assertTrue(skillConstraint.fulfilled(insertionContext)); + } + + @Test + public void whenRouteToBeOvertakenRequiresSkillsThatVehicleDoesNotHave_itShouldReturnFalse(){ + Service s4 = mock(Service.class); + when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4").build()); + when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance() + .addAllSkills(Arrays.asList("skill1","skill2","skill6","skill4")).build()); + JobInsertionContext insertionContext = new JobInsertionContext(route,s4,vehicle,route.getDriver(),0.); + assertFalse(skillConstraint.fulfilled(insertionContext)); + } + + @Test + public void whenRouteToBeOvertakenRequiresSkillsThatVehicleDoesHave_itShouldReturnTrue(){ + Service s4 = mock(Service.class); + when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill4").build()); + when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance() + .addAllSkills(Arrays.asList("skill1","skill2","skill3","skill4","skill5")).build()); + JobInsertionContext insertionContext = new JobInsertionContext(route,s4,vehicle,route.getDriver(),0.); + assertTrue(skillConstraint.fulfilled(insertionContext)); + } + + @Test + public void whenNoSkillsAreRequired_itShouldReturnTrue(){ + Service s4 = mock(Service.class); + when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().build()); + when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance().build()); + JobInsertionContext insertionContext = new JobInsertionContext(VehicleRoute.emptyRoute(),s4,vehicle,route.getDriver(),0.); + assertTrue(skillConstraint.fulfilled(insertionContext)); + } + + @Test + public void whenSkillsIsRequiredWhichVehicleDoesNotHave_itShouldReturnFalse(){ + Service s4 = mock(Service.class); + when(s4.getRequiredSkills()).thenReturn(Skills.Builder.newInstance().addSkill("skill1").build()); + when(vehicle.getSkills()).thenReturn(Skills.Builder.newInstance().build()); + JobInsertionContext insertionContext = new JobInsertionContext(VehicleRoute.emptyRoute(),s4,vehicle,route.getDriver(),0.); + assertFalse(skillConstraint.fulfilled(insertionContext)); + } +}