Nurse rostering modification - optaplanner

Hi I'm new on Optaplanner and I'm trying to adapt nurse rostering for airport checkin agent rostering. I've created A FlightAssignment in which an Employee is assigned to a Flight.
The Employee is the PlanningVariable.
The FlightAssignment is the PlanningEntity.
The CheckinRoster is the PlanningEntityCollectionProperty
Please help me, when I run the CheckinRosteringApp I get this error:
2017-03-03 16:35:47,574 [main] INFO CloudBalance 1 has 9 flights and 15 employees with a search space of 10^14.
Exception in thread "main" java.lang.IllegalArgumentException: The solutionClass (class org.optaplanner.examples.handler.domain.CheckinRoster)'s entityCollectionProperty (flightAssignmentList) should never return null.
at org.optaplanner.core.impl.domain.solution.descriptor.SolutionDescriptor.extractEntityCollection(SolutionDescriptor.java:657)
at org.optaplanner.core.impl.domain.solution.descriptor.SolutionDescriptor.getEntityCount(SolutionDescriptor.java:516)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner$FieldAccessingSolutionClonerRun.cloneSolution(FieldAccessingSolutionCloner.java:201)
at org.optaplanner.core.impl.domain.solution.cloner.FieldAccessingSolutionCloner.cloneSolution(FieldAccessingSolutionCloner.java:72)
at org.optaplanner.core.impl.score.director.AbstractScoreDirector.cloneSolution(AbstractScoreDirector.java:142)
at org.optaplanner.core.impl.solver.scope.DefaultSolverScope.setWorkingSolutionFromBestSolution(DefaultSolverScope.java:198)
at org.optaplanner.core.impl.solver.DefaultSolver.solvingStarted(DefaultSolver.java:196)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:175)
at org.optaplanner.examples.handler.app.CheckinRosteringApp.main(CheckinRosteringApp.java:30)
And if I initialize the flightAssignmentList the error disappear but the solution is empty.
2017-03-04 18:31:43,691 [main] INFO CheckinRoster 1 has 8 flights and 20 employees with a search space of 10^18.
2017-03-04 18:31:44,061 [main] INFO Solving started: time spent (350), best score (-25hard/0soft), environment mode (REPRODUCIBLE), random (JDK with seed 0).
2017-03-04 18:31:44,078 [main] INFO Construction Heuristic phase (0) ended: step total (0), time spent (369), best score (-25hard/0soft).
2017-03-04 18:31:44,090 [main] WARN No doable selected move at step index (0), time spent (382). Terminating phase early.
2017-03-04 18:31:44,091 [main] INFO Local Search phase (1) ended: step total (0), time spent (383), best score (-25hard/0soft).
2017-03-04 18:31:44,091 [main] INFO Solving ended: time spent (383), best score (-25hard/0soft), average calculate count per second (7), environment mode (REPRODUCIBLE).
[...]
Did I make something wrong in the xml config file? I used the one in nurserostering deleting the unionMoveSelector block hoping in optaplanner searching for a solution.
This is the checkinRosteringSolverConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<solver>
<!--<environmentMode>FAST_ASSERT</environmentMode>-->
<solutionClass>org.optaplanner.examples.handler.domain.CheckinRoster</solutionClass>
<entityClass>org.optaplanner.examples.handler.domain.FlightAssignment</entityClass>
<scoreDirectorFactory>
<scoreDefinitionType>HARD_SOFT</scoreDefinitionType>
<scoreDrl>org/optaplanner/examples/handler/solver/checkinRosteringScoreRules.drl</scoreDrl>
</scoreDirectorFactory>
<termination>
<!--
Official benchmark secondsSpentLimit allowed on:
- ge0ffrey's main pc: sprint 11, medium 700, long 42000
-->
<secondsSpentLimit>700</secondsSpentLimit>
<!--<bestScoreLimit>-0hard/-999999soft</bestScoreLimit>-->
</termination>
<constructionHeuristic>
<constructionHeuristicType>WEAKEST_FIT</constructionHeuristicType>
</constructionHeuristic>
<localSearch>
<acceptor>
<entityTabuSize>7</entityTabuSize>
</acceptor>
<forager>
<acceptedCountLimit>800</acceptedCountLimit>
</forager>
</localSearch>
</solver>
And this is the checkingRosteringScoreRules.drl
/*
* Copyright 2010 Red Hat, Inc. and/or its affiliates.
*
* Licensed 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.
*/
package org.optaplanner.examples.handler.solver;
dialect "java"
import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;
import org.optaplanner.examples.handler.domain.Employee;
import org.optaplanner.examples.handler.domain.Flight;
import org.optaplanner.examples.handler.domain.FlightAssignment;
import org.optaplanner.examples.handler.domain.CheckinRoster;
global HardSoftScoreHolder scoreHolder;
// ############################################################################
// Hard constraints
// ############################################################################
// This rule is build in
// All demanded shifts must be assigned to a nurse
rule "requiredEmployeeSizePerShift"
when
$flight : Flight(minimumEmployeesNumber > 0, $minimumEmployeesNumber : minimumEmployeesNumber)
$totalEmployeeNumber : Number(intValue <= $minimumEmployeesNumber) from accumulate(
$assignment : FlightAssignment(flight == $flight),
count($assignment)
)
then
scoreHolder.addHardConstraintMatch(kcontext, - Math.abs($minimumEmployeesNumber - $totalEmployeeNumber.intValue()));
end
//a nurse can only work on no clashing flights
//TODO
//TODO
// a nurse can only work one shift per day, i.e. no two shift can be assigned to the same nurse on a day.
//rule "oneShiftPerDay"
// when
// ShiftAssignment($leftId : id, $employee : employee, $shiftDate : shiftDate, employee != null)
// ShiftAssignment(employee == $employee, shiftDate == $shiftDate, id > $leftId)
// then
// scoreHolder.addHardConstraintMatch(kcontext, -1);
//end
// ############################################################################
// Soft constraints
// ############################################################################
rule "employeeCost"
when
$employee : Employee($income : income)
exists FlightAssignment(employee == $employee)
then
scoreHolder.addSoftConstraintMatch(kcontext, - $income);
end

Exception in thread "main" java.lang.IllegalArgumentException: The solutionClass (class org.optaplanner.examples.handler.domain.CheckinRoster)'s entityCollectionProperty (flightAssignmentList) should never return null.
Check your method CheckinRoster.getFlightAssignmentList(). For that dataset, it's apparently returning null.

Related

Local Search phase needs to start from an initialized solution - But how?

I am writing a modified version of the Task Assignment example with my own domain model.
In my model each Task can have a NextTask and a PreviousTask and an Assignee. All 3 are configured as PlanningVariables:
...
/** PreviousTask is a calculated task that the Resource will complete before this one. */
#PlanningVariable(valueRangeProviderRefs = { "tasksRange" }, graphType = PlanningVariableGraphType.CHAINED)
public Task PreviousTask;
#InverseRelationShadowVariable(sourceVariableName = "PreviousTask")
public Task NextTask;
#AnchorShadowVariable(sourceVariableName = "PreviousTask")
public Resource Assignee;
I have been stuck on the Local Search Phase step for some time now as it appears to require an initialized state of my planning variables (Task.PreviousTask in this case).
Error log:
2020-07-16 15:00:15.341 INFO 4616 --- [pool-1-thread-1] o.o.core.impl.solver.DefaultSolver : Solving started: time spent (65), best score (-27init/[0]hard/[0/0/0/0]soft), environment mode (REPRODUCIBLE), random (JDK with seed 0).
2020-07-16 15:00:15.356 INFO 4616 --- [pool-1-thread-1] .c.i.c.DefaultConstructionHeuristicPhase : Construction Heuristic phase (0) ended: time spent (81), best score (-27init/[0]hard/[0/0/0/0]soft), score calculation speed (90/sec), step total (0).
2020-07-16 15:00:15.376 ERROR 4616 --- [pool-1-thread-1] o.o.c.impl.solver.DefaultSolverManager : Solving failed for problemId (5e433f57-8c75-4756-8a9c-4c4ca4a83d6d).
java.lang.IllegalStateException: Local Search phase (1) needs to start from an initialized solution, but the planning variable (Task.PreviousTask) is uninitialized for the entity (com.redhat.optaplannersbs.domain.Task#697ea710).
Maybe there is no Construction Heuristic configured before this phase to initialize the solution.
I've been pouring over the documentation and trying to figure out what I've missed or broken between it and the source example but I cannot work it out. I have no Construction Heuristic configured (Same as the example), and I could not see where in the example does it ever set the previousTaskOrEmployee variable before solving.
I could supply a random PreviousTask in the initial solution model, but surely at least 1 of the tasks would have no previous task?
May I ask if you have <localSearch/> in your solverConfig.xml? If so, the <constructionHeuristic/> has to be there as well.
If none of these phases (CH nor LS) is configured, both Construction Heuristic and Local Search is added with default parameters. But once the appears in the solverConfig.xml, it's considered an override of the defaults, and a user is supposed to take care of initializing the solution (most often by providing the Construction Heuristic configuration).

web3j Error processing transaction request: insufficient funds for gas * price + value

Following this tutorial
https://github.com/web3j/web3j
Started the geth client as a private network.
Here is the contract code
pragma solidity ^0.4.10;
contract Counter {
uint256 counter =0;
function increase() public {
counter++;
}
function decrease() public{
counter--;
}
function getCounter() public constant returns (uint256) {
return counter;
}
}
Compiled the contract and genetaed the wrapper code for the contract.
Java code for Counter.sol was generated, then I tried to deploy the contract
Web3j web3 = Web3j.build(new org.web3j.protocol.http.HttpService("http://localhost:8080"));
Web3ClientVersion web3ClientVersion = web3.web3ClientVersion().send();
String clientVersion = web3ClientVersion.getWeb3ClientVersion();
Counter contract = Counter.deploy(web3, credentials,Counter.GAS_PRICE;,Counter.GAS_LIMIT).send(); // constructor params
System.out.println("before increase counter "+contract.getCounter());
contract.increase();
System.out.println("after increase counter "+contract.getCounter());
contract.decrease();
System.out.println("after decrease counter "+contract.getCounter());
Getting exception
ontract gas limit 4300000
[info] counter gas price 22000000000
[error] java.lang.RuntimeException: java.lang.RuntimeException: Error processing transaction request: insufficient funds for gas * price + value
[error] at org.web3j.tx.Contract.deploy(Contract.java:350)
[error] at org.web3j.tx.Contract.lambda$deployRemoteCall$5(Contract.java:384)
[error] at org.web3j.protocol.core.RemoteCall.send(RemoteCall.java:30)
[error] at models.smartcontract.FirstContractJava.main(FirstContractJava.java:33)
[error] Caused by: java.lang.RuntimeException: Error processing transaction request: insufficient funds for gas * price + value
[error] at org.web3j.tx.TransactionManager.processResponse(TransactionManager.java:67)
[error] at org.web3j.tx.TransactionManager.executeTransaction(TransactionManager.java:51)
[error] at org.web3j.tx.ManagedTransaction.send(ManagedTransaction.java:87)
[error] at org.web3j.tx.Contract.executeTransaction(Contract.java:275)
[error] at org.web3j.tx.Contract.create(Contract.java:317)
[error] at org.web3j.tx.Contract.deploy(Contract.java:346)
[error] ... 3 more
Then I deployed the contract using ethereum wallet because it estimates the gas limit and gas price for us.
It estimated
gas price 86440
gas limit 186440
So I changed the code like this
BigInteger gp = BigInteger.valueOf(86440);
BigInteger gl = BigInteger.valueOf(186440);
Counter contract = Counter.deploy(web3, credentials,gp,gl).send(); // constructor params
But the exception remained same.
Please guide me how to resolve this exception also how to estimate gas price and gas limit for a contract.
Web3j doesn't give very good default gas price/limit values. I believe they are hardcoded regardless of the contract you develop or the action you try to take. That being said, their default values SHOULD be ok (most of the time) if you have enough ether in your account.
Gas Price
Gas prices fluctuate depending on how much activity is on the network. The more you pay, the more likely (and faster) your transaction will be picked up. Gas prices are measured in Gwei (1 Gwei = 1000000000 Wei). You can see recent gas prices being in MainNet at https://ethgasstation.info/. Usually, you'll see most transactions paying 1-10 Gwei. For higher priority transactions (usually coin/ether transfers as those transactions don't consume a lot of gas), you may see gas prices at 100 or even 1000 Gwei. If you're running a private network, you can use whatever gas price you want (even 0), but you have to set up your miners to accept work at that low of a price. For example, with geth, you can set the minimal gas price with the --gasprice option.
MINER OPTIONS:
--mine Enable mining
--minerthreads value Number of CPU threads to use for mining (default: 8)
--etherbase value Public address for block mining rewards (default = first account created) (default: "0")
--targetgaslimit value Target gas limit sets the artificial target gas floor for the blocks to mine (default: 4712388)
--gasprice "18000000000" --> Minimal gas price to accept for mining a transactions <--
--extradata value Block extra data set by the miner (default = client version)
In your case, the default 22 Gwei is ok, but you can probably lower that to 1-5. However, the 86440 Wei when you deployed through Ethereum Wallet almost certainly won't work.
Gas Limit
Web3j just uses an old default block gas limit as its default value. It has changed over time and is currently around 8 million. Ropsten is fixed and is about 4.7 million. Web3j's default of 4.3 million is just to make sure you don't hit block size limits in test environments. However, if you start a transaction specifying 4.3 million gas at 22 Gwei, you have to have ~0.1 ether in your account. You should be able to lower you gas limit to 200,000 (based off your debug output from deployment, but you would need to post the contract code to confirm).
Balance
Finally, make sure you have ether in your account! Run a simple web3.eth.getBalance() in your geth console to confirm your balance. You can initialize an account balance in your private network in the genesis.json
{
...
"alloc": {
"<ACCT_ID>": {
"balance": "30000000000000000000000000000"
}
}
}

I am getting 'Local Search phase started with an uninitialized Solution' when I run on a larger dataset

I am developing a solver using Optaplanner 6.1.0, similar to the Vehicle Routing Problem. When I run my solver on 700 installers and 200 bookings, it will successfully solve the planning problem. But, when I used against a larger dataset (700 installers and 1220 bookings), I get
Caused by: java.lang.IllegalStateException: Local Search phase started with an uninitialized Solution. First initialize the Solution. For example, run a Construction Heuristic phase first.
but right before the exception,
16:10:40,378 INFO [DefaultConstructionHeuristicPhase] [http-listener-1(4)] Construction Heuristic phase (0) ended: step total (194), time spent (30693), best score (-1hard/-688803soft).
I am using <constructionHeuristicType>FIRST_FIT_DECREASING</constructionHeuristicType>
in my config.
Am I using it wrong?
Maybe the value range for a planning variable is empty. Especially with value range provider from entity, this is more likely. Feel free to file a jira that the error message should improve in such a case.
Diagnostic todo: Comment out the local solver phase, run the solver (so it only does the construction heuristic) and then iterate through the planning entities and print out the value for each planning value. Check if there are any nulls in there.
The fact that you have 194 steps, instead 200 steps in your CH indicates this. (If those other 6 planning entities are immovable, this won't trigger this exception (more info), so that's not the problem.)

Optaplanner - Local search phase terminated without picking a nextStep

I ran into a situation where only two valid moves that is allowed happens during the construction phase. This results in a situation where there is no valid moves to perform during local search phase. All the moves tried during the local search phase is not doable.
This results in NullPointerException at the end of local search phase.
Exception in thread "main" java.lang.NullPointerException
at org.optaplanner.core.impl.solver.scope.DefaultSolverScope.getBestScoreWithUninitializedPrefix(DefaultSolverScope.java:205)
at org.optaplanner.core.impl.solver.DefaultSolver.outerSolvingEnded(DefaultSolver.java:216)
at org.optaplanner.core.impl.solver.DefaultSolver.solve(DefaultSolver.java:161)
at com.example.jobplanner.Application.main(Application.java:328)
Here is the trace of the two valid moves that happens during the construction phase.
CH step (0), time spent (151), score (0hard/0soft), selected move count (1), picked move (com.example.jobplanner.domain.ServiceJobChip#981500 => com.example.jobplanner.domain.ShopFloorBay#9da471).
Update [fact 0:5:4216052:4216052:10:DEFAULT:NON_TRAIT:com.example.jobplanner.domain.ServiceJobChip#4054f4]
CH step (1), time spent (158), score (0hard/0soft), selected move count (1), picked move (com.example.jobplanner.domain.ServiceJobChip#4054f4 => com.example.jobplanner.domain.ShopFloorBay#15ac5d5).
Construction Heuristic phase (0) ended: step total (2), time spent (159), best score (null).
The model of the domain I am trying to optimize would be something like:
Each bay has --> set of tasks that can be performed
Job -> collection of tasks to be performed
Task --> can be scheduled to bays which can perform the task

How to Configure the Web Connector from metrics.log Values

I am reviewing the ColdFusion Web Connector settings in workers.properties to hopefully address a sporadic response time issue.
I've been advised to inspect the output from the metrics.log file (CF Admin > Debugging & Logging > Debug Output Settings > Enable Metric Logging) and use this to inform the adjustments to the settings max_reuse_connections, connection_pool_size and connection_pool_timeout.
My question is: How do I interpret the metrics.log output to inform the choice of setting values? Is there any documentation that can guide me?
Examples from over a 120 hour period:
95% of entries -
"Information","scheduler-2","06/16/14","08:09:04",,"Max threads: 150 Current thread count: 4 Current thread busy: 0 Max processing time: 83425 Request count: 9072 Error count: 72 Bytes received: 1649 Bytes sent: 22768583 Free memory: 124252584 Total memory: 1055326208 Active Sessions: 1396"
Occurred once -
"Information","scheduler-2","06/13/14","14:20:22",,"Max threads: 150 Current thread count: 10 Current thread busy: 5 Max processing time: 2338 Request count: 21 Error count: 4 Bytes received: 155 Bytes sent: 139798 Free memory: 114920208 Total memory: 1053097984 Active Sessions: 6899"
Environment:
3 x Windows 2008 R2 (hardware load balanced)
ColdFusion 10 (update 12)
Apache 2.2.21
Richard, I realize your question here is from 2014, and perhaps you have since resolved it, but I suspect your problem was that the port set in the CF admin (below the "metrics log" checkbox) was set to 8500, which is your internal web server (used by the CF admin only, typically, if at all). That's why the numbers are not changing. (And for those who don't enable the internal web server at installation of CF, or later, most values in the metrics log are null).
I address this problem in a blog post I happened to do just last week: http://www.carehart.org/blog/client/index.cfm/2016/3/2/cf_metrics_log_part1
Hope any of this helps.