How to write an advanced while loop?

See how to write a while loop how to for a simplest possible while loop. Here, we will consider a more complicated case with possible initialization.

We begin from empty repo.

$ tb init
Created repository using module "taskblaster.repository" in "/home/myuser/tmprepo".

Create a following workflow.py

import taskblaster as tb


@tb.workflow
class WhileLoopWorkflow:
    number = tb.var()

    @tb.jump('whilebranch')
    # @tb.branch('entry') is automatic, so skipped here
    @tb.task
    def initialize(self):
        return tb.node('initialize', number=self.number)

    @tb.branch('whilebranch', loop=True)
    @tb.task
    def iterate(self):
        return tb.node(
            'iterate_task',
            number=tb.Phi(entry=self.initialize, whilebranch=self.iterate),
        )

    @tb.branch('whilebranch', loop=True)
    @tb._if(false='whilebranch', true='final')
    @tb.task
    def converged(self):
        return tb.node('converged_task', number=self.iterate)

    @tb.branch('final')
    @tb.fixedpoint
    @tb.task
    def result(self):
        return tb.node('define', obj=self.iterate)


def workflow(rn):
    rn.run_workflow(WhileLoopWorkflow(number=3))

and a following tasks.py

def initialize(number):
    # Preprocessing of possible inputs
    return number


def converged_task(number):
    # This task could determine whether atoms wave been relaxed?
    return number < 1


def iterate_task(number):
    # This could relax atoms, and return the relaxed atoms
    return number - 1


def depend_on_result(number):
    # This task depends on the final result of the while loop
    return number

We note, that we will start with entry branch, and then we will immediately make a non-conditional jump to the whilebranch. Now, we have an _if task, which either jumps back to this branch, or to final branch. We have defined the final branch task as fixedpoint, which allows us to reference it from outside of this workflow, even the branch has now been executed yet.

We can iterate the workflow few times and observe the results. We iterate the workflow 4 times, run the created tasks, and observe the outputs.

$ tb workflow workflow.py && tb run . >/dev/null && tb ls --sort=topo -c sirITfo
entry:              add new      0/?   tree/result 
                    add new      0/0   tree/initialize jump: whilebranch
whilebranch:        add new      0/1   tree/iterate-001 
if:                 add new      0/1   tree/converged-001 T=final F=whilebranch 
state    deps  tags        worker        time     folder                        output
────────────────────────────────────────────────────────────────────────────────────────────────────────
done     0/0               N/A-0/1       00:00:00 tree/initialize               3
done     1/1               N/A-0/1       00:00:00 tree/iterate-001              2
done     1/1               N/A-0/1       00:00:00 tree/converged-001            False
new      0/?                                      tree/result                   ø
$ tb workflow workflow.py && tb run . >/dev/null && tb ls --sort=topo -c sirITfo
entry:             have done     0/0   tree/initialize jump: whilebranch
whilebranch:       have done     1/1   tree/iterate-001 
if:                have done     1/1   tree/converged-001 T=final F=whilebranch jump: whilebranch
whilebranch:        add new      2/2   tree/iterate-002 
if:                 add new      1/2   tree/converged-002 T=final F=whilebranch 
state    deps  tags        worker        time     folder                        output
────────────────────────────────────────────────────────────────────────────────────────────────────────
done     0/0               N/A-0/1       00:00:00 tree/initialize               3
done     1/1               N/A-0/1       00:00:00 tree/iterate-001              2
done     1/1               N/A-0/1       00:00:00 tree/converged-001            False
done     2/2               N/A-0/1       00:00:00 tree/iterate-002              1
done     2/2               N/A-0/1       00:00:00 tree/converged-002            False
new      0/?                                      tree/result                   ø
$ tb workflow workflow.py && tb run . >/dev/null && tb ls --sort=topo -c sirITfo
entry:             have done     0/0   tree/initialize jump: whilebranch
whilebranch:       have done     1/1   tree/iterate-001 
if:                have done     1/1   tree/converged-001 T=final F=whilebranch jump: whilebranch
whilebranch:       have done     2/2   tree/iterate-002 
if:                have done     2/2   tree/converged-002 T=final F=whilebranch jump: whilebranch
whilebranch:        add new      3/3   tree/iterate-003 
if:                 add new      2/3   tree/converged-003 T=final F=whilebranch 
state    deps  tags        worker        time     folder                        output
────────────────────────────────────────────────────────────────────────────────────────────────────────
done     0/0               N/A-0/1       00:00:00 tree/initialize               3
done     1/1               N/A-0/1       00:00:00 tree/iterate-001              2
done     1/1               N/A-0/1       00:00:00 tree/converged-001            False
done     2/2               N/A-0/1       00:00:00 tree/iterate-002              1
done     2/2               N/A-0/1       00:00:00 tree/converged-002            False
done     3/3               N/A-0/1       00:00:00 tree/iterate-003              0
done     3/3               N/A-0/1       00:00:00 tree/converged-003            True
new      0/?                                      tree/result                   ø
$ tb workflow workflow.py && tb run . >/dev/null && tb ls --sort=topo -c sirITfo
entry:             have done     0/0   tree/initialize jump: whilebranch
whilebranch:       have done     1/1   tree/iterate-001 
if:                have done     1/1   tree/converged-001 T=final F=whilebranch jump: whilebranch
whilebranch:       have done     2/2   tree/iterate-002 
if:                have done     2/2   tree/converged-002 T=final F=whilebranch jump: whilebranch
whilebranch:       have done     3/3   tree/iterate-003 
if:                have done     3/3   tree/converged-003 T=final F=whilebranch jump: final
final:           update new      4/4   tree/result 
state    deps  tags        worker        time     folder                        output
────────────────────────────────────────────────────────────────────────────────────────────────────────
done     0/0               N/A-0/1       00:00:00 tree/initialize               3
done     1/1               N/A-0/1       00:00:00 tree/iterate-001              2
done     1/1               N/A-0/1       00:00:00 tree/converged-001            False
done     2/2               N/A-0/1       00:00:00 tree/iterate-002              1
done     2/2               N/A-0/1       00:00:00 tree/converged-002            False
done     3/3               N/A-0/1       00:00:00 tree/iterate-003              0
done     3/3               N/A-0/1       00:00:00 tree/converged-003            True
done     4/4               N/A-0/1       00:00:00 tree/result                   0

To view an experimental automatically generated workflow diagram of the workflow here, click here.

This structure is an example of a more advanced for loop.