code: def pl_true(exp, model={}):
      
      op, args = exp.op, exp.args
      if exp == TRUE:
          return True
      elif exp == FALSE:
          return False
      elif is_prop_symbol(op):
          return model.get(exp)
      elif op == '~':
          p = pl_true(args[0], model)
          if p is None: return None
          else: return not p
      elif op == '|':
          result = False
          for arg in args:
              p = pl_true(arg, model)
              if p is True: return True
              if p is None: result = None
          return result
      elif op == '&':
          result = True
          for arg in args:
              p = pl_true(arg, model)
              if p is False: return False
              if p is None: result = None
          return result
      p, q = args
      if op == '>>':
          return pl_true(~p | q, model)
      elif op == '<<':
          return pl_true(p | ~q, model)
      pt = pl_true(p, model)
      if pt is None: return None
      qt = pl_true(q, model)
      if qt is None: return None
      if op == '<=>':
          return pt == qt
      elif op == '^':
          return pt != qt
      else:
          raise ValueError, "illegal operator in logic expression" + str(exp)
docs: Return True if the propositional logic expression is true in the model,
      and False if it is false. If the model does not specify the value for
      every proposition, this may return None to indicate 'not obvious';
      this may happen even when the expression is tautological.