optaplanner: modifying vehicle routing to let customers be not served - optaplanner

In a vehicle routing problem I want to eliminate the constraint that every customer must be served, but adding a prize for those who are served.
I'd like to add a virtual vehicle v_i for each customer c_i, such that v_i can serve only customer c_i, and when it happens it means that the customer is not served. Hence, when there are N customers, there are M real vehicles plus N virtual vehicles.
My doubt is: how can I set the valueRangeProviderRefs of the Customer class to avoid client c_j to be served by vehicle v_i, that is, can I make "vehicleRange" depend on a specific customer instead if refferring to a static List of vehicles?

This is called overconstrained planning. Technically, #PlanningVariable(nullable=true) should allow this, but OptaPlanner 6.0 (and 6.1 currently too) does not support nullable for chained variables yet...
Workaround: Create 1 dummy Vehicle, which is ignored in all the score rules and add a score rule to reward any customer being serviced by a non-dummy Vehicle.

Related

How to mass update the stock quantity of a batch of products in PrestaShop 1.7.6?

I work in the integration of an ERP (Random) and PrestaShop, one of the points considered by the integration is the stock level of the products. When there are movements in the stock of the products in the ERP originating outside of PrestaShop (for example, transfers between warehouses, purchases, external sales, etc.), these stock variations must be synchronized with the physical stock (physical_stock) of PrestaShop, because the reserved stock (stock_reserved) exists only in the PrestaShop context and is related to the reserved products in orders that have not yet been dispatched, while the available stock (stock_available) does not consider the reserved stock by design, then if the Stock that comes from the ERP is assigned to the available stock, the stock reserved until now would double. On the other hand, the physical stock considers both the available stock and the reserved stock, then the stock that comes from the ERP is assigned to the physical stock, the reserved stock is maintained and the available stock will vary depending on the following relation:
stock_available.quantity = stock_available.physical_quantity - stock_available.reserved_quantity
This is currently working correctly in production, however, what I am looking for is to design these operations in the best way through a PrestaShop module, which through a FrontController receives an ajax request where one of the request parameters (Request->_ POST['stock_quantity_changes']) is an input in array format, for example:
[
$id_stock_avaiblable_1 => $new_quantity_1,
$id_stock_avaiblable_2 => $new_quantity_2,
...
]
with which I would like to update the set of stocks that it contains in a single operation. So far, I found method src/PrestaShopBundle/Entity/Repository/StockRepository.php->bulkUpdateStock (https://github.com/PrestaShop/PrestaShop/blob/100c5c028b05c579f5788a036041e45cef510e1d/src/PrestaShopBundle/Entity/Repository/StockRepository.php#L102), that would allow me to do what I need, however I have not figured out how to create a proper instance of this class (StockRepository) yet. The StockRepository-> bulkUpdateStock method receives a set of stock movements (MovementsCollection) and with it, updates a set of available stocks, both in individual products and in pack's if necessary, in addition, records the stock movements (StockMvt's), executes the actionUpdateQuantity hook for each modified stock and removes the value of each modified stock from the cache, all this can be checked in /src/Core/Stock/StockManager.php->updateQuantity (https://github.com/PrestaShop/PrestaShop/blob/100c5c028b05c579f5788a036041e45cef510e1d/src/Core/Stock/StockManager.php#L153). Finally the method bulkUpdateStock synchronize the level of physical stock with the available stock + reserved stock. I am interested in using all this logic when updating a set of stock to adapt it to PrestaShop's operation, since currently only updating the values ​​of the stock_available table I am not registering the StockMvt's, cleaning the cache or executing the actionUpdateQuantity hook.
In summary, I found the StockRepository class that contains the bulkUpdateStock method that would allow me to correctly update the levels of a set of stocks in a single operation, however, to instantiate this class requires a set of parameters, which can be verified in https://github.com/PrestaShop/PrestaShop/blob/100c5c028b05c579f5788a036041e45cef510e1d/src/PrestaShopBundle/Entity/Repository/StockRepository.php#L72, and so far I have not found any instantiation examples for this class in the source code, I have only found code that uses this class already instantiated, as you can check in src/PrestaShopBundle/Controller/Api/StockController.php (https://github.com/PrestaShop/PrestaShop/blob/100c5c028b05c579f5788a036041e45cef510e1d/src/PrestaShopBundle/Controller/Api/StockController.php#L126). So the question finally is, how can I properly instantiate the StockRepository class ?, or is there any alternative to do what I need ?, regards :)

CVRPTW variant on optaplanner with load time in each customer

I'd like to add following restrictions to the CVRPTW problem, and know if it can be modeled on optaplanner:
1) Vehicles start in a garage, loaded in the customers and unloaded in a depot. After last unload, return to the garage
2) In each customer, the vehicle has a different volume to load, and a different time duration for the loading.
TW restrictions is global, every vehicles should start at time x and return to the garage at most on time z.
Thanks,
In the VRP examples in optaplanner-examples, it already has capacity and serviceDuration per TimeWinowedCustomer. All vehicles also return to the depot (= garage).
The only thing I see missing is an arrivalTimeBackAtTheDepot for a Vehicle, which is straightforward to calculate from the last customer's departureTime for each vehicle.

Optaplanner VRP with Pickups Before DropOffs

I am working on using Optaplanner to solve the following a complex vrp problem with many requirements. I was able to handle most of them except for the following 2 aspects.
Pickups before DropOffs only
Enforce a specific path on the way to pickup customers.
The goal is to pickup a group of customers who are going to destinations that close together and put them in the same vehicle.
Thanks in Advance! I appreciate the help!
The Problem is very similar to the example VRP TimeWindow example but with the following changes.
Customers will be picked up at fixed locations (in a circuit)
Every pickup Customer will have a drop off destination (outside of
Circuit)
The vehicle will not head to a drop-Off then come back to pickup
again. (Once vehicle leaves circuit all it does is drop-Off its
customers at set location)
The Vehicle moving in the circuit has to move in a specific path
(imagine a 1 way street)
Planning on Using Road Distances with the Score between each Pickup-to-Pickup is Known. Pickup -> Drop-Off is not known (Planning on using Air).
I'm having a hard time in enforcing that after leaving the circuit to drop-Off customers a vehicle may not come back to pickup more customers, and having this work with the fixed path a vehicle can make in the circuit.
My main idea was to do the following.
Added a TYPE attribute to the customer to differentiate between pickup & customer
Added a variable listener to the customer class that keep track of all the DropOffIds currently when a vehicle arrives to it so that it only goes to a dropOffLocation if it has a passenger heading to that place. When a vehicle arrives to a dropOff it removes that item from the list. (Essentially serves as a stack).
The problem is theoretically this isn't stopping from a vehicle picking up a customer dropping him off then picking up another, if the customers locations are relatively close.
Also having a hardtime enforcing a fixed route a vehicle must take in a circuit, was planning on using a Cost Matrix to use the soft constraint to enforce the route implicitity(A vehicle wont go backwards or a skip a point as the cost would be too high), but not working the way it should be.
I might consider a domain model like this:
#PlanningEntity
class Pickup implements PickupOrVehicle {
Customer customer;
#PlanningVariable
PickupOrVehicle previousPickup;
#PlanningVariable
int dropOffPriority;
}
#PlanningEntity // Shadow entity
class Vehicle implements PickupOrVehicle {
...
#ShadowVariable(based on dropOffPriority and previousPickup)
List<Customer> dropOffOrderList;
// For consistency we might also add pickUpOrderList
}
That dropOffPriority should either be globally unique (by initializing it uniquely and only configure SwapMoves for that variable.
Or otherwise, the VariableListener should just order 2 assignments with the same dropOffPriority by their customer's id (because the ordering must be deterministic!).
No sure if it will work well. If you do try it out, do let us know here if it works well or not.

Does optaplanner out of box support VRP with multiple trips and no depot

I am working on a VRP with the following characteristics:
The vehicle can only pick up 1 customer at one time
The vehicle picks up a customer at a location and drops off the customer at the destination
After dropping off the customer the vehicle goes on to pick up another customer
There is no depot that vehicle needs to go to in between the trips .
The vehicle makes as many trips as it can in a day to pickup/drop-off customers
At the end of day, the vehicle goes back to its designated parking station
Essentially, it's like a taxi system. It seems to me that it's a VRP with multiple trips(VRPMT) and no depot (Open VRP). I'd like to know
Does optaplanner has support for VPRMT and OVRP out of box?
If VPRMT and OVRP are not supported out of box, how easy is it to modify the existing CVRP/CVRPTW examples to make it solve OVRP and VPRMT?
Maybe I am on the wrong track and it's not even a VRP. If so, what would be the right planning problem for the taxi like system?
Many thanks in advance!
No, the examples don't include pickup and delivery or multiple trips yet
Users have done it before to add Pickup and Delivery (which is easy if multiple customers cannot be in the vehicle at the same time (otherwise it's harder and I might add an example for that way some day). Multiple trips and open VRP should by easy (although I think your parking station is a depot and you probably don't have multiple trips, just multiple customer sequentially in the same trip).
This is definitely a variant of VRP. Do note that every business has their own flavor of VRP. You'll always find some custom constraints (now or later in the development process). OptaPlanner allows you to add those custom constraints as needed.
Try this: Take the OptaPlanner VRP example, rename Depot to ParkingStation. Split up Customer's Location into pickupLocation and deliveryLocation and adjust the score rules so the soft score is the sum of:
all pickup to delivery distances
all delivery to next pickup distances
each parking to first pickup distance
each last delivery to parking distance

Domain Model and Contracts

I am modelling a DVD Rental Store:
A Client gives its clientNumber to the System.
The System checks whenever the given clientNumber is valid.
The Client gives the name of the DVD he wants to rent.
...
...I will later have to form an association between a new instance of Rent DVD class concept to the current Client c.
My Domain Model is something like:
I've made the Contract for the first and second operations as:
Preconditions: none
Postconditions: there exists a Client c such that c.clientNumber = clientNumber.
Now, I don't know if I should form an association between this Client c and the DVDStore(that I intend to use as front-end). If I don't make the association, how will I later be able to "reference" this same Client? Should I be making an association between Client and a different concept?
Thanks
Yes, one has to create an association between Client and DVDStore. Otherwise (as stated), you can't later refer to the same Client (at least without having to search for it... again!).