I am looking for an algorithm solving the following problem.
Let $\Vert x\Vert_{*} := \sqrt{x^\mathrm{T} D \,x}$, where $D$ is a diagonal matrix with positive diagonal entries. Given $a\in \mathbb{N}^n$, $b \in \mathbb{N}$, find $$\arg \min_{x \in \mathbb{N}^n} {\vert a^{\mathrm{T}} x - b\vert}$$ with minimal $\Vert x \Vert_{*}$.
Motivation
I am creating a tools website for tabletop role-playing game (TTRPG) players. In these games, players fight together against monsters, and one player (called "GM") has to ensure these fights are of appropriate difficulty. This is done using "experience points" (XP). XP is used to estimate the strength of monsters. Each monster awards a set amount of XP (tougher monsters award more XP) and each difficulty has a target XP number. When the players defeat the monsters they gain these XP, becoming stronger as a result. If the GM selects a few monsters, how many of each do we need to ensure a good battle?
For example, the GM selects goblins, hobgoblins, and bugbears (who award 1,2, and 4 XP) to be his monsters. As threshold they select 12 XP. We would have $a^T=[1,2,4], b=12.$ $x$ describes the number of monsters picked. It is clear that there are many ways to select monsters, but most of them are undesirable. We don't want a fight against just 12 goblins, or only 3 bugbears. My idea is giving each monster a somewhat arbitrary weight: $D=diag(1,6,12)$. With this we obtain the optimal $x^T=[4,2,1]$ (4 goblins, 2 hobgoblins and 1 bugbear), a well balanced encounter. If the GM selects creatures such that we can't meet the threshold, we want to get as close as possible to it.
Why don't I use a greedy algorithm? Because I thought it would be cool and interesting not to.
First,
$$\begin{array}{ll} \underset{\mathrm x \in \Bbb N^3}{\text{minimize}} & \left| \, {\rm a}^\top {\rm x} - b \, \right|\end{array}$$
If the minimum is zero, then solve the following least-norm problem
$$\begin{array}{ll} \underset{\mathrm x \in \Bbb N^3}{\text{minimize}} & \| \mathrm x \|_*^2\\ \text{subject to} & \mathrm a^\top \mathrm x = b\end{array}$$
Using Python (NumPy + CVXPY),
which outputs
Unfortunately, according to the CVXPY documentation, there are correctness issues with this solver.