Advertisement
Guest User

Untitled

a guest
Jun 25th, 2016
261
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.67 KB | None | 0 0
  1. # factorOperations.py
  2. # -------------------
  3. # Licensing Information:  You are free to use or extend these projects for
  4. # educational purposes provided that (1) you do not distribute or publish
  5. # solutions, (2) you retain this notice, and (3) you provide clear
  6. # attribution to UC Berkeley, including a link to http://ai.berkeley.edu.
  7. #
  8. # Attribution Information: The Pacman AI projects were developed at UC Berkeley.
  9. # The core projects and autograders were primarily created by John DeNero
  10. # (denero@cs.berkeley.edu) and Dan Klein (klein@cs.berkeley.edu).
  11. # Student side autograding was added by Brad Miller, Nick Hay, and
  12. # Pieter Abbeel (pabbeel@cs.berkeley.edu).
  13.  
  14.  
  15. from bayesNet import Factor
  16. import operator as op
  17. import util
  18.  
  19. def joinFactorsByVariableWithCallTracking(callTrackingList=None):
  20.  
  21.  
  22.     def joinFactorsByVariable(factors, joinVariable):
  23.         """
  24.        Input factors is a list of factors.
  25.        Input joinVariable is the variable to join on.
  26.  
  27.        This function performs a check that the variable that is being joined on
  28.        appears as an unconditioned variable in only one of the input factors.
  29.  
  30.        Then, it calls your joinFactors on all of the factors in factors that
  31.        contain that variable.
  32.  
  33.        Returns a tuple of
  34.        (factors not joined, resulting factor from joinFactors)
  35.        """
  36.  
  37.         if not (callTrackingList is None):
  38.             callTrackingList.append(('join', joinVariable))
  39.  
  40.         currentFactorsToJoin =    [factor for factor in factors if joinVariable in factor.variablesSet()]
  41.         currentFactorsNotToJoin = [factor for factor in factors if joinVariable not in factor.variablesSet()]
  42.  
  43.         # typecheck portion
  44.         numVariableOnLeft = len([factor for factor in currentFactorsToJoin if joinVariable in factor.unconditionedVariables()])
  45.         if numVariableOnLeft > 1:
  46.             print "Factor failed joinFactorsByVariable typecheck: ", factor
  47.             raise ValueError, ("The joinBy variable can only appear in one factor as an \nunconditioned variable. \n" +  
  48.                                "joinVariable: " + str(joinVariable) + "\n" +
  49.                                ", ".join(map(str, [factor.unconditionedVariables() for factor in currentFactorsToJoin])))
  50.        
  51.         joinedFactor = joinFactors(currentFactorsToJoin)
  52.         return currentFactorsNotToJoin, joinedFactor
  53.  
  54.     return joinFactorsByVariable
  55.  
  56. joinFactorsByVariable = joinFactorsByVariableWithCallTracking()
  57.  
  58.  
  59. def joinFactors(factors):
  60.     """
  61.    Question 1: Your join implementation
  62.  
  63.    Input factors is a list of factors.  
  64.    
  65.    You should calculate the set of unconditioned variables and conditioned
  66.    variables for the join of those factors.
  67.  
  68.    Return a new factor that has those variables and whose probability entries
  69.    are product of the corresponding rows of the input factors.
  70.  
  71.    You may assume that the variableDomainsDict for all the input
  72.    factors are the same, since they come from the same BayesNet.
  73.  
  74.    joinFactors will only allow unconditionedVariables to appear in
  75.    one input factor (so their join is well defined).
  76.  
  77.    Hint: Factor methods that take an assignmentDict as input
  78.    (such as getProbability and setProbability) can handle
  79.    assignmentDicts that assign more variables than are in that factor.
  80.  
  81.    Useful functions:
  82.    Factor.getAllPossibleAssignmentDicts
  83.    Factor.getProbability
  84.    Factor.setProbability
  85.    Factor.unconditionedVariables
  86.    Factor.conditionedVariables
  87.    Factor.variableDomainsDict
  88.    """
  89.  
  90.     # typecheck portion
  91.     setsOfUnconditioned = [set(factor.unconditionedVariables()) for factor in factors]
  92.     if len(factors) > 1:
  93.         intersect = reduce(lambda x, y: x & y, setsOfUnconditioned)
  94.         if len(intersect) > 0:
  95.             print "Factor failed joinFactors typecheck: ", factor
  96.             raise ValueError, ("unconditionedVariables can only appear in one factor. \n"
  97.                     + "unconditionedVariables: " + str(intersect) +
  98.                     "\nappear in more than one input factor.\n" +
  99.                     "Input factors: \n" +
  100.                     "\n".join(map(str, factors)))
  101.  
  102.     unconditionedVariables = reduce(lambda x, y: x|y, setsOfUnconditioned)
  103.     conditionedVariables   = reduce(lambda x, y: x|y, [set(factor.conditionedVariables()) for factor in factors])
  104.     conditionedVariables  -= unconditionedVariables
  105.     newFactor = Factor(unconditionedVariables, conditionedVariables, factors[0].variableDomainsDict())
  106.  
  107.     for assignmentDict in newFactor.getAllPossibleAssignmentDicts():
  108.         probability = reduce(lambda x,y: x * y.getProbability(assignmentDict), factors[1:], factors[0].getProbability(assignmentDict))
  109.         newFactor.setProbability(assignmentDict, probability)
  110.  
  111.     return newFactor
  112.  
  113. def eliminateWithCallTracking(callTrackingList=None):
  114.  
  115.     def eliminate(factor, eliminationVariable):
  116.         """
  117.        Question 2: Your eliminate implementation
  118.  
  119.        Input factor is a single factor.
  120.        Input eliminationVariable is the variable to eliminate from factor.
  121.        eliminationVariable must be an unconditioned variable in factor.
  122.        
  123.        You should calculate the set of unconditioned variables and conditioned
  124.        variables for the factor obtained by eliminating the variable
  125.        eliminationVariable.
  126.  
  127.        Return a new factor where all of the rows mentioning
  128.        eliminationVariable are summed with rows that match
  129.        assignments on the other variables.
  130.  
  131.        Useful functions:
  132.        Factor.getAllPossibleAssignmentDicts
  133.        Factor.getProbability
  134.        Factor.setProbability
  135.        Factor.unconditionedVariables
  136.        Factor.conditionedVariables
  137.        Factor.variableDomainsDict
  138.        """
  139.         # autograder tracking -- don't remove
  140.         if not (callTrackingList is None):
  141.             callTrackingList.append(('eliminate', eliminationVariable))
  142.  
  143.         # typecheck portion
  144.         if eliminationVariable not in factor.unconditionedVariables():
  145.             print "Factor failed eliminate typecheck: ", factor
  146.             raise ValueError, ("Elimination variable is not an unconditioned variable " \
  147.                             + "in this factor\n" +
  148.                             "eliminationVariable: " + str(eliminationVariable) + \
  149.                             "\nunconditionedVariables:" + str(factor.unconditionedVariables()))
  150.        
  151.         if len(factor.unconditionedVariables()) == 1:
  152.             print "Factor failed eliminate typecheck: ", factor
  153.             raise ValueError, ("Factor has only one unconditioned variable, so you " \
  154.                     + "can't eliminate \nthat variable.\n" + \
  155.                     "eliminationVariable:" + str(eliminationVariable) + "\n" +\
  156.                     "unconditionedVariables: " + str(factor.unconditionedVariables()))
  157.  
  158.         unconditionedVariables = factor.unconditionedVariables()
  159.         unconditionedVariables.remove(eliminationVariable)
  160.         conditionedVariables = factor.conditionedVariables()
  161.         newFactor = Factor(unconditionedVariables, conditionedVariables, factor.variableDomainsDict())
  162.  
  163.         eliminationVariableDomain = factor.variableDomainsDict()[eliminationVariable]
  164.         for assignmentDict in factor.getAllPossibleAssignmentDicts():
  165.  
  166.             marginalProbability = 0
  167.             for eliminationAssignment in eliminationVariableDomain:
  168.                 assignmentDict[eliminationVariable] = eliminationAssignment
  169.                 marginalProbability += factor.getProbability(assignmentDict)
  170.             assignmentDict.pop(eliminationVariable)
  171.             newFactor.setProbability(assignmentDict, marginalProbability)
  172.  
  173.         return newFactor
  174.  
  175.     return eliminate
  176.  
  177. eliminate = eliminateWithCallTracking()
  178.  
  179.  
  180. def normalize(factor):
  181.     """
  182.    Question 3: Your normalize implementation
  183.  
  184.    Input factor is a single factor.
  185.  
  186.    The set of conditioned variables for the normalized factor consists
  187.    of the input factor's conditioned variables as well as any of the
  188.    input factor's unconditioned variables with exactly one entry in their
  189.    domain.  Since there is only one entry in that variable's domain, we
  190.    can either assume it was assigned as evidence to have only one variable
  191.    in its domain, or it only had one entry in its domain to begin with.
  192.    This blurs the distinction between evidence assignments and variables
  193.    with single value domains, but that is alright since we have to assign
  194.    variables that only have one value in their domain to that single value.
  195.  
  196.    Return a new factor where the sum of the all the probabilities in the table is 1.
  197.    This should be a new factor, not a modification of this factor in place.
  198.  
  199.    If the sum of probabilities in the input factor is 0,
  200.    you should return None.
  201.  
  202.    This is intended to be used at the end of a probabilistic inference query.
  203.    Because of this, all variables that have more than one element in their
  204.    domain are assumed to be unconditioned.
  205.    There are more general implementations of normalize, but we will only
  206.    implement this version.
  207.  
  208.    Useful functions:
  209.    Factor.getAllPossibleAssignmentDicts
  210.    Factor.getProbability
  211.    Factor.setProbability
  212.    Factor.unconditionedVariables
  213.    Factor.conditionedVariables
  214.    Factor.variableDomainsDict
  215.    """
  216.  
  217.     # typecheck portion
  218.     variableDomainsDict = factor.variableDomainsDict()
  219.     for conditionedVariable in factor.conditionedVariables():
  220.         if len(variableDomainsDict[conditionedVariable]) > 1:
  221.             print "Factor failed normalize typecheck: ", factor
  222.             raise ValueError, ("The factor to be normalized must have only one " + \
  223.                             "assignment of the \n" + "conditional variables, " + \
  224.                             "so that total probability will sum to 1\n" +
  225.                             str(factor))
  226.  
  227.     unconditionedVariables = factor.unconditionedVariables()
  228.     conditionedVariables = factor.conditionedVariables()
  229.     for variable in unconditionedVariables:
  230.         if len(variableDomainsDict[variable]) == 1:
  231.             unconditionedVariables.remove(variable)
  232.             conditionedVariables.append(variable)
  233.  
  234.     newFactor = Factor(unconditionedVariables, conditionedVariables, variableDomainsDict)
  235.  
  236.     possibleAssignmentDicts = factor.getAllPossibleAssignmentDicts()
  237.     normalizationFactor = sum(map(lambda x: factor.getProbability(x), possibleAssignmentDicts))
  238.     for assignmentDict in possibleAssignmentDicts:
  239.         newProbability = factor.getProbability(assignmentDict) / normalizationFactor
  240.         newFactor.setProbability(assignmentDict, newProbability)
  241.  
  242.     return newFactor
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement