Exilian

Exilian Projects => Computer Game Development - The Indie Alley => Non-game Programs - The Tinkers' Workshop => Topic started by: Othko97 on November 11, 2014, 07:13:04 PM

Title: The Coding Help Thread
Post by: Othko97 on November 11, 2014, 07:13:04 PM
A general thread for help with coding.

To start off: I'm trying to write a parser for statistical distributions, however I have run into a minor problem. When I use the parser to find the expected value of the distribution, it gives me the variance. I honestly cannot see my fault, especially seeing as how just using my modules for any distribution works like a charm.

Code: [Select]
"""Parser for Statistical Distributions"""

from PoiDist import * #Imports Poisson functions
from BinDist import * #Imports Binomial functions
from UniDist import * #Imports Uniform Continuous functions

global DistDict #Dictionary to store distributions

DistDict = {} #Sets up dictionary

class Parser():
def __init__(self):
pass

def parse(self, string): #Parse function for parser
if "~" in string: #If input contains a tilde key, denoting a new distribution
listA = string.split("~") #Creates a list split on the tilde, allowing separation of name
name = listA[0] #Declares variable name
listB = listA[1].split("(") #Splits ListA[1] to allow the type of distribution to be found
type = str(listB[0]) #Declares variable type

if type == "B": #If a binomial distribution
listC = listB[1].split(",") #Splits listC to show number of trials and probability of success
n = str(listC[0]) #Sets n to number of trials
n = int(n) #Converts n to integer
p = str(listC[1][:-1]) #Sets p to probability of success
p = float(p) #Converts p to float
DistDict[name] = B(n, p) #Adds distribution to the dictionary

if type == "U": #If a continuous uniform distribution
listC = listB[1].split(",") #Splits listC to show upper and lower bounds
a = str(listC[0]) #Sets a to lower bound
a = float(a) #Converts a to float
b = str(listC[1][:-1]) #Sets b to upper bound
b = float(b) #Converts b to float
DistDict[name] = U(a, b) #Adds distribution to the dictionary

if type == "Po": #If a poisson distribution
l = str(listB[1][0:-1]) #Sets l to average/variance
l = float(l) #Converts l to float
DistDict[name] = Po(l) #Adds distribution to dictionary

elif "Var" or "var" in string: #If asking for a variance
listA = string.split("(") #Splits to find distribution wanted
print(DistDict[listA[1][:-1]].Var()) #Prints the variance of the requested distribution

elif "E" or "e" in string: #If asking for an expected value
listA = string.split("(") #Splits to find distribution wanted
print(DistDict[listA[1][:-1]].E()) #Prints the expected value of the requested distribution
Title: Re: The Help Thread
Post by: Jubal on November 11, 2014, 07:29:44 PM
So to get this straight, each distribution has a set of functions which you just imported that include a var and an e function?
Title: Re: The Help Thread
Post by: Glaurung on November 11, 2014, 08:01:39 PM
Also, how do you call this code? At a rough guess, you call it (at least) once to initialise your distribution dictionary, passing in a string containing a tilde and distribution name, and then again to get the desired data, passing in a string containing 'e' or 'var'. Is that right?
Title: Re: The Help Thread
Post by: Othko97 on November 11, 2014, 08:33:03 PM
Each distribution is a class containing functions for expected values and variance. The dictionary contains a variable name and the object it represents. This part certainly works correctly, as just printing parameters for the object gives them correctly. Eventually I intend to create a main program which just passes input through the parser or quits. A sample of where things go wrong looks somewhat like so:

Code: [Select]
>>>from Parser import *
>>>p = Parser()
>>>p.parse("X~B(10,0.5)")
>>>print(DistDict["X"].n)
10
>>>print(DistDict["X"].p)
0.5
>>>p.parse("E(X)")
2.5  #This should be 5.0
>>>p.parse("Var(X)")
2.5
>>>print(DistDict["X"].E())
5.0

As you can see, this is somewhat problematic. The functions themselves also work correctly, as is testified by the last line in the above demonstration. So yeah, pass it through once to set up the variable, and again to call a function.
Title: Re: The Help Thread
Post by: Othko97 on November 12, 2014, 08:37:53 AM
Solved!
Title: Re: The Help Thread
Post by: Glaurung on November 12, 2014, 08:51:28 AM
And the answer is?
Title: Re: The Help Thread
Post by: Cuddly Khan on November 12, 2014, 08:55:33 AM
It's 42!
Title: Re: The Help Thread
Post by: Othko97 on November 12, 2014, 09:31:45 AM
I still have no idea why it didn't work, but I rewrote it so that anything not containing a tilde is considered together, with a split used to find out what is wanted. This for some reason worked.
Code: [Select]
if "~" in string:
    code
else:
    listA = string.split("(")
    if listA[0] == "E" or listA[0] == "e":
        print(DistDict[str(listA[1][:-1])].E())
    elif listA[0] == "Var" or listA[0] == "var":
        print(DistDict[str(listA[1][:-1])].Var())
Title: Re: The Help Thread
Post by: Glaurung on November 12, 2014, 10:09:20 AM
Strange. I was going to suggest swapping the 'elif' sections in the original code to see what happened. Anyway, I'm glad to know it's fixed.
Title: Re: The Help Thread
Post by: Son of the King on November 12, 2014, 07:52:21 PM

Code: [Select]
elif "Var" or "var" in string: #If asking for a variance
listA = string.split("(") #Splits to find distribution wanted
print(DistDict[listA[1][:-1]].Var()) #Prints the variance of the requested distribution

elif "E" or "e" in string: #If asking for an expected value
listA = string.split("(") #Splits to find distribution wanted
print(DistDict[listA[1][:-1]].E()) #Prints the expected value of the requested distribution

These conditions are always true. Python will see them as `if ("Var") or ("var" in string)` and since "Var" is always True you'll always enter the first elif. You could do

Code: [Select]
elif "Var" in string or "var" in string
or better

Code: [Select]
elif any(f in string for f in ("var", "Var"))
or even better in my eyes

Code: [Select]
elif "var" in string.lower()
Title: Re: The Help Thread
Post by: Othko97 on November 12, 2014, 08:00:00 PM
Thank you SotK! I was wondering why that wasn't working. Looking back I recall now that I was not fully sure of the use of the in keyword in that context. However I believe my current solution is now superior as now one could have a variable denoted E or Var.