For taskassigning project,I want the same tasktype tasks can be adjacent as more as possible。 - optaplanner

Below is what I plan, please give me advice:
(1) In the Task class, add a CustomShadowVariable:
#CustomShadowVariable(variableListenerClass =
NumOfAdjacentUpdatingVariableListener.class,
sources = { #PlanningVariableReference(variableName =
"previousTaskOrEmployee") })
private Integer numOfAdjacent;
(2) In the class NumOfAdjacentUpdatingVariableListener:
#Override
public void afterEntityAdded(ScoreDirector<TaskAssigningSolution>
scoreDirector, Task task) {
//update number of adjacent tasks : numOfAdjacent
}
#Override
public void afterVariableChanged(ScoreDirector<TaskAssigningSolution>
scoreDirector, Task task) {
//update number of adjacent tasks : numOfAdjacent
}
(3) In the constraints,add a constraint to reward the numOfAdjacent.

You can achieve that without a custom shadow variable. Simply add a new constraint that penalizes every pair of adjacent tasks if they have different types. This constraint will push OptaPlanner to reorder tasks and minimize the number of adjacent tasks with different types.
The constraint could look like this:
private Constraint adjacentTaskDifferentTypes(ConstraintFactory constraintFactory) {
return constraintFactory.forEach(Task.class)
.join(Task.class, equal(Task::getNextTask, Function.identity()))
.filter((t1, t2) -> !t1.getTaskType().equals(t2.getTaskType()))
.penalize("Adjacent task have different types",
// constraint weight
BendableScore.ofSoft(HARD_LEVELS, SOFT_LEVELS, 0, 3));
}
This constraint works on the TaskAssignment example in https://github.com/kiegroup/optaplanner. Try implementing a similar constraint using your project's domain model.
Then tweak the resulting solution by changing the constraint's priority. You can adjust the priority by changing the constraint weight:
Change the match weight (3 in the code snippet above) to change the constraint priority relative to other constraints affecting the same score level.
Change the constraint's score level (0 in the code snippet above) to give the constraint higher priority than all constraints on lower score levels.

Related

Unable to load Aggregate using Repository.load() for Integer AggregateIdentifier

I've been trying in vain to load an aggregate using the load method of the repository class. I know that the load() method requires a string argument but my aggregate identifier is integer.
I have tried to convert to string, yet I'm not able to load the aggregate. I keep getting null.
My code is shown below
#Autowired
private Repository<Product> repository;
#CommandHandler
public Order(CreateOrderCommand cmd){
try{
//This line throws an error
Product product = (Product) repository.load(Integer.toString(cmd.getProductId()));
}
catch (Exception ex){
System.out.println("Oops! Error Occured: " + ex.getMessage());
}
apply(
new OrderCreatedEvent(
cmd.getOrderId(), cmd.getPrice(), cmd.getNumber(), cmd.getProductId()
)
);
}
I'm providing an more updates:
I simply want to update the products stock, when a new order is placed. So what I did was that in the CommandHandler for creating a new Order, I simply find the Product aggregate and call it's UpdateStock method, which is a command handler.
Is there something I really don't understand?
These are the files below:
The Product aggregate:
#Aggregate
public class Product {
#AggregateIdentifier
private String id;
private Double price;
private Integer stock;
private String description;
public Product() {
}
#CommandHandler
public Product(AddProductCommand cmd){
apply( new ProductAddedEvent(
cmd.getId(),
cmd.getPrice(),
cmd.getStock(),
cmd.getDescription()
)
);
}
#CommandHandler
public void updateStock (UpdateStockCommand cmd){
if(this.stock >= cmd.getStock()){
apply(new StockUpdatedEvent(cmd.getId(), cmd.getStock()));
}
else {
throw new RuntimeException("Out of Stock!");
}
}
#EventSourcingHandler
public void on(StockUpdatedEvent evt){
id = evt.getId();
stock = stock - evt.getStock();
}
#EventSourcingHandler
public void on(ProductAddedEvent evt){
id = evt.getId();
price = evt.getPrice();
stock = evt.getStock();
description = evt.getDescription();
}
}
The Order aggregate:
#Aggregate
public class Order {
#AggregateIdentifier
private String orderId;
private Double price;
private Integer number;
private String productId;
//Repository provides an abstraction for storage of Aggregates
#Autowired
private Repository<Product> repository;
#CommandHandler
public Order(CreateOrderCommand cmd){
try{
//This line throws an error
Product product = (Product) repository.load(cmd.getProductId());
}
catch (Exception ex){
System.out.println("Oops! Error Occured: " + ex.getMessage());
}
apply(
new OrderCreatedEvent(
cmd.getOrderId(), cmd.getPrice(), cmd.getNumber(), cmd.getProductId()
)
);
}
#EventSourcingHandler
public void on(OrderCreatedEvent evt){
orderId = evt.getOrderId();
price = evt.getPrice();
number = evt.getNumber();
productId = evt.getProductId();
}
}
As you have noticed, Axon will enforce a String for the aggregate identifier. This doesn't mean you need to provide a String directly. It'll work perfectly fine as long as you have a sensible toString() method implemented. Hence, using Integer as the aggregate identifier will result in the toString() result of that field to be used as the aggregate identifier.
Having said that, I'm surprised you are unable to load an aggregate based on this.
Maybe we need to do some follow up based on that, but firstly I want to comment on the snippet you're sharing.
It seems like you have a constructor command handler on the Order class. Moreover, that signals to me that the Order class is an aggregate.
I'd like to state that by no means would I ever recommend to load in an Aggregate from within another Aggregate.
Doing so ties in the lock on the Order aggregate with the Product aggregate, thus blocking a larger portion of your system than the sender of CreateOrderCommand would ever expect.
Communication between aggregate should be kept asynchronous at all times, through means of event messages.
That thus requires a dedicated Event Handling Component which does the coordination between both instances based on the published event.
I'd thus strongly suggest a rewrite of your logic on the matter.
When it comes to loading in an aggregate, I'd be hard pressed to give you a reasoning right now.
Hence, let me ask a couple of follow up questions.
I'd suggest to update your original request with the responses by the way; to maintain a nice thread of continuity.
Which version of Axon are you using any way?
Are you using any interesting configurations around the Product aggregate?
Are you pairing your application with Axon Server? If so, standard or enterprise, and which version?
Do you use the Configuration API directly or the axon-spring-boot-starter?
Update
Thanks for updating your question Kindson, let me update my answer too.
Firstly, as I already stated previously, I would never load in an Aggregate from within another Aggregate. Both your Order class and Product class are Aggregates and the snippets make overly clear that you are consolidating the "product Repository" from within the Order aggregate.
This approach does not only prolong locks on your aggregates, thus imposing strains on your users, but following this approach might event incur deadlocks. As a rule of thumb, always follow an asynchronous approach to communicating between aggregate instances. Thus a component reacting on an aggregate's events and dispatching commands to another. This can be done in a regular Event Handling Component, or a Saga for example.
Apart from the above, I have tested locally whether I could use an Integer as an Aggregate Identifier. Thus, as the #AggregateIdentifier annotated field in the aggregate and as the #TargetAggregateIdentifier annotated field on your command message. On top of that, I tried this out by having the framework call the Repository#load(String) operation (thus just dispatching a command on the CommandGateway/CommandBus) and by calling it directly as you did.
Sadly, this works out fine for me. Thus, as another follow up, I'd suggest to share the actual exception you are getting when you are performing the Repository#load(String) operation.

Optaplanner: NullPointerException when calling scoreDirector.beforeVariableChanged in a simple custom move

I am building a Capacited Vehicle Routing Problem with Time Windows, but with one small difference when compared to the one provided in examples from the documentation: I don't have a depot. Instead, each order has a pickup step, and a delivery step, in two different locations.
(like in the Vehicle Routing example from the documentation, the previousStep planning variable has the CHAINED graph type, and its valueRangeProviderRefs includes both Drivers, and Steps)
This difference adds a couple of constraints:
the pickup and delivery steps of a given order must be handled by the same driver
the pickup must be before the delivery
After experimenting with constraints, I have found that it would be more efficient to implement two types of custom moves:
assign both steps of an order to a driver
rearrange the steps of a driver
I am currently implementing that first custom move. My solver's configuration looks like this:
SolverFactory<RoutingProblem> solverFactory = SolverFactory.create(
new SolverConfig()
.withSolutionClass(RoutingProblem.class)
.withEntityClasses(Step.class, StepList.class)
.withScoreDirectorFactory(new ScoreDirectorFactoryConfig()
.withConstraintProviderClass(Constraints.class)
)
.withTerminationConfig(new TerminationConfig()
.withSecondsSpentLimit(60L)
)
.withPhaseList(List.of(
new LocalSearchPhaseConfig()
.withMoveSelectorConfig(CustomMoveListFactory.getConfig())
))
);
My CustomMoveListFactory looks like this (I plan on migrating it to an MoveIteratorFactory later, but for the moment, this is easier to read and write):
public class CustomMoveListFactory implements MoveListFactory<RoutingProblem> {
public static MoveListFactoryConfig getConfig() {
MoveListFactoryConfig result = new MoveListFactoryConfig();
result.setMoveListFactoryClass(CustomMoveListFactory.class);
return result;
}
#Override
public List<? extends Move<RoutingProblem>> createMoveList(RoutingProblem routingProblem) {
List<Move<RoutingProblem>> moves = new ArrayList<>();
// 1. Assign moves
for (Order order : routingProblem.getOrders()) {
Driver currentDriver = order.getDriver();
for (Driver driver : routingProblem.getDrivers()) {
if (!driver.equals(currentDriver)) {
moves.add(new AssignMove(order, driver));
}
}
}
// 2. Rearrange moves
// TODO
return moves;
}
}
And finally, the move itself looks like this (nevermind the undo or the isDoable for the moment):
#Override
protected void doMoveOnGenuineVariables(ScoreDirector<RoutingProblem> scoreDirector) {
assignStep(scoreDirector, order.getPickupStep());
assignStep(scoreDirector, order.getDeliveryStep());
}
private void assignStep(ScoreDirector<RoutingProblem> scoreDirector, Step step) {
StepList beforeStep = step.getPreviousStep();
Step afterStep = step.getNextStep();
// 1. Insert step at the end of the driver's step list
StepList lastStep = driver.getLastStep();
scoreDirector.beforeVariableChanged(step, "previousStep"); // NullPointerException here
step.setPreviousStep(lastStep);
scoreDirector.afterVariableChanged(step, "previousStep");
// 2. Remove step from current chained list
if (afterStep != null) {
scoreDirector.beforeVariableChanged(afterStep, "previousStep");
afterStep.setPreviousStep(beforeStep);
scoreDirector.afterVariableChanged(afterStep, "previousStep");
}
}
The idea being that at no point I'm doing an invalid chained list manipulation:
However, as the title and the code comment indicate, I am getting a NullPointerException when I call scoreDirector.beforeVariableChanged. None of my variables are null (I've printed them to make sure). The NullPointerException doesn't occur in my code, but deep inside Optaplanner's inner workings, making it difficult for me to fix it:
Exception in thread "main" java.lang.NullPointerException
at org.drools.core.common.NamedEntryPoint.update(NamedEntryPoint.java:353)
at org.drools.core.common.NamedEntryPoint.update(NamedEntryPoint.java:338)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.update(StatefulKnowledgeSessionImpl.java:1579)
at org.drools.core.impl.StatefulKnowledgeSessionImpl.update(StatefulKnowledgeSessionImpl.java:1551)
at org.optaplanner.core.impl.score.stream.drools.DroolsConstraintSession.update(DroolsConstraintSession.java:49)
at org.optaplanner.core.impl.score.director.stream.ConstraintStreamScoreDirector.afterVariableChanged(ConstraintStreamScoreDirector.java:137)
at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.retract(SingletonInverseVariableListener.java:96)
at org.optaplanner.core.impl.domain.variable.inverserelation.SingletonInverseVariableListener.beforeVariableChanged(SingletonInverseVariableListener.java:46)
at org.optaplanner.core.impl.domain.variable.listener.support.VariableListenerSupport.beforeVariableChanged(VariableListenerSupport.java:170)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.beforeVariableChanged(AbstractScoreDirector.java:430)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.beforeVariableChanged(AbstractScoreDirector.java:390)
at test.optaplanner.solver.AssignMove.assignStep(AssignMove.java:98)
at test.optaplanner.solver.AssignMove.doMoveOnGenuineVariables(AssignMove.java:85)
at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:35)
at org.optaplanner.core.impl.heuristic.move.AbstractMove.doMove(AbstractMove.java:30)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.doAndProcessMove(AbstractScoreDirector.java:187)
at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.doMove(LocalSearchDecider.java:132)
at org.optaplanner.core.impl.localsearch.decider.LocalSearchDecider.decideNextStep(LocalSearchDecider.java:116)
at org.optaplanner.core.impl.localsearch.DefaultLocalSearchPhase.solve(DefaultLocalSearchPhase.java:70)
at org.optaplanner.core.impl.solver.AbstractSolver.runPhases(AbstractSolver.java:98)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:189)
at test.optaplanner.OptaPlannerService.testOptaplanner(OptaPlannerService.java:68)
at test.optaplanner.App.main(App.java:13)
Is there something I did wrong? It seems I am following the documentation for custom moves fairly closely, outside of the fact that I am using exclusively java code instead of drools.
The initial solution I feed to the solver has all of the steps assigned to a single driver. There are 15 drivers and 40 orders.
In order to bypass this error, I have tried a number of different things:
remove the shadow variable annotation, turn Driver into a problem fact, and handle the nextStep field myself => this makes no difference
use Simulated Annealing + First Fit Decreasing construction heuristics, and start with steps not assigned to any driver (this was inspired by looking up the example here, which is more complete than the one from the documentation) => the NullPointerException appears on afterVariableChanged instead, but it still appears.
a number of other things which were probably not very smart
But without a more helpful error message, I can't think of anything else to try.
Thank you for your help

Render glitch with custom block boundaries minecraft

I'm creating a mod for Minecraft. Recently, I've tried to make a custom block, and I'm having two issues with it.
My main issue is that the block is rendering incorrectly. I want the block to be smaller in size than a full block. I successfully changed the block boundaries with setBlockBounds(), and while that did make the block render smaller and use the smaller boundaries, it causes other rendering issues. When I place the block, the floor below is becomes invisible and I can see through it, either to caves below, blocks behind it, or the void if there is nothing there. How do I fix that block not rendering? Here's a screenshot:
Additionally, my goal for this block is to emit an "aura" that gives players around it speed or some other potion effect. I have the basic code for finding players around the block and giving them speed, but I can't find a way to activate this method every tick or every X amount of ticks to ensure that it gives players within the box speed in a reliable manner. There are already some blocks in the normal game that do this, so it must be possible. How can I do this?
For your first issue, you need to override isOpaqueCube to return false. You'll also want to override isFullCube for other parts of the code, but that isn't as important for rendering. Example:
public class YourBlock {
// ... existing code ...
/**
* Used to determine ambient occlusion and culling when rebuilding chunks for render
*/
#Override
public boolean isOpaqueCube(IBlockState state) {
return false;
}
#Override
public boolean isFullCube(IBlockState state) {
return false;
}
}
Here's some info on rendering that mentions this.
Regarding your second problem, that's more complicated. It's generally achieved via a tile entity, though you can also use block updates (which is much slower). Good examples of this are BlockBeacon and TileEntityBeacon (for using tile entities) and BlockFrostedIce (for block updates). Here's some (potentially out of date) info on tile entities.
Here's an (untested) example of getting an update each tick this with tile entities:
public class YourBlock {
// ... existing code ...
/**
* Returns a new instance of a block's tile entity class. Called on placing the block.
*/
#Override
public TileEntity createNewTileEntity(World worldIn, int meta) {
return new TileEntityYourBlock();
}
}
/**
* Tile entity for your block.
*
* Tile entities normally store data, but they can also receive an update each
* tick, but to do so they must implement ITickable. So, don't forget the
* "implements ITickable".
*/
public class TileEntityYourBlock extends TileEntity implements ITickable {
#Override
public void update() {
// Your code to give potion effects to nearby players would go here
// If you only want to do it every so often, you can check like this:
if (this.worldObj.getTotalWorldTime() % 80 == 0) {
// Only runs every 80 ticks (4 seconds)
}
}
// The following code isn't required to make a tile entity that gets ticked,
// but you'll want it if you want (EG) to be able to set the effect.
/**
* Example potion effect.
* May be null.
*/
private Potion effect;
public void setEffect(Potion potionEffect) {
this.effect = potionEffect;
}
public Potion getEffect() {
return this.effect;
}
#Override
public void readFromNBT(NBTTagCompound compound) {
super.readFromNBT(compound);
int effectID = compound.getInteger("Effect")
this.effect = Potion.getPotionById(effectID);
}
public void writeToNBT(NBTTagCompound compound) {
super.writeToNBT(compound);
int effectID = Potion.getIdFromPotion(this.effect);
compound.setInteger("Effect", effectID);
}
}
// This line needs to go in the main registration.
// The ID can be anything so long as it isn't used by another mod.
GameRegistry.registerTileEntity(TileEntityYourBlock.class, "YourBlock");

OptaPlanner customer-vehicle delivery restrictions

I am using OptaPlanner for vehicle routing and scheduling. I'd like to include the concept of customer-vehicle restrictions.
Example 1: customers specified as mechanised customers can only
receive delivery from vehicles that have been specified as mechanised
(e.g. vehicles with forklifts, hydraulic tail lifts, etc.)
Example 2: customers have physical constraints on their premises and
can only accept delivery from vehicles under a certain size.
In general terms a group of customers should receive delivery from a group of vehicles. Any vehicles that do not meet the criteria should not be considered for delivery to these customers.
I've searched the forum, but don't see any questions for the same scenario. Can anyone assist?
Add a hard constraint, for example in DRL
when
Customer(vehicleOk == false)
then
... // penalize hard score
end
with a class that looks like this:
class Customer {
private boolean needsMech;
private Vehicle vehicle; // Anchor shadow variable
...
public boolean isVehicleOk() {
if (needsMech && !vehicle.isMech()) {
return false;
}
if (...) { // size limitation
return false;
}
return true;
}
}

Arquillian Does Not Execute More Than 4 Tests

This one is a bit of a headscratcher: I have an Arquillian test class with 8 tests. If I execute 4 of them at once, all of them work, but if I add even one other test, the last one fails. If I execute all 8 of them, the last 4 fail. If I change the the order, still the last 4 fail. There is no rhyme nor reason to which ones get executed and which one fails besides that.
(The same holds true if I put half of the tests in another class. Then both classes execute fine on their own, but if they are started as part of the same run configuration, the second one will fail all its tests.)
The error occurs inside the #Before method, so here it is:
#PersistenceContext
private EntityManager em;
#Inject
private UserTransaction transaction;
#Before
public void setUp() throws Exception {
Assert.assertNotNull("EntityManager cannot be null!", this.em);
this.transaction.begin();
this.em.createNativeQuery(MY_SCRIPT_1).executeUpdate();
this.em.createNativeQuery(MY_SCRIPT_2).executeUpdate();
this.transaction.commit();
}
Where MY_SCRIPT_X is a bunch of code, but the relevant portion might be:
-- MY_SCRIPT_1
DROP SCHEMA IF EXISTS scheme1 CASCADE;
DROP SCHEMA IF EXISTS scheme2 CASCADE;
DROP SCHEMA IF EXISTS public CASCADE;
CREATE SCHEMA public;
-- MY_SCRIPT_2
CREATE TABLE scheme1.dbconfig (
propkey character varying NOT NULL,
propvalue character varying NOT NULL,
CONSTRAINT dbconfig_pkey PRIMARY KEY (propkey)
);
COMMENT ON TABLE scheme1.dbconfig IS 'global database configuration properties';
INSERT INTO scheme1.dbconfig VALUES
('initialized', true),
('version', 2);
The error does not occur if I use only one big script [em.createNativeQuery(MY_SCRIPT_1 + MY_SCRIPT_2)], even though the table scheme1.dbconfig is only referenced in one of the files.
All I get as an error message is:
09:20:18,243 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-24) ERROR: relation "scheme1.dbconfig" does not exist
Position: 169
I have no idea where position 169 is (ignoring all comments, the 169th position should be between the R and the O of propkey, which seems odd). But I checked the database after executing the entire class and getting the above error, and the table scheme1.dbconfig does indeed exist.
I know, it's an oddly specific problem, but does anybody what the problem might be (or even how to debug it further)?
Some more infos:
database: PostgreSQL
Hibernate: 4.3.5
container: Wildfly 8.1.0.Final
And all it needs for my to reproduce the bug is (the beans.xml is an default empty file, and the persistence.xml has only the jta-data-source):
#RunWith(Arquillian.class)
public class BugTest {
private static final String CLEANUP_SCRIPT = "DROP SCHEMA IF EXISTS scheme1 CASCADE; "
+ "DROP SCHEMA IF EXISTS public CASCADE; "
+ "CREATE SCHEMA public AUTHORIZATION testdba;";
private static final String CREATE_SCRIPT = "CREATE SCHEMA scheme1; "
+ "CREATE TABLE scheme1.dbconfig ( propkey character varying NOT NULL, propvalue character varying NOT NULL, CONSTRAINT dbconfig_pkey PRIMARY KEY (propkey) ); "
+ "INSERT INTO scheme1.dbconfig VALUES ('initialized', true), ('version', 2);";
#Deployment
public static Archive<?> createDeployment() {
return ShrinkWrap.create(JavaArchive.class).addAsManifestResource("META-INF/beans.xml", "beans.xml")
.addAsManifestResource("META-INF/persistence.xml", "persistence.xml");
}
#PersistenceContext
private EntityManager em;
#Inject
private UserTransaction transaction;
#Before
public void setUp() throws Exception {
this.transaction.begin();
this.em.createNativeQuery(CLEANUP_SCRIPT).executeUpdate();
this.em.createNativeQuery(CREATE_SCRIPT).executeUpdate();
this.transaction.commit();
}
// since an exception gets thrown in the setUp() method, these are not called
// they are only needed because the exception gets thrown for more than
// four tests methods
#Test public void test1() { }
#Test public void test2() { }
#Test public void test3() { }
#Test public void test4() { }
#Test public void test5() { }
#Test public void test6() { }
#Test public void test7() { }
#Test public void test8() { }
}
I ran over that problem again and again and again in the previous two years. The only thing that reliable works are the following:
using one script instead of two; in this case, I'll concatenate the two files before executing
not initializing every time; I'll test if one of the schemata is present and hope and pray that the previous tests left the database in an usable condition (good luck debugging using this one)
No, Arquillian will run as many tests as you need in a single file, or at least until JUnit (or TestNG) stop running. Here are some examples from Apache DeltaSpike with more than four tests running:
https://github.com/apache/deltaspike/blob/master/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/impl/exception/control/handler/CallingHandlersTest.java
https://github.com/apache/deltaspike/blob/master/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/handler/EntityRepositoryHandlerTest.java
https://github.com/apache/deltaspike/blob/master/deltaspike/core/impl/src/test/java/org/apache/deltaspike/test/core/api/message/MessageContextTest.java
You must have something in your setup that is causing the problem.