def create_model():
    all_vars = []

    # b = 0.02
    # target_mean = 1/0.1**2
    # a = b*target_mean

    b = 0.001
    target_mean = 10/0.1**2
    a = b*target_mean

    # print a/b
    # print np.sqrt(a/(b**2))

    # tau_qd = Normal('tau_qd', 0.05,1/(0.15**2))
    # tau_qd = Exponential('tau_qd', 10)
    tau_qd = Gamma('tau_qd', a, b)
    plot_dist(tau_qd, transform=lambda x: 1/np.sqrt(x))
    print np.mean([1/np.sqrt(tau_qd.random()) for i in xrange(1000)])
    print np.std([1/np.sqrt(tau_qd.random()) for i in xrange(1000)])
    # pot = TruncPotential('tau_qd_potential', 0, 0.2, tau_qd)
    # all_vars.append(pot)
    # tau_qd.value = 1/0.05**2
    all_vars.append(tau_qd)

    # plot_dist(tau_qd, 0, 0.2)

    mu_sc = Normal('mu_sc', 0.5, 1/(0.25**2))
    mu_sc.value=0.5
    pot = TruncPotential('mu_sc_potential', 0, 1, mu_sc)
    all_vars.append(pot)

    # tau_sc = Normal('tau_sc', 0.2, 1/(0.25**2))
    # tau_sc = Exponential('tau_sc', 10)

    tau_sc = Gamma('tau_sc', a, b)
    # plot_dist(tau_sc)
    # tau_sc.value = 1/0.1**2
    # pot = TruncPotential('tau_sc_potential', 0, 0.3, tau_sc)
    # all_vars.append(pot)

    # tau_bias = Normal('tau_bias', 0.05, 1/(0.25**2))
    # tau_bias = Exponential('tau_bias', 10)
    tau_bias = Gamma('tau_bias', a, b)
    # pot = TruncPotential('tau_bias_potential', 0, 0.2, tau_bias)
    # all_vars.append(pot)
    # tau_bias.value = 1/0.01**2

    # tau_student_handin_capabilities = Normal('tau_student_handin_capabilities', 0.05, 1/(0.15**2))
    # tau_student_handin_capabilities = Exponential('tau_student_handin_capabilities', 10)
    tau_student_handin_capabilities = Gamma('tau_student_handin_capabilities', a, b)
    # tau_student_handin_capabilities.value = 1/0.05**2
    # pot = TruncPotential('tau_student_handin_capabilities_potential', 0, 0.3, tau_student_handin_capabilities)
    # all_vars.append(pot)


    # tau_student_question_capabilities = Normal('tau_student_question_capabilities', 0.05,1/(0.15**2))
    # tau_student_question_capabilities = Exponential('tau_student_question_capabilities', 10)
    tau_student_question_capabilities = Gamma('tau_student_question_capabilities', a, b)
    # plot_dist(tau_student_question_capabilities)
    # tau_student_question_capabilities.value = 1/0.05**2
    # pot = TruncPotential('tau_student_question_capabilities_potential', 0, 0.15, tau_student_question_capabilities)
    # all_vars.append(pot)

    # plot_dist(tau_student_question_capabilities, 0, 0.2)


    all_vars.append(mu_sc)
    all_vars.append(tau_sc)
    all_vars.append(tau_bias)
    all_vars.append(tau_student_handin_capabilities)
    all_vars.append(tau_student_question_capabilities)

    for i in xrange(num_assignments):
        questions = []
        for j in xrange(num_questions_pr_handin):
            # tau = pymc.Lambda('tau_%i_%i'% (i,j), lambda a=tau_qd: 1/ (tau_qd.value*tau_qd.value))
            tau = tau_qd
            difficulty = Normal('difficulty_q_%i_%i'% (i,j), 0, tau)
            q = Question(difficulty)
            questions.append(q)
            all_vars.append(difficulty)
        assignment = Assignment(questions)
        assignments.append(assignment)




    for i in xrange(num_students):
        # tau = pymc.Lambda('tau1_%i'%i, lambda a=tau_sc: 1/(tau_sc.value*tau_sc.value))
        tau = tau_sc
        student_capabilities = Normal('student_capabilities_s_%i'%i, mu_sc, tau)
        # pot = TruncPotential('student_capabilities_potential_s_%i'%i, 0, 1, student_capabilities)
        all_vars.append(student_capabilities)
        # all_vars.append(pot)

        # grading_bias = Normal('grading_bias_s_%i'%i, 0, 1/tau_bias)
        # tau = pymc.Lambda('tau2_%i'%i, lambda a=tau_bias: 1/ (tau_bias.value*tau_bias.value))
        tau = tau_bias
        grading_bias = Normal('grading_bias_s_%i'%i, 0, tau)
        all_vars.append(grading_bias)

        s = Student(student_capabilities, grading_bias)
        students.append(s)
        for j, assignment in enumerate(assignments):
            # student_handin_capabilities = Normal('student_handin_capabilities_sh_%i_%i' % (i,j), 0, 1/tau_student_handin_capabilities)
            tau = tau_student_handin_capabilities
            student_handin_capabilities = Normal('student_handin_capabilities_sh_%i_%i' % (i,j), 0, tau)
            all_vars.append(student_handin_capabilities)
            question_capabilities = []
            for k, q in enumerate(assignment.questions):
                tau = tau_student_question_capabilities
                student_question_capabilities = Normal('student_question_capabilities_shq_%i_%i_%i' % (i,j,k ), 0, tau)
                all_vars.append(student_question_capabilities)
                question_capabilities.append(student_question_capabilities)
            handins.append(Handin(s, assignment, student_handin_capabilities, question_capabilities))


    # assign grader
    all_grades = []
    for handin in handins:
        potential_graders = range(0, len(students))
        potential_graders.remove(students.index(handin.student))
        idx = np.random.randint(0, len(potential_graders), num_graders_pr_handin)
        graders = [students[i] for i in idx]
        grades = handin.grade(graders)
        all_grades.append(grades)

    grade_list = sum(sum(all_grades, []),[])


    b = 1.0
    target_mean = 1/np.sqrt(0.01)
    a = b*target_mean
    tau_exo_grade = Gamma('tau_exo_grade', a, b)
    # plt.hist([1/tau_exo_grade.random()**2 for i in xrange(50000)])
    # tau_exo_grade = Exponential('mu_exo_grade', 20)
    # tau_exo_grade = Normal('mu_exo_grade', 0.05, 1/(0.1**2))
    # pot = TruncPotential('tau_exo_grade', 0, 0.2, tau_exo_grade)
    # all_vars.append(pot)
    tau = tau_exo_grade
    all_vars.append(tau_exo_grade)

    print "Creating grade list"

    # grade_list_real = [g.value for g in grade_list]
    # print 1
    # grade_list_real = [min(max((g), 0), 1) for g in grade_list_real]
    # print 2
    # grade_list = [Normal('grade_%i'%i, g, tau, value=g_real, observed=True)  for i, (g_real, g) in enumerate(zip(grade_list_real, grade_list))]
    # print 3
    # grade_list_potentials = [TruncPotential('grade_potential_%i'%i, 0, 1, g) for i,g in enumerate(grade_list)]
    # print 4

    # take one MCMC step in order to make it more probable that all variables are in the allowed range
    # var_dict = {str(v):v for v in all_vars}
    # sampler = pymc.MCMC(var_dict)
    # sampler.sample(iter=1)

    grade_list_real = [g.value for g in grade_list]
    # plt.hist(grade_list_real)
    # plt.show()

    print "Number of illegal grades: %i (out of %i)" % (len([g for g in grade_list_real if g > 1 or g < 0]), len(grade_list))
    grade_list_real = [min(max((g), 0), 1) for g in grade_list_real]
    # grade_list = Normal('grade_%i'%i, np.array(grade_list), np.array([tau]*len(grade_list)), value=grade_list_real, observed=True)
    # grade_list = [Normal('grade_%i'%i, g, tau, value=g_real, observed=True)  for i, (g_real, g) in enumerate(zip(grade_list_real, grade_list))]
    grade_list_new = []
    for i, (g_real, g) in enumerate(zip(grade_list_real, grade_list)):
        grade_list_new.append(Normal('grade_%i'%i, g, tau, value=g_real, observed=True))
        if i % 100 == 0:
            print i
    # grade_list_potentials = [TruncPotential('grade_potential_%i'%i, 0, 1, g) for i,g in enumerate(grade_list)]
    grade_list = grade_list_new
    print "Grade list created"

    all_vars += grade_list
    # all_vars += grade_list_potentials

    all_vars = list(set(all_vars))
    print len(all_vars)
    # print [str(v) for v in all_vars]
    return locals(), grade_list_real, all_vars
def create_model():
    all_vars = []


    mu_sc = Normal('mu_sc', 0.5, 1/(0.25**2))
    mu_sc.value=0.5
    # pot = TruncPotential('mu_sc_potential', 0, 1, mu_sc)
    # all_vars.append(pot)

    # target = 0.1**2
    # a = 2
    # b = target*(a+1)

    target = 0.02**2
    a = 0.7
    b = target*(a+1)
    tau_qd = InverseGamma('tau_qd', a, b)
    tau_sc = InverseGamma('tau_sc', a, b)
    tau_bias = InverseGamma('tau_bias', a, b)


    # plot_dist(tau_qd, transform=lambda x: np.sqrt(x), high=0.5)

    print np.mean([np.sqrt(tau_qd.random()) for i in xrange(10000)])
    print np.std([np.sqrt(tau_qd.random()) for i in xrange(10000)])

    target = 0.02**2
    a = 0.9
    b = target*(a+1)
    tau_student_question_capabilities = InverseGamma('tau_student_question_capabilities', a, b)
    tau_student_handin_capabilities = InverseGamma('tau_student_handin_capabilities', a, b)
    # plot_dist(tau_student_handin_capabilities, transform=lambda x: np.sqrt(x), high=0.5)

    all_vars.append(mu_sc)
    all_vars.append(tau_sc)
    all_vars.append(tau_bias)
    all_vars.append(tau_student_handin_capabilities)
    all_vars.append(tau_student_question_capabilities)
    all_vars.append(tau_qd)

    for i in xrange(num_assignments):
        questions = []
        for j in xrange(num_questions_pr_handin):
            # tau = pymc.Lambda('tau_%i_%i'% (i,j), lambda a=tau_qd: 1/ (tau_qd.value*tau_qd.value))
            tau = tau_qd
            difficulty = Normal('difficulty_q_%i_%i'% (i,j), 0, 1/tau)
            q = Question(difficulty)
            questions.append(q)
            all_vars.append(difficulty)
        assignment = Assignment(questions)
        assignments.append(assignment)




    for i in xrange(num_students):
        tau = tau_sc
        student_capabilities = Normal('student_capabilities_s_%i'%i, mu_sc, 1/tau)
        all_vars.append(student_capabilities)

        tau = tau_bias
        grading_bias = Normal('grading_bias_s_%i'%i, 0, 1/tau)
        all_vars.append(grading_bias)

        s = Student(student_capabilities, grading_bias)
        students.append(s)
        for j, assignment in enumerate(assignments):
            tau = tau_student_handin_capabilities
            student_handin_capabilities = Normal('student_handin_capabilities_sh_%i_%i' % (i,j), 0, 1/tau)
            all_vars.append(student_handin_capabilities)
            question_capabilities = []
            for k, q in enumerate(assignment.questions):
                tau = tau_student_question_capabilities
                student_question_capabilities = Normal('student_question_capabilities_shq_%i_%i_%i' % (i,j,k ), 0, 1/tau)
                all_vars.append(student_question_capabilities)
                question_capabilities.append(student_question_capabilities)
            handins.append(Handin(s, assignment, student_handin_capabilities, question_capabilities))


    # assign grader
    all_grades = []
    num_grades_given = np.zeros((len(students),1))
    for handin in handins:
        potential_graders = range(0, len(students))
        potential_graders.remove(students.index(handin.student))
        idx = np.random.randint(0, len(potential_graders)+1, num_graders_pr_handin)
        num_grades_given[idx] += 1
        graders = [students[i] for i in idx]
        grades = handin.grade(graders)
        all_grades.append(grades)

    # print num_grades_given



    grade_list = sum(sum(all_grades, []),[])

    tau = 1/0.02**2

    print "Creating grade list"

    grade_list_real = [g.value for g in grade_list]

    print "Number of illegal grades: %i (out of %i)" % (len([g for g in grade_list_real if g > 1 or g < 0]), len(grade_list))
    grade_list_real = [min(max((g), 0), 1) for g in grade_list_real]

    grade_list_new = []
    for i, (g_real, g) in enumerate(zip(grade_list_real, grade_list)):
        grade_list_new.append(Normal('grade_%i'%i, g, tau, value=g_real, observed=True))
        if i % 10000 == 0:
            print i
    grade_list = grade_list_new
    print "Grade list created"

    all_vars += grade_list

    all_vars = list(set(all_vars))
    print len(all_vars)
    return locals(), grade_list_real, all_vars