Porting challenge for MTK/Symbolics

The following SymPy code was given to me by someone who wanted to see if Symbolics/SymbolicUtils/MTK can handle these sorts of situations.

using SymPy
w_1, w_2 = symbols("w_1, w_2",real=true,positive=true)
pi = symbols("pi")
left = pi*(w_1/2)+(1-pi)w_1
right = pi*w_2+(1-pi)*w_2/2

prob_simp = solve(left-right,pi)[1]
prob = max(min(solve(left-right,pi)[1],1),0)
print(prob)

y_1,y_2 = symbols("y_1,y_2")
profit = (1-(1-prob)^2)*(y_1-w_1)
print(profit)


profit_simp = (1-(1-prob_simp)^2)*(y_1-w_1)
dprofit = diff(profit_simp, w_1)
print(dprofit)
BR = solve(dprofit,w_1)[1]
print(BR)

symmetric_sol = solve(w_2-BR(y_1 => 1))
print(symmetric_sol)

Can this be ported directly, and if not what are the missing features/overloads/etc.? By directly I mean that it is the symbolics output that the person cares about. The biggest thing I wasn’t sure about was how to handle the simple 1-D solve.

1 Like

The solve we have right now can only do linear equations.

So you can pass in Symbolics.solve_for([left-right ~ 0], [pi]) to try it out.

1 Like

The arrays have to match - so it’d be solve_for(left-right ~ 0, pi) or solve_for([left-right ~ 0], [pi]), which give

julia> Symbolics.solve_for(left-right ~ 0, pi)                                                 
(pi*(0.5w1 + 0.5w2) + w1*(1 - pi) + 0.5pi*w1 - (pi*w2) - (0.5w2*(1 - pi)))*((0.5w1 + 0.5w2)^-1)

Thanks, edited my answer. Well that seems to be a bug :frowning:

Thanks guys. I see snippets but do you have the full code you wrote to get to that last stage? If you can throw in a |> simplify or whatever at the end of the solve_for for good measure. I was hoping to be able to forward this whole post to people as an example of how you can do simple stuff with symbolics (since it is largely focused on the more complicated numerical-symbolic interaction at this point).

1 Like

I was just playing around, sorry :sweat_smile: I basically just did @variables w1 w2 pi and then entered the equations. I didn’t even restrict them to be positive, since I don’t know how.

Here are both approaches written in similar styles:

using SymPy
@syms pi w[1:2]::(real, positive)
left = sum((pi/2, pi) .* w)
right =  sum((pi, (1-pi)/2) .* w)

prob_simp = solve(left-right,pi)[1]
prob = max(min(prob_simp,1),0)
print(prob)

@syms y[1:2]
profit = (1-(1-prob)^2)*(y[1]-w[1]) # (1 - (1 - Max(0, Min(1, -w₂/(w₁ - 3*w₂))))^2)*(-w₁ + y₁)

using Symbolics
@variables pi w[1:2]
left = sum((pi/2, pi) .* w)
right =  sum((pi, (1-pi)/2) .* w)

prob_simp = Symbolics.solve_for(left - right ~ 0, pi)
prob = max(min(prob_simp,1),0)
print(prob)

@variables y[1:2]
profit = (1-(1-prob)^2)*(y[1]-w[1]) 
2 Likes

Oh it works if you call Symbolics.expand on the result… @YingboMa take note

using Symbolics

julia> @variables w1,w2,pi
3-element Vector{Num}:
 w1
 w2
 pi

julia> left = pi*(w1/2)+(1-pi)*w1
w1*(1 - pi) + 0.5pi*w1

julia> right=pi*w2+(1-pi)*w2/2
pi*w2 + 0.5w2*(1 - pi)

julia> Symbolics.expand(Symbolics.solve_for([right-left ~ 0], [pi])[1])
0.5w2*((-0.5w1 - (0.5w2))^-1) - (w1*((-0.5w1 - (0.5w2))^-1))
1 Like

Thanks. What about the diff and then solve thing? How to do that with symbolics/mtk and have it simplify correctly?