To solve this problem, we first need to define the decision variables and the objective function. Let's denote the amount invested in company A as `x_A` and the amount invested in company B as `x_B`. The objective is to maximize earnings, which can be calculated as the sum of returns from both investments.

Given:
- Total budget: $500,000
- Minimum investment ratio of A to B: 2:1 (i.e., `x_A >= 2*x_B`)
- Maximum investment in company B: $200,000 (i.e., `x_B <= 200,000`)
- Return on investment for company A: 9%
- Return on investment for company B: 12%

The objective function to maximize earnings can be written as:
`0.09*x_A + 0.12*x_B`

Subject to the constraints:
1. Budget constraint: `x_A + x_B <= 500,000`
2. Investment ratio constraint: `x_A >= 2*x_B`
3. Maximum investment in B constraint: `x_B <= 200,000`
4. Non-negativity constraints: `x_A >= 0`, `x_B >= 0` (since investments cannot be negative)

Now, let's translate this problem into Gurobi code:

```python
from gurobipy import *

# Create a new model
m = Model("Investment_Optimization")

# Define the decision variables
x_A = m.addVar(lb=0, name="Investment_in_A")
x_B = m.addVar(lb=0, name="Investment_in_B")

# Set the objective function
m.setObjective(0.09*x_A + 0.12*x_B, GRB.MAXIMIZE)

# Add constraints
m.addConstr(x_A + x_B <= 500000, name="Budget_Constraint")
m.addConstr(x_A >= 2*x_B, name="Investment_Ratio_Constraint")
m.addConstr(x_B <= 200000, name="Max_Investment_in_B_Constraint")

# Optimize the model
m.optimize()

# Print the results
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f" Invest in Company A: ${x_A.x:.2f}")
    print(f" Invest in Company B: ${x_B.x:.2f}")
    print(f" Maximum Earnings: ${m.objVal:.2f}")
else:
    print("No optimal solution found")

```