Avatar billede chrisrj Forsker
26. november 2014 - 16:08 Der er 15 kommentarer og
1 løsning

Lille algoritme til at udregne arbejde for en opgave

Hejsa

Jeg sidder, nu igen, med min bysamfundssimulator og skal lave en funktion der simulerer forskere der, ja, forsker. ;)

Ideen er, at der skal være:
En effektivitetsfaktor baseret på den enktelte forskers talent, passion og erfaring med det område der forskes i. (Er lavet)

En sværhedsgrad som også skal være en faktor. (Er lavet)

En variabel der viser hvor meget arbejde der er lavet pt. (0-100%). (Er lavet)

Mulighed for mindre og større gennembrud/tilbageslag.


Eksempelvis:
Der er lavet 10 % på projektet, effektivitetsfaktoren er lav (under 0) og sværhedsgraden er høj (5-10), så risikoen for et mindre tilbageslag er stor, mens muligheden for et stort gennembrud er umuligt.

Jeg kunne godt lave en masse if'er med de forskellige scenariere, men det er jo ikke særligt elegant. :-/

Så hvordan gør en guru? :) :)


Kode til inspiration:
public void Work() {
            double EfficiencyFactor = 0, DifficultyFactor = 0;
            int MinorSetback, MajorSetback, MinorBreakthrough, MajorBreakthrough, NoWorkDone;

            if (this._ActiveResearchProject == null) {
                Console.WriteLine("Job, Scientist: Work impossible without ActiveResearchProject!");
            } else {
                if (this._ActiveResearchProject.Status != ConstructionStatus.Completed) {
                    EfficiencyFactor = this.CalcEfficiency();
                    DifficultyFactor = this._ActiveResearchProject.Difficulty;

                    if (EfficiencyFactor < 0 && DifficultyFactor > 5 && this._ActiveResearchProject.WorkDone > 50) {
                        MinorSetback = 50; //big risk
                        MajorSetback = 25; //medium risk
                        MinorBreakthrough = 10; //small chance
                        MajorBreakthrough = 0; // no chance

                        NoWorkDone = 100 - (MinorSetback + MajorSetback + MinorBreakthrough + MajorBreakthrough); //medium-small risk
                    }

                } else {
                    Console.WriteLine("Job, Scientist: Work already finished.");
                }
            }
        }
Avatar billede softspot Forsker
26. november 2014 - 17:04 #1
Jeg er ikke guru eller noget, men jeg tænker du måske kan bruge en eller anden form for beslutningsmatrix, hvor dine grænseværdier for de enkelte værdisæt angives og så hvilke procenter der er for hver af setback- og breakthrough-værdierne. Du kan så lave én funktion der evaluerer på parametrene i stedet for en masse if-sætninger.

Giver det mening?
Avatar billede chrisrj Forsker
26. november 2014 - 17:29 #2
Jah, mjoh...bortset fra, at jeg egenligt gerne ville undgå (faste)grænseværdier, hvis muligt... :)

Men tak for forslaget. Jeg ser lige om der kommer andre input. :)
Avatar billede softspot Forsker
26. november 2014 - 19:16 #3
Nu har jeg ingen idé om, hvordan du har implementeret dine regler, men matrix'en kan vel godt opbygges dynamisk, så du bliver bundet til faste grænseværdier. Det er vel mest et spørgsmål om, hvor komplekst et system du er i stand til at håndtere...
Avatar billede chrisrj Forsker
26. november 2014 - 19:54 #4
Jeg har ikke implementeret denne del endnu.

Effektivitetsfaktoren og sværhedsgraden er lavet rimelig simpelt - men de er ikke låste, så at sige. :)

...og nu ville jeg jo gerne undgå (faste)grænseværdier. ;)

Hvor komplekst? Tja, vel lige så komplekst som jeg kan forstå... :)
Avatar billede arne_v Ekspert
28. november 2014 - 03:25 #5
Her er noget til inspiration:


using System;

namespace E
{
    public struct Risk
    {
        public double MinorSetback;
        public double MajorSetback;
        public double MinorBreakthrough;
        public double MajorBreakthrough;
    }
    public struct ExternalContext
    {
        public double EfficiencyFactor;
        public double DifficultyFactor;
    }
    public struct InternalContext
    {
        public int EfficiencyFactor;
        public int DifficultyFactor;
    }
    public interface FunctionGenerator
    {
        Calculation.ConvertFunction GetEfficiencyConvertFunction();
        Calculation.ConvertFunction GetDifficultyConvertFunction();
    }
    public interface TableGenerator
    {
        double[,] GetMinorSetbackTable();
        double[,] GetMajorSetbackTable();
        double[,] GetMinorBreakthroughTable();
        double[,] GetMajorBreakthroughTable();
    }
    public static class Calculation
    {
        public delegate int ConvertFunction(double x);
        private static InternalContext External2Internal(ExternalContext extctx, ConvertFunction efficencyConvert, ConvertFunction difficultyConvert)
        {
            InternalContext res = new InternalContext();
            res.EfficiencyFactor = efficencyConvert(extctx.EfficiencyFactor);
            res.DifficultyFactor = difficultyConvert(extctx.DifficultyFactor);
            return res;
        }
        private static Risk Context2Risk(ExternalContext extctx, ConvertFunction efficencyConvert, ConvertFunction difficultyConvert,
                                        double[,] minorSetbackTable, double[,] majorSetbackTable, double[,] minorBreakthroughTable, double[,] majorBreakthroughTable)
        {
            InternalContext intctx = External2Internal(extctx, efficencyConvert, difficultyConvert);
            Risk res = new Risk();
            res.MinorSetback = minorSetbackTable[intctx.EfficiencyFactor, intctx.DifficultyFactor];
            res.MajorSetback = majorSetbackTable[intctx.EfficiencyFactor, intctx.DifficultyFactor];
            res.MinorBreakthrough = minorBreakthroughTable[intctx.EfficiencyFactor, intctx.DifficultyFactor];
            res.MajorBreakthrough = majorBreakthroughTable[intctx.EfficiencyFactor, intctx.DifficultyFactor];
            return res;
        }
        public static Risk Context2Risk(ExternalContext extctx, FunctionGenerator funcgen, TableGenerator tblgen)
        {
            return Context2Risk(extctx, funcgen.GetEfficiencyConvertFunction(), funcgen.GetDifficultyConvertFunction(),
                                tblgen.GetMinorSetbackTable(), tblgen.GetMajorSetbackTable(), tblgen.GetMinorBreakthroughTable(), tblgen.GetMajorBreakthroughTable());
        }
    }
    public class Program
    {
        public class HardcodedFunctionGenerator : FunctionGenerator
        {
            public Calculation.ConvertFunction GetEfficiencyConvertFunction()
            {
                return exteff => { if(exteff < 0) return 0; else if(exteff < 1) return 1; else return 2; };
            }
            public Calculation.ConvertFunction GetDifficultyConvertFunction()
            {
                return extdif => { if(extdif < 0) return 0; else if(extdif < 5) return 1; else return 2; };   
            }
        }
        public class HardcodedTableGenerator : TableGenerator
        {
            public double[,] GetMinorSetbackTable()
            {
                return new double[,] { { 0.4, 0.45, 0.5 }, { 0.3, 0.35, 0.4 }, { 0.2, 0.25, 0.3 } };
            }
            public double[,] GetMajorSetbackTable()
            {
                return new double[,] { { 0.1, 0.15, 0.2 }, { 0.0, 0.05, 0.1 }, { 0.0, 0.0, 0.0 } };
            }
            public double[,] GetMinorBreakthroughTable()
            {
                return new double[,] { { 0.4, 0.35, 0.3 }, { 0.5, 0.45, 0.4 }, { 0.55, 0.5, 0.5 } };
            }
            public double[,] GetMajorBreakthroughTable()
            {
                return new double[,] { { 0.1, 0.05, 0.0 }, { 0.2, 0.15, 0.1 }, { 0.25, 0.25, 0.2 } };
            }
        }
        public static void Main(string[] args)
        {
            ExternalContext extctx = new ExternalContext { EfficiencyFactor = 0.8, DifficultyFactor = 3.0 };
            Risk risk;
            risk = Calculation.Context2Risk(extctx, new HardcodedFunctionGenerator(), new HardcodedTableGenerator());
            Console.WriteLine("{0:F2} {1:F2} {2:F2} {3:F2}", risk.MajorSetback, risk.MinorSetback, risk.MinorBreakthrough, risk.MajorBreakthrough);
            extctx.EfficiencyFactor += 0.3;
            risk = Calculation.Context2Risk(extctx, new HardcodedFunctionGenerator(), new HardcodedTableGenerator());
            Console.WriteLine("{0:F2} {1:F2} {2:F2} {3:F2}", risk.MajorSetback, risk.MinorSetback, risk.MinorBreakthrough, risk.MajorBreakthrough);
            extctx.DifficultyFactor += 3.0;
            risk = Calculation.Context2Risk(extctx, new HardcodedFunctionGenerator(), new HardcodedTableGenerator());
            Console.WriteLine("{0:F2} {1:F2} {2:F2} {3:F2}", risk.MajorSetback, risk.MinorSetback, risk.MinorBreakthrough, risk.MajorBreakthrough);
            Console.ReadKey();
        }
    }
}
Avatar billede arne_v Ekspert
28. november 2014 - 03:27 #6
Hvis du ikke vil hardcode vaerdier saa skal du lave f.eks. ConfigfileFunctionGenerator og ConfigfileTableGenerator.
Avatar billede chrisrj Forsker
28. november 2014 - 08:20 #7
Nice!

Jeg ser på det ved nærmeste lejlighed. :) :)
Avatar billede chrisrj Forsker
09. december 2014 - 16:20 #8
Nå, så fik jeg endelig tid til at kigge på det igen.

Det ser fint ud og gør det jeg vil. :)

Altså bortset fra det der med at det gerne skulle være dynamisk... ;)


Jeg har så kløet mig lidt i (jule)skægget og gumlet lidt pebernødder mens jeg googlede en formel for dynamiske forholdstal. Det fik jeg sgutte meget ud af. :D MAO: NUL hits.

Så fagfolk må bruge et andet term som jeg ikke kender.

Jeg prøvede så google risikoberegning på engelsk - så får jeg en masse forskningsrapporter (høhø). Men det hjælper mig ikke rigtigt, da man jo skal betale for at se dem. :-/

Og selv om jeg så dem, tror jeg ikke, at jeg ville kunne bruge det - det er nok en tand for langhåret på dét niveau! :D


Så jeg ville egenligt gerne se et eksempel, eller noget. Hvis det var muligt? :)
Avatar billede arne_v Ekspert
09. december 2014 - 19:10 #9
Du kan jo lave det dynamisk med ConfigfileFunctionGenerator og ConfigfileTableGenerator.

Eller ConstructorArgFunctionGenerator og ConstructorArgTableGenerator.
Avatar billede arne_v Ekspert
09. december 2014 - 19:11 #10
Jeg kan godt proeve at se om jeg kan lave en kontinuerlig mapping funktion.
Avatar billede chrisrj Forsker
09. december 2014 - 19:18 #11
Det ville være super fedt, hvis du gad. :) :)
Avatar billede arne_v Ekspert
11. december 2014 - 03:43 #12
Forsoeg:


using System;

namespace E
{
    public interface IRiskEstimator
    {
        double MajorSetback(double efficiency, double difficulty);
        double MinorSetback(double efficiency, double difficulty);
        double MinorBreakthrough(double efficiency, double difficulty);
        double MajorBreakthrough(double efficiency, double difficulty);
    }
    public class ExponentialRiskEstimator : IRiskEstimator
    {
        private double aneutral;
        private double apositive;
        private double anegative;
        public  ExponentialRiskEstimator(double aneutral, double apositive, double anegative)
        {
            this.aneutral = aneutral;
            this.apositive = apositive;
            this.anegative = anegative;
        }
        private double Negative(double efficiency, double difficulty)
        {
            return Math.Pow(aneutral, efficiency/difficulty);
        }
        private double Positive(double efficiency, double difficulty)
        {
            return 1 - Math.Pow(aneutral, efficiency/difficulty);   
        }
        public double MajorSetback(double efficiency, double difficulty)
        {
            return Math.Pow(anegative, efficiency/difficulty);       
        }
        public double MinorSetback(double efficiency, double difficulty)
        {
            return Negative(efficiency, difficulty) - MajorSetback(efficiency, difficulty);
        }
        public double MinorBreakthrough(double efficiency, double difficulty)
        {
            return Positive(efficiency, difficulty) - MajorBreakthrough(efficiency, difficulty);
        }
        public double MajorBreakthrough(double efficiency, double difficulty)
        {
            return 1 - Math.Pow(apositive, efficiency/difficulty);       
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            IRiskEstimator est = new ExponentialRiskEstimator(0.5, 0.9, 0.1);
            for(int i = -1; i < 5; i++)
            {
                double efficiency = 1.0 + i * 0.5;
                double difficulty = 1.0;
                Console.WriteLine("{0:F3} {1:F3} {2:F3} {3:F3} {4:F3} {5:F3}",
                                  efficiency,
                                  difficulty,
                                  est.MajorSetback(efficiency, difficulty),
                                  est.MinorSetback(efficiency, difficulty),
                                  est.MinorBreakthrough(efficiency, difficulty),
                                  est.MajorBreakthrough(efficiency, difficulty));
            }
            for(int i = -1; i < 5; i++)
            {
                double efficiency = 1.0;
                double difficulty = 1.0 + i * 0.5;
                Console.WriteLine("{0:F3} {1:F3} {2:F3} {3:F3} {4:F3} {5:F3}",
                                  efficiency,
                                  difficulty,
                                  est.MajorSetback(efficiency, difficulty),
                                  est.MinorSetback(efficiency, difficulty),
                                  est.MinorBreakthrough(efficiency, difficulty),
                                  est.MajorBreakthrough(efficiency, difficulty));
            }
            Console.ReadKey();
        }
    }
}
Avatar billede chrisrj Forsker
11. december 2014 - 18:21 #13
Storartet. Jeg finder et passende sted at presse det ind i min kalender for at prøve det af! :) :)
Avatar billede chrisrj Forsker
29. december 2014 - 00:45 #14
Så var der sørme et lille hul i kalenderen...og ved du hvad? :)

Det ser sørme ud til at virke som jeg gerne ville have det! :D

Jeg prøvede at indsætte nogle værdier (efficiency og difficulty) der er tættere på dem jeg bruger.

Som det ses i de nederste kørsler i hvert loop, er det jo faktisk ikk' så ring' endda: https://billedeupload.dk/?v=hWZU.png
:) :)

Du får hermed en virtuel skålfuld pebernødder: http://multimedia.pol.dk/archive/00397/lol_pebern_d_LYSE_2_397473a.jpg !! :D
Avatar billede chrisrj Forsker
10. maj 2015 - 00:44 #15
Hvadøh...skal du ha' de points eller hvad hvar?? :)
Avatar billede arne_v Ekspert
10. maj 2015 - 03:13 #16
jo tak
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester