Qalculate / libqalculate

Qalculate! library and CLI
https://qalculate.github.io/
GNU General Public License v2.0
1.84k stars 148 forks source link

How to use "where" feature with three unknowns? #194

Open Vahtera opened 4 years ago

Vahtera commented 4 years ago

Hi (again) :)

I'm having trouble inputting an equation that has three different.. "clues" (I don't know what they are called in English). Example 1: x+y+z where x+y=2 and x+z=3 and y+z=4 qalc 'x+y+z where x+y=2 and x+z=3 and y+z=4' will give out:

warning: Original value (x) was not found.
x + y + z = z + 0.5

similar with: x+y+z where 2(x+y)=1 and 3(x+z)=1 and 4(y+z)=1 qalc 'x+y+z where 2(x+y)=1 and 3(x+z)=1 and 4(y+z)=1' will give out the exact same result.

inputting qalc 'x+y+z where 2(x+y)=3(x+z)=4(y+z)=1' (which should be the same as the previous) gives out:

warning: Original value (x) was not found.
x + y + z = 0.75 - 5z

How should I input those equations? Or does "where" not (yet) support three unknowns?

ps. for the record any equation with just x and y (for example x-y where x+y=2 and 2y=1) works perfectly. It's only those that have three unknown variables.

hanna-kn commented 4 years ago

The "where" syntax was implemented in response to a request for simple substitutions, e.g. x+y where x=1 and y=2 (issue https://github.com/Qalculate/libqalculate/issues/147).

If there are not a single variable to the left of the equals sign, the first variable (in alphabetical order) is isolated. x+y+z where x+y=2 and x+z=3 and y+z=4 becomes x+y+z where x=2-y and x=3-z and y=4-z. Each where substitution is done in order: x+y+z first becomes (y+2)+y+z and when Qalculate tries to replace x with z+3, x (which has already been replaced) is not found.

x+y+z where x+y=2 and x+z=3 and y+z=4 can unfortunately currently only be solved using the multisolve() function.

Vahtera commented 4 years ago

Yeah, I read #147 and that's why I though it might not support this.

Well, that's not such a big deal, multisolve() seemed to be quite functional. You can't automatically use it like "equation where multisolve()", but that's quite a small thing really. And because it's qalc, if I REALLY want to do that I can do it with a shell script :)

Thank you again!

ps. Is this out of qalc's featureset, or can we expect/hope that one day either "where" will support more variables and inputs and/or support multisolve() as an input to where? Like that you could do the example like this: x+y+z where multisolve([x+y=2, x+z=3, y+z=4]; [x, y, z]) That sounds like it would be easy to implement, which probably means it's horribly hard. (In my experience that has been the case...)

Vahtera commented 4 years ago

I was really bored, so if anyone wants/needs to use multisolve() via command line and don't want to enter the variables by hand afterwards into an equation:

#!/bin/bash

# Multisolve helper for qalc. 
# Script by Anna Vahtera 2020
# Requires qalc to be installed and working (obviously). 

multisolve() {
        INPUT=$(qalc -s "parse 2" "multisolve([$1; $2; $3];[x; y; z])")

        x="$(echo $INPUT | awk -F" " '{print $(NF -2)}')"
        y="$(echo $INPUT | awk -F" " '{print $(NF -1)}')"
        z="$(echo $INPUT | awk -F" " '{print $(NF -0)}')"

        EQUATION=$(echo $4 | sed "s/x/$x/g" | sed "s/y/$y/g" | sed "s/z/$z/g" | sed 's/\[//g' | sed 's/\]//g' | sed 's/,//g')
        RESULT=$(qalc -s "parse 2" "$EQUATION")

        echo "$4 (where $1, $2, $3) resolves to" $RESULT
        exit 1
}

noarguments() {
        echo "Usage: multisolve EQUATION1 EQUATION2 EQUATION3 PRIMARY_EQUATION"
        echo "Example: multisolve x+y=2 x+z=3 y+z=4 x+y+z"
        echo "Note: multisolve.sh support ONLY solving x, y and z. You can just use qalc if you only need x and y."
        echo ""
        exit 1
}

[[ -z "$1" || -z "$2" || -z "$3" || -z "$4" ]] && noarguments || multisolve $1 $2 $3 $4

Should work with practically any linux distro with qalc installed and working. Written and tested on an Orange Pi Lite 2 running Armbian (Debian 10 Buster). It's probably not the best shell script out there, but it works.

hanna-kn commented 4 years ago

An alternative solution is to add the initial expression to the equation system: element(multisolve([x+y=2; x+z=3; y+z=4; \a=x+y+z]; [x; y; z; \a]); 4)

This can be added as a function using function f194 element(multisolve([\y; \z; \a; 'a'=\x]; [x; y; z; 'a']); 4) in qalc, which can then be called using f194(x+y+z; x+y=2; x+z=3; y+z=4).

Vahtera commented 4 years ago

Ooh. NICE. Thank you very much for that!