Working with implicit functions in Mathematica returned from other functions - wolfram-mathematica

I have a equation
inv = (x + f) (y + g) == z;
But for some reason I cannot CountourPlot it, even though copy-pasting output, for example {(2 + x) (2 + y)} == {11} into CountourPlot works. I've tried both Hold and Defer to no luck.
What's happening and how I can fix this problem?
Actual code:
inv00 = (x + 1) (y + 1) == z
inv01 = inv00 /. {z -> 2}
ContourPlot[inv01, {x, 0, 1}, {y, 0, 1}]
ContourPlot[(1 + x) (1 + y) == 2, {x, 0, 1}, {y, 0, 1}]

Related

How to solve flow game using Google OR tools?

I tried to make solver for flow game using google-OR tools.
I made a few rules for the corner to only contains corner pipes, but other than that, i can not figure out how to make the pipe connected to each other nor how to tell the model to make a pipe that is connecting to each other.
A few snippet
pipe_types = {
0: " ",
1: "-",
2: "|",
3: "┗" ,
4: "┛" ,
5: "┓",
6: "┏",
7: "●"
}
model = cp_model.CpModel()
filled_map = [[0,0,0,0],
[0,0,7,0],
[0,0,0,0],
[0,7,0,0]]
mesh_size = int(np.sqrt(len(np.array(filled_map).flatten())))
target_map = [[model.NewIntVar(1, 6, 'column: %i' % i) for i in range(mesh_size)] for j in range(mesh_size)]
flow_map = init_map(model, target_map, filled_map)
for i in range(len(flow_map)):
for j in range(len(flow_map[0])):
# check if top or bottom side
if (i == 0) or (i == len(flow_map)-1):
model.Add(flow_map[i][j] != 2)
# check if left or right side
if (j == 0) or (j == len(flow_map[0])-1):
model.Add(flow_map[i][j] != 1)
# left up corner
if (i == 0) & (j == 0):
model.Add(flow_map[i][j] != 3)
model.Add(flow_map[i][j] != 4)
model.Add(flow_map[i][j] != 5)
# right up corner
if (i == 0) & (j == len(flow_map[0])-1):
model.Add(flow_map[i][j] != 3)
model.Add(flow_map[i][j] != 4)
model.Add(flow_map[i][j] != 6)
# left bottom corner
if (i == len(flow_map)-1) & (j == 0):
model.Add(flow_map[i][j] != 4)
model.Add(flow_map[i][j] != 5)
model.Add(flow_map[i][j] != 6)
# right bottom corner
if (i == len(flow_map)-1) & (j == len(flow_map[0])-1):
model.Add(flow_map[i][j] != 3)
model.Add(flow_map[i][j] != 5)
model.Add(flow_map[i][j] != 6)
# Solving
status = solver.Solve(model)
res = []
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
for i in range(len(flow_map)):
for j in range(len(flow_map[0])):
res.append(solver.Value(flow_map[i][j]))
print(solver.Value(flow_map[i][j]), end=" ")
print()
This would results horizontal pipes on the center of the mesh. Later on, i would have to figure out how to add color and such on this too.
Is there any pointer on how to make this on OR tools?
Edit 1:
Based on David Eisenstat's answer, I can find solution. Visualizing this solution based on JohanC's answer, I get this result.
Can I get the pathing made from google-OR tools?
Edit 2:
Using hamilton path from "Hamiltonian" path using Python
I could generate somewhat correct pathing.
But it feels so weird since OR tools already calculate the pathing, and I have to recalculate the path. The path generated from "Hamiltonian" path using Python doesn't show all possible combinations. If I can take the path from OR tools, I think that would be my best interest.
As I don't have experience with OR-tools, here is an approach with Z3.
The initial board is represented by numbers for the end points, one number for each color. The idea is a bit similar to how Sudoku is represented.
Each other cell on the board will get either a value for zero, or a number. This number should be equal to exactly two of its neighbors.
The initial endpoints should have exactly one neighbor with its color.
from z3 import Solver, Sum, Int, If, And, Or, sat
def plot_solution(S):
import matplotlib.pyplot as plt
ax = plt.gca()
colors = plt.cm.tab10.colors
for i in range(M):
for j in range(N):
if board[i][j] != 0:
ax.scatter(j, i, s=500, color=colors[board[i][j]])
if S[i][j] != 0:
for k in range(M):
for l in range(N):
if abs(k - i) + abs(l - j) == 1 and S[i][j] == S[k][l]:
ax.plot([j, l], [i, k], color=colors[S[i][j]], lw=15)
ax.set_ylim(M - 0.5, -0.5)
ax.set_xlim(-0.5, N - 0.5)
ax.set_aspect('equal')
ax.set_facecolor('black')
ax.set_yticks([i + 0.5 for i in range(M - 1)], minor=True)
ax.set_xticks([j + 0.5 for j in range(N - 1)], minor=True)
ax.grid(b=True, which='minor', color='white')
ax.set_xticks([])
ax.set_yticks([])
ax.tick_params(axis='both', which='both', length=0)
plt.show()
board = [[1, 0, 0, 2, 3],
[0, 0, 0, 4, 0],
[0, 0, 4, 0, 0],
[0, 2, 3, 0, 5],
[0, 1, 5, 0, 0]]
M = len(board)
N = len(board[0])
B = [[Int(f'B_{i}_{j}') for j in range(N)] for i in range(M)]
s = Solver()
s.add(([If(board[i][j] != 0, B[i][j] == board[i][j], And(B[i][j] >= 0, B[i][j] < 10))
for j in range(N) for i in range(M)]))
for i in range(M):
for j in range(N):
same_neighs_ij = Sum([If(B[i][j] == B[k][l], 1, 0)
for k in range(M) for l in range(N) if abs(k - i) + abs(l - j) == 1])
if board[i][j] != 0:
s.add(same_neighs_ij == 1)
else:
s.add(Or(same_neighs_ij == 2, B[i][j] == 0))
if s.check() == sat:
m = s.model()
S = [[m[B[i][j]].as_long() for j in range(N)] for i in range(M)]
print(S)
plot_solution(S)
Solution:
[[1, 2, 2, 2, 3],
[1, 2, 4, 4, 3],
[1, 2, 4, 3, 3],
[1, 2, 3, 3, 5],
[1, 1, 5, 5, 5]]
As mentioned in the comments, a possible requirement is that all cells would need to be colored. This would need a more complicated approach. Here is an example of such a configuration for which the above code could create a solution that connects all end points without touching all cells:
board = [[0, 1, 2, 0, 0, 0, 0],
[1, 3, 4, 0, 3, 5, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 2, 0, 4, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 5, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]]
The best way is probably with AddCircuit. This constraint takes a directed graph where each arc is labeled with a literal and requires that the arcs labeled true form a subgraph where each node has in- and out-degree 1, and further that there is at most one cycle that is not a self-loop. By forcing an arc from the end to the beginning, we can use this constraint type to require that there is a single path from the beginning to the end.
The documentation is somewhat poor, so here's a working code sample. I'll leave the drawing part to you.
import collections
from ortools.sat.python import cp_model
def validate_board_and_count_colors(board):
assert isinstance(board, list)
assert all(isinstance(row, list) for row in board)
assert len(set(map(len, board))) == 1
colors = collections.Counter(square for row in board for square in row)
del colors[0]
assert all(count == 2 for count in colors.values())
num_colors = len(colors)
assert set(colors.keys()) == set(range(1, num_colors + 1))
return num_colors
def main(board):
num_colors = validate_board_and_count_colors(board)
model = cp_model.CpModel()
solution = [
[square or model.NewIntVar(1, num_colors, "") for (j, square) in enumerate(row)]
for (i, row) in enumerate(board)
]
true = model.NewBoolVar("")
model.AddBoolOr([true])
for color in range(1, num_colors + 1):
endpoints = []
arcs = []
for i, row in enumerate(board):
for j, square in enumerate(row):
if square == color:
endpoints.append((i, j))
else:
arcs.append(((i, j), (i, j)))
if i < len(board) - 1:
arcs.append(((i, j), (i + 1, j)))
if j < len(row) - 1:
arcs.append(((i, j), (i, j + 1)))
(i1, j1), (i2, j2) = endpoints
k1 = i1 * len(row) + j1
k2 = i2 * len(row) + j2
arc_variables = [(k2, k1, true)]
for (i1, j1), (i2, j2) in arcs:
k1 = i1 * len(row) + j1
k2 = i2 * len(row) + j2
edge = model.NewBoolVar("")
if k1 == k2:
model.Add(solution[i1][j1] != color).OnlyEnforceIf(edge)
arc_variables.append((k1, k1, edge))
else:
model.Add(solution[i1][j1] == color).OnlyEnforceIf(edge)
model.Add(solution[i2][j2] == color).OnlyEnforceIf(edge)
forward = model.NewBoolVar("")
backward = model.NewBoolVar("")
model.AddBoolOr([edge, forward.Not()])
model.AddBoolOr([edge, backward.Not()])
model.AddBoolOr([edge.Not(), forward, backward])
model.AddBoolOr([forward.Not(), backward.Not()])
arc_variables.append((k1, k2, forward))
arc_variables.append((k2, k1, backward))
model.AddCircuit(arc_variables)
solver = cp_model.CpSolver()
status = solver.Solve(model)
if status == cp_model.OPTIMAL:
for row in solution:
print("".join(str(solver.Value(x)) for x in row))
if __name__ == "__main__":
main(
[
[1, 0, 0, 2, 3],
[0, 0, 0, 4, 0],
[0, 0, 4, 0, 0],
[0, 2, 3, 0, 5],
[0, 1, 5, 0, 0],
]
)

how can I change value of array in a loop in mathematica?

I wrote a code in matlab as below:
T= ((1-(-1)) * rand([4,4],'double') + (-1) * ones(4,4));
for i=1:4
for j=1:i
T(j,i)=TT(i,j);
end
T(i,i)=0;
end
Now, I want to write this code in mathematica as below:
T = RandomReal[{-1, 1}, {4, 4}];
For[i = 1, i < 5, i++,
For[ j = 1, j < i, j++,
T[[j, i]] = T[[i, j]]]
T[[i, i]] = 0];
But it doesn't work!
Could you tell me about my mistakes?
Thank you.
SeedRandom[1234];
t = u = RandomReal[{-1, 1}, {4, 4}];
t // MatrixForm
If must use For
For[i = 1, i < 5, i++,
For[j = 1, j < i, j++, t[[j, i]] = t[[i, j]]]; t[[i, i]] = 0];
It mutates t
t // MatrixForm
One way to do this functionally
(l = LowerTriangularize[u, -1]) + Transpose[l]

Using a case statement to assign multiple variable in ruby

I'm implementing an HSV to RGB function in ruby, and I was hoping for syntax like this:
def hsv_to_rgb(h, s, v)
if (h == 0) then return 0, 0, 0 end
c = v * s
hp = h / 60.0
x = c * (1 - (hp % 2 - 1).abs)
r, g, b = case hp
when 0..1
c, x, 0
when 1..2
x, c, 0
when 2..3
0, c, x
when 3..4
0, x, c
when 4..5
x, 0, c
else
c, 0, x
end
m = v - c
return r + m, g + m, b + m
end
however, when I attempt to run this in Jruby I get the following error message:
SyntaxError: julia2.rb:60: syntax error, unexpected '\n'
when 1..2
Does something like this syntax exist in ruby?
Thanks!
Your return values in the case statement are not accepted by the ruby engine. I think you want to return an array... using the [] perhaps?
Like this:
def hsv_to_rgb(h, s, v)
if (h == 0) then return 0, 0, 0 end
c = v * s
hp = h / 60.0
x = c * (1 - (hp % 2 - 1).abs)
r, g, b = case hp
when 0..1
[c, x, 0]
when 1..2
[x, c, 0]
when 2..3
[0, c, x]
when 3..4
[0, x, c]
when 4..5
[x, 0, c]
else
[c, 0, x]
end
m = v - c
return r + m, g + m, b + m
end
Returning array will work and it is more readable as well.

How to fix an Adam's method?

I've such errors:
Coordinate .. is not a floating-point number
and can't correctly fix it.
The program works correctly for a function 1 - t *y , but not for y*y*Exp[t] - 2*y.
I will be really happy if you tell me why and how to fix this problem.
ABM[a0_, b0_, \[Alpha]_, m0_] :=
Module[{a = a0, b = b0, F, j, k, m = m0, p},
h = (b - a)/m; T = Table[a, {m + 1}];
Y = Table[\[Alpha], {m + 1}];
For[j = 1, j <= 3, j++, Subscript[k, 1] = h*f[T[[j]], Y[[j]]];
Subscript[k, 2] = h*f[T[[j]] + h/2, Y[[j]] + Subscript[k, 1]/2];
Subscript[k, 3] = h*f[T[[j]] + h/2, Y[[j]] + Subscript[k, 2]/2];
Subscript[k, 4] = h*f[T[[j]] + h, Y[[j]] + Subscript[k, 3]];
Y[[j + 1]] = Y[[j]] + (1/6)*(Subscript[k, 1] + 2*Subscript[k, 2] +
2*Subscript[k, 3] + Subscript[k, 4]);
T[[j + 1]] = a + h*j; ];
Subscript[F, 0] = f[T[[1]], Y[[1]]]; Subscript[F, 1] =
f[T[[2]], Y[[2]]]; Subscript[F, 2] = f[T[[3]], Y[[3]]];
Subscript[F, 3] = f[T[[4]], Y[[4]]]; For[j = 4, j <= m, j++,
p = Y[[j]] + (h/24)*(-9*Subscript[F, 0] + 37*Subscript[F, 1] -
59*Subscript[F, 2] + 55*Subscript[F, 3]);
T[[j + 1]] = a + h*j;
p = Y[[j]] + (h/24)*(Subscript[F, 1] -
5*Subscript[F, 2] + 19*Subscript[F, 3] +
9*f[T[[j + 1]], p]);
Y[[j + 1]] = p; Subscript[F, 0] = Subscript[F, 1];
Subscript[F, 1] = Subscript[F, 2]; Subscript[F, 2] =
Subscript[F, 3];
Subscript[F, 3] = f[T[[j + 1]], Y[[j + 1]]]; ];
Return[Transpose[{T, Y}]]];
f[t_, y_] = y*y*Exp[t] - 2*y;
Print["Find numerical solutions to the D.E."];
Print["y' = ", f[t, y]];
n = 25;
pts1 = ABM[0, 8, 2., n];
Y1 = Y;
Needs["Graphics`Colors`"];
graph1 = ListPlot[pts1, PlotJoined -> True, PlotStyle -> Green,
PlotRange -> {{0, 10}, {0, 10}}];
Print["The Adams-Bashforth-Moulton solution for y' = ", f[t, y]];
Print["Using n = ", n + 1, " points."];
Print[pts1];
Print[""];
Print["The final value is y(5) = ", Subscript[y, n + 1], " = ",
Y[[n + 1]]];

How to draw three-dimensional image: Plot3D NDSolve

m = 10; c = 2; k = 5; F = 12;
NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t],
x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}]
{f, 0, 5} ( 0=< f <= 5 )
How to draw three-dimensional image:
x = u(t,f)
............
If f = 0.1,0.2,... 5,
We can solve the equation:
NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t],
x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}]
x is a function of t and f
...............
m = 10; c = 2; k = 5; F = 12;
f = 0.1
s = NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t],
x[0] == 0, x'[0] == 0}, x[t], {t, 0, 30}]
Plot[Evaluate[x[t] /. s], {t, 0, 30}, PlotRange -> All]
f = 0.1
f = 0.2
f = 0.3
f = 5
How to draw three-dimensional image:
x = u(t,f)
Here goes a solution.
m = 10; c = 2; k = 5; F = 12;
NumberOfDiscrit$f = 20;(* Number of points you want to divide 0<=f<=5*)
NumberOfDiscrit$t = 100;(* Number of points you want to divide 0<=t<=30 *)
fValues = Range[0., 5., 5./(NumberOfDiscrit$f - 1)];
tValues = Range[0., 30., 30./(NumberOfDiscrit$t - 1)];
res = Map[(x /.
First#First#
NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*#*t])*x[t] ==
F*Sin[2*Pi*#*t], x[0] == 0, x'[0] == 0}, x, {t, 0, 30}]) &,
fValues];
AllDat = Map[(##tValues) &, res];
InterpolationDat =
Flatten[Table[
Transpose#{tValues,
Table[fValues[[j]], {i, 1, NumberOfDiscrit$t}],
AllDat[[j]]}, {j, 1, NumberOfDiscrit$f}], 1];
Final3DFunction = Interpolation[InterpolationDat];
Plot3D[Final3DFunction[t, f], {t, 0, 30}, {f, 0, 5}, PlotRange -> All,
PlotPoints -> 60, MaxRecursion -> 3, Mesh -> None]
You can use Manipulate to dynamically change some of the parameters. By the way the above 3D picture may be misleading if one takes f as a continuous variable in u(t,f). You should note that the numerical solution seems to blow up for asymptotic values of t>>30. See the picture below.
Hope this helps you out.
You could also do something like this
Clear[f]
m = 10; c = 2; k = 5; F = 12;
s = NDSolve[{m*Derivative[2, 0][x][t, f] +
c*Derivative[1, 0][x][t, f] + (k*Sin[2*Pi*f*t])*x[t, f] == F*Sin[2*Pi*f*t],
x[0, f] == 0,
Derivative[1, 0][x][0, f] == 0}, x, {t, 0, 30}, {f, 0, .2}]
Plot3D[Evaluate[x[t, f] /. s[[1]]], {t, 0, 30}, {f, 0, .2}, PlotRange -> All]
This should do it.
m = 10; c = 2; k = 5; F = 12;
fun[f_?NumericQ] :=
Module[
{x, t},
First[x /.
NDSolve[
{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] == F*Sin[2*Pi*f*t],
x[0] == 0, x'[0] == 0},
x, {t, 0, 30}
]
]
]
ContourPlot[fun[f][t], {f, 0, 5}, {t, 0, 30}]
Important points:
The pattern _?NumericQ prevents fun from being evaluated for symbolc arguments (think fun[a]), and causing NDSolve::nlnum errors.
Since NDSolve doesn't appear to localize its function variable (t), we needed to do this manually using Module to prevent conflict between the t used in NDSolve and the one used in ContourPlot. (You could use a differently named variable in ContourPlot, but I think it was important to point out this caveat.)
For a significant speedup in plotting, you can use memoization, as pointed out by Mr. Wizard.
Clear[funMemo] (* very important!! *)
funMemo[f_?NumericQ] :=
funMemo[f] = Module[{x, t},
First[x /.
NDSolve[{m*x''[t] + c*x'[t] + (k*Sin[2*Pi*f*t])*x[t] ==
F*Sin[2*Pi*f*t], x[0] == 0, x'[0] == 0}, x, {t, 0, 30}]]]
ContourPlot[funMemo[f][t], {f, 0, 5}, {t, 0, 30}] (* much faster than with fun *)
If you're feeling adventurous, and willing to explore Mathematica a bit more deeply, you can further improve this by limiting the amount of memory the cached definitions are allowed to use, as I described here.
Let's define a helper function for enabling memoization:
SetAttributes[memo, HoldAll]
SetAttributes[memoStore, HoldFirst]
SetAttributes[memoVals, HoldFirst]
memoVals[_] = {};
memoStore[f_, x_] :=
With[{vals = memoVals[f]},
If[Length[vals] > 100, f /: memoStore[f, First[vals]] =.;
memoVals[f] ^= Append[Rest[memoVals[f]], x],
memoVals[f] ^= Append[memoVals[f], x]];
f /: memoStore[f, x] = f[x]]
memo[f_Symbol][x_?NumericQ] := memoStore[f, x]
Then using the original, non-memoized fun function, plot as
ContourPlot[memo[fun][f][t], {f, 0, 5}, {t, 0, 30}]

Resources