Logbook + Scratchpad

TIL

In the previous post I mentioned that I have recently discovered Voilà, a Python project whose purpose is to convert Jupyter Notebooks into standalone Web applications. This is particularly useful when a notebook contains a lot of interactive components like Jupyter widgets, and you want users to only see them as a UI without any code.

I've quickly tried it with a notebook I had, and it is quite easy to set up. You just need to make sure that there are no cells that “hang up” with calls to external APIs or processes that require user interaction to be stopped. I'll share a more detailed example when I have a more interesting (interaction-wise) notebook.

There is a dedicated website with a gallery of examples, which are not only useful to discover what is possible with Voilà but also to find other Python tools that may be useful for other things.

#TIL #tech #python

A few times I thought that it would be nice to be able to generate and display LaTeX expressions in a Jupyter notebook (meaning in code, not in Markdown cells), but I never really got to look for a solution.

Today, while looking for something else, I have come across a nice trick in a notebook meant to showcase Voilà (which I will explore in a different post).

The HTML class in IPython.display can display LaTeX expressions interspersed with HTML code and variables, so for example you can generate a few h1 LaTeX headers doing the following:

from IPython.display import HTML

for char in ['B', 'C', 'D']:
    display(HTML(r"<h1>$f(x, y)=\displaystyle \frac{A}{%s}$</h1>" % char))

The result is this:

$f(x, y)=\displaystyle \frac{A}{B}$ $f(x, y)=\displaystyle \frac{A}{C}$ $f(x, y)=\displaystyle \frac{A}{D}$

If all you need is LaTeX without any formatting, just use the Latex class from IPython.display:

from IPython.display import Latex

for char in ['B', 'C', 'D']:
    display(Latex(r"$f(x, y)=\displaystyle \frac{A}{%s}$" % char))

Another nice option is to use the sympy package and write symbolic formulae that can be converted to LaTeX directly with the latex function:

import sympy

x, y = sympy.symbols('x y')
HTML(r"$f(x,y)= %s$" % sympy.latex(x + y))

The result is this:

$f(x, y)= x + y$

#TIL #tech #python

In my (re)exploration of PDDL I've understood better not only how different language features drive the decision of what planner to use, but also one more dimension that makes planners different: satisfiability versus optimality.

Numeric and temporal domains

Beyond classical planning based on predicates (using :predicates and :actions in PDDL), it is possible to plan based on numeric quantities (:functions) and actions with a duration (:durative-actions). The two domains can be mixed, for example by expressing durations as functions rather than fixed numbers. Both require the use of a metric (:metric), which can be any numeric function (or just total-time for temporal domains) to be minimized or maximized.

Some planners like LPG-td can cover both domains, but more often than not planners specialize in one of the two (and not many planners cover the temporal domain).

Satisficing vs optimal planners

A planner can not only cover just some construct of PDDL (say, numeric fluents but not durative actions), but also be limited to find solutions that satisfy the domain (satisficing planners) without necessarily be optimal (a task for optimal planners). Some planners such as ENHSP can even do both, but it's necessary to always make sure of the capabilities of a planner with respect to the problem to solve.

#TIL #tech #AI #planning

In the previous post I mentioned the planutils project as an easy way to try several PDDL planners. Today I learned about the planutils server, a simple Flask app that exposes an HTTP API to invoke planners remotely, and I thought it's a brilliant idea. As of now, the API can only be used to get information on installed planners and to invoke each of them with its basic parameters, namely the PDDL domain and problem.

The nice thing about it is that there is a setup script to set up a planutils server Docker container with a few representative planners (among which OPTIC for PDDL3 support, ENHSP-2020 for numeric planning, and TFD for temporal planning) and an exposed port (5555 by default).

With the server container running, the API can be used with any usual tool. An example with curl could be like this:

curl -s -H "Content-Type: application/json" -d "{\"domain\": \"$(cat domain.pddl | tr '\n' ' ')\", \"problem\": \"$(cat problem.pddl | tr '\n' ' ')\"}" localhost:5555/package/enhsp-2020/solve

In this example, the two PDDL files are converted to strings and passed to the ENHSP-2020 planner as JSON values.

I will shortly put all this in a GitHub repo along with some example PDDL files for reference.

#TIL #tech #AI #planning

Prompted by a recent discussion, I went “back to the basics” and took a new look at PDDL.

The language, based on STRIPS (which I know from early courses in robotics), has undergone several improvements to make it more and more expressive. This means that, as it happened with RDFS, OWL, and their reasoners, there are different planners that make use of one version of the language or another, and finding what planner supports what version and what specific features of the language is not always easy.

The Planning.wiki website has a good review of the main versions of the languages as well as a list of (some of) the known planners. Today I also discovered the planutils project that aims to make trying different planners easier by packaging them with Docker. The setup is quite easy and using it is also relatively straightforward.

I began doing some experiments with PDDL myself, which I'll write about in another post.

#TIL #tech #AI #planning

Today I was still configuring a Fedora-based server, and I noticed that SELinux was not enabled by default. To make sure not to mess up and lose access to the server, I followed the guide on the Fedora website and I enabled the Permissive mode first, set the files to be relabeled after reboot, and rebooted. After reboot, I checked for errors using this command:

$ ausearch -m AVC,USER_AVC,SELINUX_ERR,USER_SELINUX_ERR -ts recent

I saw one error related to the SSH port, and I learned that I needed to explicitly tell SELinux when SSH runs on a different port (which, in this case, I had changed as part of the setting up process):

$ semanage port -a -t ssh_port_t -p tcp 2222

Having fixed this, I finally set SELinux to Enforcing.

#TIL #tech #sysadmin

Today I was performing a very common ritual of the software development world: using SSH to log onto a server.

Although I always use SSH keys, for a couple of reasons today I needed to temporarily enable password access. I made sure that password authentication was enabled by setting PasswordAuthentication yes in the sshd_config file and restarting the sshd service, but this didn't seem to work.

After a little debugging, I learned that there might be additional SSH configuration files in the /etc/ssh/sshd_config.d directory; sure enough, there was a file which was overriding my configuration with PasswordAuthentication no. After getting rid of such file, I finally got password access.

Inspecting SSH logs

Another thing I learned today: I was used to inspect the /var/log/auth.log file (or the /var/log/secure file in CentOS), but there was neither on this server whose OS was Fedora 39. Since systemd is now the default, the standard way of inspecting service logs is to use journalctl as follows:

$ journalctl -u sshd | tail

#TIL #sysadmin

The recent demise of a server because of a hard drive failure inspired me to brush up my knowledge of command-line monitoring tools. I have used smartmontools in the past, and I needed a refresher on smartctl.

Given a /dev/sdX device, you can get a quick health report as follows:

$ smartctl -H /dev/sdX

For a full report, do this:

$ smartctl -a /dev/sdX

The values to be worried about are in the WHEN_FAILED column of the SMART Attributes table. To see this table only, run the following command:

$ smartctl -A /dev/sdX

What I didn't remember, and I relearned today, is that you can run tests (both short and long) in the background:

$ smartctl -t short /dev/sdX (or -t long)

Most importantly, you can poll the test progress with the following:

$ smartctl -a /dev/sdX | grep -A 1 "Self-test execution"

#TIL #tech