promworkbench / BasicStochasticMiner

0 stars 0 forks source link

What does 'bad' mean? #1

Open AdamBanham opened 6 months ago

AdamBanham commented 6 months ago

Dear Sander,

What does the sysout of 'bad' mean in the following snippet in the solver?

https://github.com/promworkbench/BasicStochasticMiner/blob/8d1485cab435ba51753820149d6e6e01a7fc5cca/src/org/processmining/basicstochasticminer/solver/Solver.java#L53-L63

AdamBanham commented 6 months ago

In one execution of the solver, I saw the following in sysout.

!--- starting run 999 ---!
--- starting discovery of weights ---
--- built equations ---
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
bad
--- found solution ---
!--- average weight after 1000 runs ---!
~~~ solved variable ~~~
base_t_1 was set to 1.0
~~~ solved variable ~~~
adjust_x_t_1^0.0 was set to 1.0
~~~ solved variable ~~~
base_t_2 was set to 8.499961831395261
~~~ solved variable ~~~
adjust_x_t_2^0.0 was set to 0.9749784490546685
~~~ solved variable ~~~
base_t_3 was set to 6.061515718802166
~~~ solved variable ~~~
adjust_x_t_3^0.0 was set to 0.9775940931599493
~~~ solved variable ~~~
base_t_5 was set to 8.175634150966115
~~~ solved variable ~~~
adjust_x_t_5^1.0 was set to 0.5726823284575581
~~~ solved variable ~~~
base_t_4 was set to 4.479076187389696
~~~ solved variable ~~~
adjust_x_t_4^1.0 was set to 0.6214623434651779

Should I be worried?

AdamBanham commented 6 months ago

Here is the code snippet I am using, in case you want to debug further.

package org.processmining.qut.exogenousaware.ab.jobs;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.processmining.basicstochasticminer.solver.Division;
import org.processmining.basicstochasticminer.solver.Equation;
import org.processmining.basicstochasticminer.solver.Function;
import org.processmining.basicstochasticminer.solver.Product;
import org.processmining.basicstochasticminer.solver.Solver;
import org.processmining.basicstochasticminer.solver.Sum;
import org.processmining.basicstochasticminer.solver.Variable;
import org.processmining.basicstochasticminer.solver.VariablePower;

public class BPM2024B {

    private static int RUNS = 1000;

    /*
     * Main entry point
     */
    public static void main(String[] args) throws Throwable {
        System.out.println("!--- Starting run 1 ---!");
        Tuple<List<Function>, double[]> out = runSolution();
//      testing for determinism
        for(int j = 0; j < RUNS-1; j++) {
            System.out.println(String.format("!--- starting run %d ---!", j+1));
            Tuple<List<Function>, double[]> inner = runSolution();
            for(int i = 0; i < inner.getRight().length; i++) {
                out.getRight()[i] += inner.getRight()[i];
            }
        }
        System.out.println(
                String.format("!--- average weight after %d runs ---!", RUNS)
        );
        for (int i = 0; i < out.getLeft().size(); i++) {
            System.out.println(
                    "~~~ solved variable ~~~\n"+
                    out.getLeft().get(i).toString()+
                    " was set to "+
                    out.getRight()[i] / RUNS
            );
        }
    }

    public static Tuple<List<Function>,double[]> runSolution() {
        System.out.println("--- starting discovery of weights ---");
        Tuple<List<Equation>,List<Function>> out = buildEquations();
        System.out.println("--- built equations ---");
        int[] fixed = new int[out.getRight().size()];
        int[] nonzero = new int[out.getRight().size()];
        double[] inital = new double[out.getRight().size()];
        for(int i = 0; i < out.getRight().size(); i++) {
            fixed[i] = 0;
            inital[i] =  1;         
            nonzero[i] = 1;
        }
        double[] solvedvalues = Solver.solve(out.getLeft(), out.getRight().size(), fixed, nonzero, inital);
        System.out.println("--- found solution ---");
        return new Tuple<>(out.getRight(), solvedvalues);       
    }

    public static class VariableCounter {

        int count = 0;

        public VariableCounter() {
        }

        public int get() {
            return this.count;
        }

        public void incr() {
            this.count++;
        }
    }

    public static String BASE_T1 = "base_t_1";
    public static String BASE_T2 = "base_t_2";
    public static String BASE_T3 = "base_t_3";
    public static String BASE_T4 = "base_t_4";
    public static String BASE_T5 = "base_t_5";

    public static String ADJUST_X_T1 = "adjust_x_t_1";
    public static String ADJUST_X_T2 = "adjust_x_t_2";
    public static String ADJUST_X_T3 = "adjust_x_t_3";
    public static String ADJUST_X_T4 = "adjust_x_t_4";
    public static String ADJUST_X_T5 = "adjust_x_t_5";

    /*
     * Builds the dummy equations in paper
     */
    public static Tuple<List<Equation>,List<Function>> buildEquations() {
        List<Equation> eqs = new ArrayList<>();
        List<Function> vars = new ArrayList<>();
        Map<String, Tuple<Function,Integer>> varnames = new HashMap<>();
        VariableCounter counter =  new VariableCounter();
//      first equation
//      1/1 = (base_t_1 . adjust_t_1^0)/ (base_t_1 . adjust_t_1^0)
        eqs.add(
                createEquation(1/1.0f, 0, BASE_T1, ADJUST_X_T1, varnames, vars, counter)
        );
//      1/1 = (base_t_1 . adjust_t_1^19)/ (base_t_1 . adjust_t_1^19)
        eqs.add(
                createEquation(1/1.0f, 19, BASE_T1, ADJUST_X_T1, varnames, vars, counter)
        );
//      1/1 = (base_t_1 . adjust_t_1^63)/ (base_t_1 . adjust_t_1^63)
        eqs.add(
                createEquation(1/1.0f, 63, BASE_T1, ADJUST_X_T1, varnames, vars, counter)
        );
//      1/2 = (base_t_2 . adjust_t_2^0) / ( base_t_2 . adjust_t_2^0 + base_t_3 . adjust_t_3^0)
        eqs.add( 
                createEquation(1/2.0f, 0,
                        BASE_T2, ADJUST_X_T2, varnames, vars, counter,
                        new Tuple<>(BASE_T3,ADJUST_X_T3))
        );
//      1/2 = (base_t_3 . adjust_t_3^0) / ( base_t_2 . adjust_t_2^0 + base_t_3 . adjust_t_3^0)
        eqs.add( 
                createEquation(1/2.0f, 0,
                        BASE_T3, ADJUST_X_T3, varnames, vars, counter,
                        new Tuple<>(BASE_T2,ADJUST_X_T2))
        );
//      1/1 = (base_t_2 . adjust_t_2^5) / ( base_t_2 . adjust_t_2^5 + base_t_3 . adjust_t_3^5)
        eqs.add( 
                createEquation(1/1.0f, 5,
                        BASE_T2, ADJUST_X_T2, varnames, vars, counter,
                        new Tuple<>(BASE_T3,ADJUST_X_T3))
        );
//      1/1 = (base_t_2 . adjust_t_2^21) / ( base_t_2 . adjust_t_2^21 + base_t_3 . adjust_t_3^21)
        eqs.add( 
                createEquation(1/1.0f, 21,
                        BASE_T2, ADJUST_X_T2, varnames, vars, counter,
                        new Tuple<>(BASE_T3,ADJUST_X_T3))
        );
//      1/1 = (base_t_3 . adjust_t_3^22) / ( base_t_2 . adjust_t_2^22 + base_t_3 . adjust_t_3^22)
        eqs.add( 
                createEquation(1/1.0f, 22,
                        BASE_T3, ADJUST_X_T3, varnames, vars, counter,
                        new Tuple<>(BASE_T2,ADJUST_X_T2))
        );
//      1/1 = (base_t_3 . adjust_t_3^36) / ( base_t_2 . adjust_t_2^36 + base_t_3 . adjust_t_3^36)
        eqs.add( 
                createEquation(1/1.0f, 36,
                        BASE_T3, ADJUST_X_T3, varnames, vars, counter,
                        new Tuple<>(BASE_T2,ADJUST_X_T2))
        );
//      1/1 = (base_t_2 . adjust_t_2^48) / ( base_t_2 . adjust_t_2^48 + base_t_3 . adjust_t_3^48)
        eqs.add( 
                createEquation(1/1.0f, 48,
                        BASE_T2, ADJUST_X_T2, varnames, vars, counter,
                        new Tuple<>(BASE_T3,ADJUST_X_T3))
        );
//      1/1 = (base_t5 . adjust_t_5^1) / (base_t4 . adjust_t_4^1 + base_t5 . adjust_t_5^1)
        eqs.add( 
                createEquation(1/1.0f, 1,
                        BASE_T5, ADJUST_X_T5, varnames, vars, counter,
                        new Tuple<>(BASE_T4, ADJUST_X_T4)
                )
        );
//      1/1 = (base_t5 . adjust_t_5^9) / (base_t4 . adjust_t_4^9 + base_t5 . adjust_t_5^9)
        eqs.add( 
                createEquation(1/1.0f, 9,
                        BASE_T5, ADJUST_X_T5, varnames, vars, counter,
                        new Tuple<>(BASE_T4, ADJUST_X_T4)
                )
        );
//      ? = 1
//      4/4 = (base_t4 . adjust_t_4^0) / (base_t4 . adjust_t_4^0 + base_t5 . adjust_t_5^0)
//      eqs.add( 
//              createEquation(4/4.0f, 1,
//                      BASE_T4, ADJUST_X_T4, varnames, vars, counter,
//                      new Tuple<>(BASE_T5, ADJUST_X_T5)
//              )
//      );
//      !- ? = next theta -!
//      1/1 = (base_t4 . adjust_t_4^5) / (base_t_4 . adjust_t_4^5) + base_t_5 . adjust_t_5^5)
        eqs.add(
                createEquation(1/1.0f, 5,
                        BASE_T4, ADJUST_X_T4, varnames, vars, counter,
                        new Tuple<>(BASE_T5, ADJUST_X_T5)
                )
        );
//      1/1 = (base_t_4 . adjust_t_4^0) / (base_t_4 . adjust_t_4^0) + base_t_5 . adjust_t_5^0)
        eqs.add(
                createEquation(1/1.0f, 0,
                        BASE_T4, ADJUST_X_T4, varnames, vars, counter,
                        new Tuple<>(BASE_T5, ADJUST_X_T5)
                )
        );
//      1/1 = (base_t_4 . adjust_t_4^36) / (base_t_4 . adjust_t_4^36) + base_t_5 . adjust_t_5^36)
        eqs.add(
                createEquation(1/1.0f, 36,
                        BASE_T4, ADJUST_X_T4, varnames, vars, counter,
                        new Tuple<>(BASE_T5, ADJUST_X_T5)
                )
        );
//      1/1 = (base_t_4 . adjust_t_4^22) / (base_t_4 . adjust_t_4^22) + base_t_5 . adjust_t_5^22)
        eqs.add(
                createEquation(1/1.0f, 22,
                        BASE_T4, ADJUST_X_T4, varnames, vars, counter,
                        new Tuple<>(BASE_T5, ADJUST_X_T5)
                )
        );
//      !- ! = average seen -!
//      1\1 = (base_t_5 . adjust_t_5^5 / (base_t_4 . adjust_t_4^5 + base_t_5 . adjust_t_5^5)
        eqs.add( 
                createEquation(1/1.0f, 5,
                        BASE_T5, ADJUST_X_T5, varnames, vars, counter,
                        new Tuple<>(BASE_T4, ADJUST_X_T4)
                )
        );
        return new Tuple<List<Equation>, List<Function>>(eqs,vars);
    }

    @SafeVarargs
    public static Equation createEquation(
            double value, int power, 
            String topBase, String topAdjust,
            Map<String, Tuple<Function,Integer>> lookup, 
            List<Function> storage, 
            VariableCounter counter,
            Tuple<String,String>... Bottoms) {

//      build top (always the same)
        Function b1 = createVarIfNeeded(topBase, lookup, storage, counter);
        Function x1 = createVarIfNeeded(topAdjust, lookup, storage, counter, power);
        Product top = new Product(b1 , x1);
//      build bottom (different)
        Sum bottom = new Sum(top);
        for (int i = 0; i < Bottoms.length; i++) {
            String botBase = Bottoms[i].getLeft();
            String botAdjust = Bottoms[i].getRight();
            bottom = new Sum(bottom,
                new Product( 
                        createVarIfNeeded(botBase, lookup, storage, counter),
                        createVarIfNeeded(botAdjust, lookup, storage, counter, power)
                )
            );
        }
        Division right = new Division(top, bottom);
//      set value for right
        return new Equation(value, right, 1);
    }

    public static Function createVarIfNeeded(String name, Map<String, Tuple<Function,Integer>> lookup, List<Function> storage, VariableCounter var_count){
        return createVarIfNeeded(name, lookup, storage, var_count, 1);
    }

    public static Function createVarIfNeeded(String name, Map<String, Tuple<Function,Integer>> lookup, List<Function> storage, VariableCounter var_count, int power) {
        Function out;

        if (lookup.containsKey(name)) {
            if (name.contains("adjust")) {
                Tuple<Function,Integer> old = lookup.get(name);
                out = new VariablePower(old.getRight(), name, power);
            } else {
                out = lookup.get(name).getLeft();
            }
        } else {
            if (name.contains("adjust")) {
                out = new VariablePower(var_count.get(),name, power);
                lookup.put(name, new Tuple<>(out, var_count.get()));
            } else {
                out = new Variable(var_count.get(), name);
                lookup.put(name, new Tuple<>(out, var_count.get()));
            }
            storage.add(out);
            var_count.incr();
        }

        return out;
    }

}