Think about how to improve the following program, then do so. Show me the full code.

```import tkinter as tk
from tkinter import ttk, PhotoImage
import numpy as np
from scipy import special
import matplotlib.pyplot as plt
from math import log, exp

class CondorcetSimulation:
    def __init__(self, root):
        self.root = root
        self.root.title("Condorcet's Jury Theorem Simulator")
        self.root.resizable(False, False)  # Add this line

        # Default values
        self.n_voters = tk.StringVar(value="5")
        self.p = tk.StringVar(value="0.6")

        # Create frame for better organization
        self.main_frame = ttk.Frame(self.root, padding="10")
        self.main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # Create widgets
        self.create_widgets()

    def create_widgets(self):
        # Label and entry for number of voters
        ttk.Label(self.main_frame, text="Number of Voters (n):").grid(row=0, column=0, padx=5, pady=5, sticky=tk.W)
        self.voters_entry = ttk.Entry(self.main_frame, textvariable=self.n_voters, width=20)
        self.voters_entry.grid(row=0, column=1, padx=5, pady=5)

        # Label and entry for probability
        ttk.Label(self.main_frame, text="Probability (p):").grid(row=1, column=0, padx=5, pady=5, sticky=tk.W)
        self.p_entry = ttk.Entry(self.main_frame, textvariable=self.p, width=20)
        self.p_entry.grid(row=1, column=1, padx=5, pady=5)

        # Button to run simulation
        ttk.Button(self.main_frame, text="Run Simulation", 
                  command=self.run_simulation).grid(row=2, column=0, columnspan=2, pady=10)

        # Result display area
        self.result_frame = ttk.LabelFrame(self.main_frame, text="Results", padding="5")
        self.result_frame.grid(row=3, column=0, columnspan=2, sticky=(tk.W, tk.E), pady=5)
        
        # Result text with a white background for better visibility
        self.result_text = tk.Text(self.result_frame, height=2, width=37, wrap=tk.WORD)
        self.result_text.grid(row=0, column=0, padx=5, pady=5)
        self.result_text.configure(state='disabled')  # Make read-only by default

        # Configure grid weights
        self.main_frame.columnconfigure(1, weight=1)
        self.result_frame.columnconfigure(0, weight=1)

    def update_result_display(self, message, is_error=False):
        """Update the result display with the given message."""
        self.result_text.configure(state='normal')  # Temporarily enable editing
        self.result_text.delete(1.0, tk.END)  # Clear current content
        
        # Configure tag for error messages (red color)
        self.result_text.tag_configure('error', foreground='red')
        self.result_text.tag_configure('success', foreground='black')
        
        # Insert the message with appropriate tag
        self.result_text.insert(tk.END, message, 'error' if is_error else 'success')
        self.result_text.configure(state='disabled')  # Make read-only again

    def validate_inputs(self):
        """Validate user inputs before running simulation."""
        try:
            n = int(self.n_voters.get())
            if n < 2:
                self.update_result_display("Error: Number of voters must be at least 2.", is_error=True)
                return None, None
        except ValueError:
            self.update_result_display("Error: Please enter a valid integer for voters.", is_error=True)
            return None, None

        try:
            p = float(self.p.get())
            if not 0 <= p <= 1:
                self.update_result_display("Error: Probability must be between 0 and 1 (inclusive).", is_error=True)
                return None, None
        except ValueError:
            self.update_result_display("Error: Please enter a valid number for probability.", is_error=True)
            return None, None

        return n, p

    def run_simulation(self):
        """Run the Condorcet simulation with validated inputs."""
        n, p = self.validate_inputs()
        if n is None or p is None:
            return

        try:
            # Calculate probability that majority chooses correctly
            majority_success_prob = self.calculate_condorcet_optimized(n, p)
            
            # Format and display the results
            result_message = (f"Probability that majority is correct: {majority_success_prob:.4f}")
            self.update_result_display(result_message)
            
        except ValueError as e:
            self.update_result_display(f"Error in calculation: {str(e)}", is_error=True)

    def calculate_condorcet_optimized(self, n, p):
        """
        Calculate Condorcet probability using normal approximation for large n.
        Falls back to exact calculation for small n.
        """
        try:
            if p == 1:
                return 1.0
                
            if n < 1000:  # Use exact calculation for small n
                return self.calculate_condorcet_exact(n, p)
            else:  # Use normal approximation for large n
                mean = n * p
                std = max((n * p * (1-p)) ** 0.5, 1e-10)  # Avoid division by zero
                majority = n/2
                z = (majority - mean) / std
                return 1 - special.ndtr(z)
        except Exception as e:
            raise ValueError(f"Error in probability calculation: {str(e)}")

    def calculate_condorcet_exact(self, n, p):
        """
        Exact calculation for small n using log space to avoid overflow.
        """
        try:
            if p == 1:
                return 1.0
                
            if p < 0 or p > 1:  # Handle edge cases
                raise ValueError("Probability must be between 0 and 1 (inclusive)")
                
            majority = n // 2 + 1
            prob = 0
            for k in range(majority, n + 1):
                # Use safe log calculations
                log_prob = (special.gammaln(n + 1) - 
                          special.gammaln(k + 1) - 
                          special.gammaln(n - k + 1) +
                          k * np.log(p) + 
                          (n - k) * np.log(1 - p))
                if log_prob > -700:  # Prevent underflow
                    prob += np.exp(log_prob)
            return min(1.0, max(0.0, prob))  # Ensure result is between 0 and 1
        except Exception as e:
            raise ValueError(f"Error in exact calculation: {str(e)}")

# Create the main window and run the app
if __name__ == "__main__":
    root = tk.Tk()
    app = CondorcetSimulation(root)
    root.mainloop()```