[education/kstars] /: Add a new not-default scheduler option to disable greedy scheduling.

Hy Murveit null at kde.org
Sun Nov 12 00:03:14 GMT 2023


Git commit 75d45b64e9a3bbc19df16f6e42eaf9a77932fbbe by Hy Murveit.
Committed on 11/11/2023 at 21:36.
Pushed by wreissenberger into branch 'master'.

Add a new not-default scheduler option to disable greedy scheduling.

M  +80   -1    Tests/kstars_ui/test_ekos_scheduler_ops.cpp
M  +4    -1    doc/ekos-scheduler.docbook
M  +-    --    doc/ekos_scheduler_settings.png
M  +13   -0    kstars/ekos/opsekos.ui
M  +2    -2    kstars/ekos/scheduler/greedyscheduler.cpp
M  +4    -0    kstars/kstars.kcfg

https://invent.kde.org/education/kstars/-/commit/75d45b64e9a3bbc19df16f6e42eaf9a77932fbbe

diff --git a/Tests/kstars_ui/test_ekos_scheduler_ops.cpp b/Tests/kstars_ui/test_ekos_scheduler_ops.cpp
index a2d9285a7..4276d3a81 100644
--- a/Tests/kstars_ui/test_ekos_scheduler_ops.cpp
+++ b/Tests/kstars_ui/test_ekos_scheduler_ops.cpp
@@ -129,6 +129,7 @@ void TestEkosSchedulerOps::init()
     Options::setDuskOffset(0);
     Options::setSettingAltitudeCutoff(0);
     Options::setSchedulerAlgorithm(Ekos::ALGORITHM_GREEDY);
+    Options::setGreedyScheduling(true);
 }
 
 void TestEkosSchedulerOps::cleanup()
@@ -1203,6 +1204,17 @@ void TestEkosSchedulerOps::testGreedy()
         {"Deneb",  "2021/06/14 22:44", "2021/06/15 03:48"}},
     scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
 
+    // Disable greedy scheduling, and Deneb should NOT run until Altair is done.
+    Options::setGreedyScheduling(false);
+    scheduler->evaluateJobs(false);
+    QVERIFY(checkSchedule(
+    {
+        {"Altair", "2021/06/13 23:34", "2021/06/14 03:00"},
+        {"Deneb",  "2021/06/14 03:01", "2021/06/14 03:53"},
+        {"Deneb",  "2021/06/14 22:44", "2021/06/15 03:52"}},
+    scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
+    Options::setGreedyScheduling(true);
+
     // As above, except Altair has completion condition repeat 2. It should run longer.
     // This makes a mess of things, as Altair can't complete during the first night, running into an artificial horizon constraint.
     // It also can't start the 2nd night as early as Deneb, so the 2nd night is Deneb, Altair (completing), Deneb, and Deneb finishes the 3rd night.
@@ -1219,6 +1231,17 @@ void TestEkosSchedulerOps::testGreedy()
         {"Deneb",  "2021/06/15 02:30", "2021/06/15 03:53"}},
     scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
 
+    // Again disable greedy scheduling, and Deneb should NOT run until Altair is done.
+    Options::setGreedyScheduling(false);
+    scheduler->evaluateJobs(false);
+    QVERIFY(checkSchedule(
+    {
+        {"Altair", "2021/06/13 23:34", "2021/06/14 03:18"},
+        {"Altair", "2021/06/14 23:30", "2021/06/15 02:32"},
+        {"Deneb",  "2021/06/15 02:33", "2021/06/15 03:53"}},
+    scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
+    Options::setGreedyScheduling(true);
+
     // Now we're using START_AT 6/14 1am for Altair (but not repeating twice).
     // Deneb will run until then (1am) the 1st night. Altair will run until it hits the horizon constraint.
     // Deneb runs through the end of the night, and again the next night until it completes.
@@ -1233,6 +1256,17 @@ void TestEkosSchedulerOps::testGreedy()
         {"Deneb",  "2021/06/14 22:44", "2021/06/15 02:44"}},
     scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
 
+    // Again disable greedy scheduling, and Deneb should NOT run until Altair is done.
+    Options::setGreedyScheduling(false);
+    scheduler->evaluateJobs(false);
+    QVERIFY(checkSchedule(
+    {
+        {"Altair", "2021/06/14 01:00", "2021/06/14 03:21"},
+        {"Deneb",  "2021/06/14 03:22", "2021/06/14 03:53"},
+        {"Deneb",  "2021/06/14 22:44", "2021/06/15 03:53"}},
+    scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
+    Options::setGreedyScheduling(true);
+
     // We again use START_AT 6/14 1am for Altair, but force Deneb to complete by 3:30am on 6/14.
     // So we get the same first two lines as above, but now Deneb stops on the 3rd line at 3:30.
     loadGreedySchedule(true, "Altair", atStartupCondition, finishCompletionCondition, dir, schedJob200x60, 30);
@@ -1245,7 +1279,17 @@ void TestEkosSchedulerOps::testGreedy()
         {"Deneb",  "2021/06/14 03:22", "2021/06/14 03:30"}},
     scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
 
-    // Finally, we have the same Altair constraints, but this time allow Deneb to run forever.
+    // Again disable greedy scheduling, and Deneb should NOT run until Altair is done.
+    Options::setGreedyScheduling(false);
+    scheduler->evaluateJobs(false);
+    QVERIFY(checkSchedule(
+    {
+        {"Altair", "2021/06/14 01:00", "2021/06/14 03:21"},
+        {"Deneb",  "2021/06/14 03:22", "2021/06/14 03:30"}},
+    scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
+    Options::setGreedyScheduling(true);
+
+    // We have the same Altair constraints, but this time allow Deneb to run forever.
     // It will look like the 3rd test, except Deneb keeps running through the end of the simulated time (2 days).
     loadGreedySchedule(true, "Altair", atStartupCondition, finishCompletionCondition, dir, schedJob200x60, 30);
     loadGreedySchedule(false, "Deneb", asapStartupCondition, loopCompletionCondition, dir, schedJob400x60, 30);
@@ -1257,6 +1301,41 @@ void TestEkosSchedulerOps::testGreedy()
         {"Deneb",  "2021/06/14 03:22", "2021/06/14 03:53"},
         {"Deneb",  "2021/06/14 22:44", "2021/06/15 03:52"}},
     scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
+
+    // Again disable greedy scheduling, and Deneb should NOT run until Altair is done.
+    Options::setGreedyScheduling(false);
+    scheduler->evaluateJobs(false);
+    QVERIFY(checkSchedule(
+    {
+        {"Altair", "2021/06/14 01:00", "2021/06/14 03:19"},
+        {"Deneb",  "2021/06/14 03:20", "2021/06/14 03:52"},
+        {"Deneb",  "2021/06/14 22:44", "2021/06/15 03:52"}},
+    scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
+    Options::setGreedyScheduling(true);
+
+    // Altair stars asap, Deneb has an at 1am startup and loop finish.
+    // Altair should start when it's able (about 23:35) but get interrupted by deneb which is higher priority
+    // because of its startat. Altair will start up again the next evening because Deneb's startat will have expired.
+    loadGreedySchedule(true, "Altair", asapStartupCondition, finishCompletionCondition, dir, schedJob200x60, 30);
+    loadGreedySchedule(false, "Deneb", atStartupCondition, loopCompletionCondition, dir, schedJob400x60, 30);
+    scheduler->evaluateJobs(false);
+    QVERIFY(checkSchedule(
+    {
+        {"Altair", "2021/06/13 23:34", "2021/06/14 01:00"},
+        {"Deneb",  "2021/06/14 01:00", "2021/06/14 03:52"},
+        {"Altair", "2021/06/14 23:30", "2021/06/15 01:31"}},
+    scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
+
+    // Again disable greedy scheduling. Nothing should change as no jobs were running before higher priority ones.
+    Options::setGreedyScheduling(false);
+    scheduler->evaluateJobs(false);
+    QVERIFY(checkSchedule(
+    {
+        {"Altair", "2021/06/13 23:34", "2021/06/14 01:00"},
+        {"Deneb",  "2021/06/14 01:00", "2021/06/14 03:52"},
+        {"Altair", "2021/06/14 23:30", "2021/06/15 01:31"}},
+    scheduler->getGreedyScheduler()->getSchedule(), checkScheduleTolerance));
+    Options::setGreedyScheduling(true);
 }
 
 void TestEkosSchedulerOps::testGroups()
diff --git a/doc/ekos-scheduler.docbook b/doc/ekos-scheduler.docbook
index aba7d853c..a99c1b271 100644
--- a/doc/ekos-scheduler.docbook
+++ b/doc/ekos-scheduler.docbook
@@ -73,7 +73,10 @@
       The algorithm shows its projected next start times and stop times for all job in the Scheduler table. It also shows its estimate of times jobs will run during the next 48 hours in the log panel at the bottom of the window. See the screenshot of the scheduler window at the top of this section.
         </para>
         <para>
-          The scheduling algorithm described in the above paragraph is known as the Greedy Scheduling algorithm. It is the recommended one to use. In previous versions of Ekos, there was another "Classic scheduling algorithm" which is currently being phased out. That scheme could not preempt running jobs, and thus did not make as much use of the equipment as the Greedy Algorithm. 
+          The scheduling algorithm described in the above paragraph is known as the Greedy Scheduling algorithm. It is the recommended one to use. In previous versions of Ekos, there was another "Classic scheduling algorithm" which is no longer in Ekos. That scheme could not preempt running jobs, and thus did not make as much use of the equipment as the Greedy Algorithm. 
+        </para>
+        <para>
+          There is a checkbox option in the scheduler options menu called <guilabel>Use greedy scheduling</guilabel> which defaults to being checked.  The system works as described above when it is checked. When it is unchecked the scheduler is prevented from scheduling lower priority jobs when uncompleted higher priority jobs cannot run. This results in less efficient use of the system, but may give you more control over scheduling.
         </para>
     </sect3>
     <sect3 id="scheduler-files">
diff --git a/doc/ekos_scheduler_settings.png b/doc/ekos_scheduler_settings.png
index c3ef28c3a..7ef0eef85 100644
Binary files a/doc/ekos_scheduler_settings.png and b/doc/ekos_scheduler_settings.png differ
diff --git a/kstars/ekos/opsekos.ui b/kstars/ekos/opsekos.ui
index 74b6aa894..47b10d53a 100644
--- a/kstars/ekos/opsekos.ui
+++ b/kstars/ekos/opsekos.ui
@@ -406,6 +406,19 @@
          </property>
         </widget>
        </item>
+       <item>
+        <widget class="QCheckBox" name="kcfg_GreedyScheduling">
+         <property name="toolTip">
+          <string><html><head/><body><p>When checked the scheduler tries to run lower priority jobs when no higher priority job can run. Recommended.</p></body></html></string>
+         </property>
+         <property name="text">
+          <string>Use greedy scheduling</string>
+         </property>
+         <property name="checked">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
       </layout>
      </widget>
     </item>
diff --git a/kstars/ekos/scheduler/greedyscheduler.cpp b/kstars/ekos/scheduler/greedyscheduler.cpp
index 9e4f62c1f..7fae292c1 100644
--- a/kstars/ekos/scheduler/greedyscheduler.cpp
+++ b/kstars/ekos/scheduler/greedyscheduler.cpp
@@ -324,7 +324,7 @@ SchedulerJob *GreedyScheduler::selectNextJob(const QList<SchedulerJob *> &jobs,
                 if (nextInterruption) *nextInterruption = QDateTime();
                 interruptStr = "";
             }
-            else
+            else if (Options::greedyScheduling())
             {
                 // Allow this job to be scheduled if it can run this many seconds
                 // before running into a higher priority job.
@@ -424,7 +424,7 @@ SchedulerJob *GreedyScheduler::selectNextJob(const QList<SchedulerJob *> &jobs,
         // - the selected job is a repeating job and
         // - another group member is runnable now and
         // - that group mnember is behind the selected job's iteration.
-        if (nextJob && !nextJob->getGroup().isEmpty() && nextJob->getCompletedIterations() > 0)
+        if (nextJob && !nextJob->getGroup().isEmpty() && Options::greedyScheduling() && nextJob->getCompletedIterations() > 0)
         {
             // Iterate through the jobs list, first finding the selected job, the looking at all jobs after that.
             bool foundSelectedJob = false;
diff --git a/kstars/kstars.kcfg b/kstars/kstars.kcfg
index b9afdcee5..319325a53 100644
--- a/kstars/kstars.kcfg
+++ b/kstars/kstars.kcfg
@@ -2813,6 +2813,10 @@
          <label>When processing a scheduled job, resume the sequence starting from the last image present in storage.</label>
          <default>true</default>
       </entry>
+      <entry name="GreedyScheduling" type="Bool">
+         <label>When true, the scheduler tries to run lower priority jobs when no higher priority job can run. Recommended.</label>
+         <default>true</default>
+      </entry>
       <entry name="LeadTime" type="Double">
          <label>Minimum time between jobs in minutes.</label>
          <default>5</default>


More information about the kde-doc-english mailing list