how to decide number of devices complete one task? - optaplanner

I have a business model. With a task, there is a list of selectable devices. How to determine the final device to complete the task through the optimization algorithm of optaplaner, which may be 1, 2, or more. and determine the start time and end time of the task according to the optimized equipment work time. Please give me a suggestion. Thank you!
#PlanningEntity(difficultyComparatorClass = TaskDifficultyComparator.class)
#Data
#EqualsAndHashCode(callSuper = false)
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Task extends TaskOrDevice {
#PlanningVariable(valueRangeProviderRefs = { "deviceRange", "taskRange" }, graphType = PlanningVariableGraphType.CHAINED)
private TaskOrDevice previousTaskOrDevice;
#AnchorShadowVariable(sourceVariableName = "previousTaskOrDevice")
private DeviceInfo deviceInfo;
#CustomShadowVariable(variableListenerClass = StartTimeUpdatingVariableListener.class,
sources = { #PlanningVariableReference(variableName = "previousTaskOrDevice") })
private Long startTime; // In minutes
private List<DeviceInfo> selectAbleDevices;
}

Related

Optaplanner doesn't see my planning variable

So I have a class Cycle:
#PlanningEntity
public class Cycle {
private Integer START = 29;
private Integer END = 42;
private final int SUSTAIN_START = 29;
private final int SUSTAIN_END = 72;
#PlanningVariable(valueRangeProviderRefs = { "startRange" } )
public Integer getStartIndex() {
System.out.println("DEBUG: getStartIndex");
return START;
}
public void setStartIndex(Integer i) {
System.out.println("DEBUG: setStartIndex");
START = i;
END = i+13;
}
#ValueRangeProvider(id = "startRange")
public List<Integer> getStartIndexes () {
ArrayList<Integer> startRange = new ArrayList<Integer>();
for(int i = SUSTAIN_START; i < SUSTAIN_END; i++) {
startRange.add(i);
}
return startRange;
}
}
and Optplanner doesn't ever call any of these methods, and I have no clue why. I've tried adding a "#ProblemFactCollectionProperty" annotatation on the getStartIndexes method, but I read in the docs that that annotation should only be used within a PlanningSolution.
I've also tried using scanAnnotatedClasses and explicitly specifying the entityClass in my solver config and neither seemed to make a difference.
Why can't Optaplanner see my variable and why doesn't Optaplanner change it?
More Info: I'm using Optaplanner version 7.30.0.Final and I have another planning entity with two planning variables that are seen and changed by Optaplanner.
The problem, per #yurloc's comment, was that I was missing the PlanningEntityCollectionProperty for Cycles in my PlanningSolution class. Thanks for the help!

How can i get the seconds out of the chronometer?(Kotlin)

Im trying to get the seconds out of the chronometer, but it will not work properly."
private var mSeconds = 0
private fun updateChrono(){
if(mChronoRunning){
mSeconds = mSeconds +1
tvChronoSeconds.text = mSeconds.toString()
}
}
The function above should count every second, but it counts randomly an just every 2nd second."
This is the Chronometer:
private fun startChrono() {
chronometer.base = SystemClock.elapsedRealtime() +mChronoStopTime
chronometer.start()
}
private fun pauseChrono() {
mChronoStopTime = chronometer.base -SystemClock.elapsedRealtime()
chronometer.stop()
}
private fun resetChrono() {
chronometer.base = SystemClock.elapsedRealtime()
chronometer.stop()
}
Is the declaration of the var wrong?
Is the finction wrong? has anyone an idea how to do it right. Thank you!!!"
okay:what i have done so far: i made a new var
"var mElapsedSeconds = 0L"
and put it in the function.i took the elapsedRealtime, minus the base and divided it by 1000. it works with a short delay. maybe it helps someone!!!
private fun updateChrono(){
if(mChronoRunning) {
mElapsedSeconds = ((SystemClock.elapsedRealtime() - mChronometer!!.getBase()).toLong()/1000);
tvChronoSeconds.text = mElapsedSeconds.toString()
}
}

Create correct object relation

I'm starting to learn OOP and I know it's hard to build good, quality, testable code and I'm afraid to make some architectural mistake and the beginning because it's harder to refactor later.
Currently, I'm working on Laravel and I need a component (a small part of a program) to calculate online advertising statistics (CPM, EPC and so on) uisng cronjob. For this purpose, I need to collect data from the database, calculate statistic(s) and store it to related table. This need to be run through CLI using cronjob. Calculation of stats should be done if possible by SQL, but it not always can be done with current architecture.
So I need to create some reusable component which can be easily extended with new stat calculation logic, either with just fetch already calculated logic from DB and store it or fetch, calculate and store to DB. And to have ability for futuhre to use it easily in any part of application not just by CLI.
To run it from CLI I'm using Laravel command with scheduling:
class StatsComamnd extends Command
{
protected $signature = 'project:calculatestats {statName}';
public function __construct(StatsService $statsService){
parent::__construct();
$this->statsService = $statsService;
}
public function handle() {
$method = $this->argument('statName');
if(!method_exists($this, $method)) {
$this->error('Invalid stat name provided!');
}
$this->{$method}();
}
public function networkOffers():void {
$this->stastService->setStatsHandler(app(OffersNetworkStatsHandler::class))->handle();
}
public function networkOffersCpm():void{
app(OffersNetworkCpmHandler::class)->handle();
}
public function networkOffersEpc:void{
app(OffersNetworkEpcHandler::class)->handle();
}
public function networkSurveys():void{
app(SurveysNetworkHandler::class)->handle();
}
public function networkSurveysCpm():void{
app(SurveysNetrworkCpmHandler::class)->handle();
}
public function networkSurveysEpc:void{
app(SurveysNetworkEpcHandler::class)->handle();
}
//...other handlers, like countryOffersCpm, toolSpecificOffersCpm and so on
}
SurveysNetrworkCpmStatsHandler:
/** This handle responsible of collectiong, calculating and storing network wide survey CPMs. We can't calculate CPM inside DB, so here we are going to use CpmCalculator */
class SurveysNetrworkCpmStatsHandler implements StatsHandlerInterface {
private $surveyImpressionsRepo;
private $statsRepo;
private $vcPointRepo;
private $calculator;
public function __construct(
SurveyImpressionRepositoryInterface $surveyImpressionRepository,
SurveyStatsRepositoryInterface $statsRepository,
VcPointRepositoryInterface $vcPointRepository,
CpmCalculator $calculator
){
$this->surveyImpressionsRepo = $surveyImpressionRepository;
$this->calculator = $calculator;
$this->vcPointRepo = $vcPointRepository;
$this->statsRepo = $statsRepository;
}
public function handle() {
$stats = [];
list($impressions, $conversions) = $this->fetchStatisticData();
foreach ($impressions as $impression) {
$sid = $impression->survey_id;
$conversion = $conversions->first(function($conversion) use ($sid) {
return $conversion->survey_id === $sid;
});
if(!isset($conversion)) {
continue;
}
$stat = new \SurveyNetworkCpmStat();
$stat->offer_id = $impression->offer_id;
$stat->survey_id = $sid;
$stat->mobile_cpm = $this->calculator->setConversionCount($conversion->conversions_count_mobile)->setImpressionsCount($impression->unique_impressions_count_mobile)->setPayoutSum($conversion->payout_sum_mobile)->calculate();
$stat->desktop_cpm = $this->calculator->setConversionCount($conversion->conversions_count_desktop)->setImpressionsCount($impression->unique_impressions_count_desktop)->setPayoutSum($conversion->payout_sum_desktop)->calculate();
$stat[] = $stat->toArray();
}
$this->store($stats)
}
private function fetchStatisticData(){
$impressions = $this->surveyImpressionsRepo->getImpressionsForNetworkCpm();
$conversions = $this->vcPointRepo->getConversionsForSurveyNetworkCpm();
return [$impressions, $conversions];
}
private function store($stst): bool{
$this->statsRepo->insert()
}
}
SurveysNetrworkStatsHandler:
/** This handle responsible of collectiong, calculating and storing all network wide survey stats.*/
class SurveysNetrworkStatsHandler implements StatsHandlerInterface {
private $cpmHandler;
private $epcHandler;
private $statsRepo;
public function __construct(
SurveysNetrworkCpmStatsHandler $cpmHandler,
SurveysNetrworkEpcStatsHandler $epcHandler,
SurveyStatsRepositoryInterface $statsRepository
){
$this->cpmHandler = $cpmHandler;
$this->epcHandler = $epcHandler;
$this->statsRepo = $statsRepository;
}
public function handle() {
$this->cpmHandler->handle();
$this->epcHandler->handle();
}
}
OffersNetrworkCpmStatsHandler:
etrworkCpmStatsHandler:
/** This handle responsible of collectiong, calculating and storing network wide offers CPMs. We can calculate CPM inside DB, so here do not need any Calculator */
class OffersNetrworkCpmStatsHandler implements StatsHandlerInterface {
private $surveyImpressionsRepo;
private $statsRepo;
public function __construct(
SurveyImpressionRepositoryInterface $surveyImpressionRepository,
SurveyStatsRepositoryInterface $statsRepository
){
$this->surveyImpressionsRepo = $surveyImpressionRepository;
$this->statsRepo = $statsRepository;
}
public function handle() {
$stats = [];
$stats = $this->fetchStatisticData();
$this->store($stats)
}
private function fetchStatisticData(){
return $this->surveyImpressionsRepo->getCpm();
}
private function store($stst): bool{
$this->statsRepo->insert()
}
}
CpmCalculator:
/** Class NetworkCpmCalculator. This object responsible for calculation of CPM. Formula to calculate cpm is payout_sum/(impressions_count/1000) */
class NetworkCpmCalculator implements StatsCalculatorInterface {
private $payoutSum = 0;
private $impressionsCount = 0;
private $conversionsCount = 0;
public function setPayoutSum(float $payoutSum = null):self{
$this->payoutSum = $payoutSum;
return $this;
}
public function setImpressionsCount(int $impressionsCount = null):self{
$this->impressionsCount = $impressionsCount;
return $this;
}
public function setConversionCount(int $conversionsCount = null):self{
$this->conversionsCount = $conversionsCount;
return $this;
}
public function calculate():int{
if(!$this->validate()) {
return null;
}
return $this->payoutSum/($this->impressionsCount/1000);
}
//validation here
}
I remove all validation logic here and interfaces to reduca amount of code.
Can anyone suggest any improvements, maybe I can use some patterns here? Thanks for any suggestions.

Optaplanner shadow variable with more than one source

Optaplanner allows for a shadow variable to have more than one source (sources = {}) but only one variableListsnerClass. In my implementation i have a planning entity with shadow variables that should be able to change by two listsners, but this is not supported it seems or am i wrong? is there a way to have two listeners affect one shadow variable?
I have the following planning entities: PlannerActivity, PlannerTask and PlannerTaskResourceAllocation.
Any change on a PlannerActivity startIndex (genuine var) is listened to by the ActivityStartIndexVariableListener which moves the startindex (shadow var) and endIndex (shadow var) on all tasks belonging to that activity. this works fine
In addition to that, any change on a PlannerTaskResourceAllocation resource (geniune var), is listened to by TaskResourceVariableListener, and when the resource is a product, also updates the ohHandAmounts for that product, this also works fine.
The problem i have is that i need to add logic that when a resource is changed on a PlannerTaskResourceAllocation and that resource is an equipment, i need to possibly recalculate the task duration is the new equipment might be slower or faster than what was assigned before.
so what i need here is that the PlannerActivity and PlannerTask startIndex and endIndex should be able to be changed by the TaskResourceVariableListener as well, but they are already listed to by the
ActivityStartIndexVariableListener, and there's no way for me to specify two listeners for one shadow variable.
PlannerTask:
public class PlannerTask extends InventoryTransactionCause {
private static final long serialVersionUID = 1L;
#Getter
#Setter
private Activity activity;
#Getter
#Setter
private Integer indexInActivity;
// shadow variable
private Integer startIndex;
#Getter
#Setter
private double startOffset;
// shadow variable
private Integer length;
// shadow variable
private Integer endIndex;
#Getter
#Setter
private double endOffset;
#Getter
#Setter
private Integer originalStartIndex;
#Getter
#Setter
private Integer originalEndIndex;
#Getter
#Setter
private String state;
// getters and setters for shadow variables
// this is one of the shadow variables that i need affected by two
// listeners, one is the ActivityStartIndexVariableListener and the
// other is TaskResourceVariableListener
#CustomShadowVariable(variableListenerClass = ActivityStartIndexVariableListener.class,
sources = { #CustomShadowVariable.Source(entityClass = PlannerActivity.class, variableName = "endIndex"),
#CustomShadowVariable.Source(entityClass = PlannerTaskResourceAllocation.class,
variableName = "resource") })
public Integer getStartIndex() {
return this.startIndex;
}
public void setStartIndex(Integer startIndex) {
this.startIndex = startIndex;
}
#CustomShadowVariable(variableListenerClass = ActivityStartIndexVariableListener.class,
sources = { #CustomShadowVariable.Source(entityClass = PlannerActivity.class, variableName = "endIndex"),
#CustomShadowVariable.Source(entityClass = PlannerTaskResourceAllocation.class,
variableName = "resource") })
public Integer getEndIndex() {
return this.endIndex;
}
public void setEndIndex(Integer endIndex) {
this.endIndex = endIndex;
}
#CustomShadowVariable(variableListenerClass = TaskResourceVariableListener.class,
sources = { #CustomShadowVariable.Source(entityClass = PlannerTaskResourceAllocation.class,
variableName = "resource") })
public Integer getLength() {
return this.length;
}
public void setLength(Integer length) {
this.length = length;
}
}
This is supported with the variableListenerRef attribute: the first shadow variable has a normal shadow variable annotation and the second shadow variable points to the first shadow variable with #CustomShadowVariable(variableListenerRef = #PlanningVariableReference(variableName = "firstShadow"))
For example, 1 variable listener that changes 2 shadow variables that is based on 2 genuine variables:
#PlanningVariable(valueRangeProviderRefs = "valueRange")
public TestdataValue getPrimaryValue() {
return primaryValue;
}
public void setPrimaryValue(TestdataValue primaryValue) {
this.primaryValue = primaryValue;
}
#PlanningVariable(valueRangeProviderRefs = "valueRange")
public TestdataValue getSecondaryValue() {
return secondaryValue;
}
public void setSecondaryValue(TestdataValue secondaryValue) {
this.secondaryValue = secondaryValue;
}
#CustomShadowVariable(variableListenerClass = ComposedValuesUpdatingVariableListener.class,
sources = {#CustomShadowVariable.Source(variableName = "primaryValue"),
#CustomShadowVariable.Source(variableName = "secondaryValue")})
public String getComposedCode() {
return composedCode;
}
public void setComposedCode(String composedCode) {
this.composedCode = composedCode;
}
#CustomShadowVariable(variableListenerRef = #PlanningVariableReference(variableName = "composedCode"))
public String getReverseComposedCode() {
return reverseComposedCode;
}
public void setReverseComposedCode(String reverseComposedCode) {
this.reverseComposedCode = reverseComposedCode;
}
You can make shadow variables that depend on shadow variables.
Create a custom shadow variable (with a VariableListener impl) for startIndex that depends on endIndex and length (which are both shadow vars).

My Akka.Net Demo is incredibly slow

I am trying to get a proof of concept running with akka.net. I am sure that I am doing something terribly wrong, but I can't figure out what it is.
I want my actors to form a graph of nodes. Later, this will be a complex graph of business objekts, but for now I want to try a simple linear structure like this:
I want to ask a node for a neighbour that is 9 steps away. I am trying to implement this in a recursive manner. I ask node #9 for a neighbour that is 9 steps away, then I ask node #8 for a neighbour that is 8 steps away and so on. Finally, this should return node #0 as an answer.
Well, my code works, but it takes more than 4 seconds to execute. Why is that?
This is my full code listing:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Akka;
using Akka.Actor;
namespace AkkaTest
{
class Program
{
public static Stopwatch stopwatch = new Stopwatch();
static void Main(string[] args)
{
var system = ActorSystem.Create("MySystem");
IActorRef[] current = new IActorRef[0];
Console.WriteLine("Initializing actors...");
for (int i = 0; i < 10; i++)
{
var current1 = current;
var props = Props.Create<Obj>(() => new Obj(current1, Guid.NewGuid()));
var actorRef = system.ActorOf(props, i.ToString());
current = new[] { actorRef };
}
Console.WriteLine("actors initialized.");
FindNeighboursRequest r = new FindNeighboursRequest(9);
stopwatch.Start();
var response = current[0].Ask(r);
FindNeighboursResponse result = (FindNeighboursResponse)response.Result;
stopwatch.Stop();
foreach (var d in result.FoundNeighbours)
{
Console.WriteLine(d);
}
Console.WriteLine("Search took " + stopwatch.ElapsedMilliseconds + "ms.");
Console.ReadLine();
}
}
public class FindNeighboursRequest
{
public FindNeighboursRequest(int distance)
{
this.Distance = distance;
}
public int Distance { get; private set; }
}
public class FindNeighboursResponse
{
private IActorRef[] foundNeighbours;
public FindNeighboursResponse(IEnumerable<IActorRef> descendants)
{
this.foundNeighbours = descendants.ToArray();
}
public IActorRef[] FoundNeighbours
{
get { return this.foundNeighbours; }
}
}
public class Obj : ReceiveActor
{
private Guid objGuid;
readonly List<IActorRef> neighbours = new List<IActorRef>();
public Obj(IEnumerable<IActorRef> otherObjs, Guid objGuid)
{
this.neighbours.AddRange(otherObjs);
this.objGuid = objGuid;
Receive<FindNeighboursRequest>(r => handleFindNeighbourRequest(r));
}
public Obj()
{
}
private async void handleFindNeighbourRequest (FindNeighboursRequest r)
{
if (r.Distance == 0)
{
FindNeighboursResponse response = new FindNeighboursResponse(new IActorRef[] { Self });
Sender.Tell(response, Self);
return;
}
List<FindNeighboursResponse> responses = new List<FindNeighboursResponse>();
foreach (var actorRef in neighbours)
{
FindNeighboursRequest req = new FindNeighboursRequest(r.Distance - 1);
var response2 = actorRef.Ask(req);
responses.Add((FindNeighboursResponse)response2.Result);
}
FindNeighboursResponse response3 = new FindNeighboursResponse(responses.SelectMany(rx => rx.FoundNeighbours));
Sender.Tell(response3, Self);
}
}
}
The reason of such slow behavior is the way you use Ask (an that you use it, but I'll cover this later). In your example, you're asking each neighbor in a loop, and then immediately executing response2.Result which is actively blocking current actor (and thread it resides on). So you're essentially making synchronous flow with blocking.
The easiest thing to fix that, is to collect all tasks returned from Ask and use Task.WhenAll to collect them all, without waiting for each one in a loop. Taking this example:
public class Obj : ReceiveActor
{
private readonly IActorRef[] _neighbours;
private readonly Guid _id;
public Obj(IActorRef[] neighbours, Guid id)
{
_neighbours = neighbours;
_id = id;
Receive<FindNeighboursRequest>(async r =>
{
if (r.Distance == 0) Sender.Tell(new FindNeighboursResponse(new[] {Self}));
else
{
var request = new FindNeighboursRequest(r.Distance - 1);
var replies = _neighbours.Select(neighbour => neighbour.Ask<FindNeighboursResponse>(request));
var ready = await Task.WhenAll(replies);
var responses = ready.SelectMany(x => x.FoundNeighbours);
Sender.Tell(new FindNeighboursResponse(responses.ToArray()));
}
});
}
}
This one is much faster.
NOTE: In general you shouldn't use Ask inside of an actor:
Each ask is allocating a listener inside current actor, so in general using Ask is A LOT heavier than passing messages with Tell.
When sending messages through chain of actors, cost of ask is additionally transporting message twice (one for request and one for reply) through each actor. One of the popular patterns is that, when you are sending request from A⇒B⇒C⇒D and respond from D back to A, you can reply directly D⇒A, without need of passing the message through whole chain back. Usually combination of Forward/Tell works better.
In general don't use async version of Receive if it's not necessary - at the moment, it's slower for an actor when compared to sync version.