¿Cómo puedo trazar una lista devuelta por la solución de Mathematica en ecuaciones enteras acotadas?
-
14-11-2019 - |
Pregunta
Entonces tengo un conjunto de ecuaciones diofánticas acotadas que especifican líneas en el plano.Quiero hacer que Mathematica trace la intersección de dos de estas ecuaciones para poder ver cómo se ven.
Hasta ahora tengo algo como:
Resolver[0 < x - y < 3 && -1 < 2 x - y < 2, {x, y}, Enteros]
que devuelve alguna estructura como:
{{x -> -2, y -> -4}, {x -> -1, y -> -3}, {x -> -1, y -> -2}, {x -> 0, y -> -1}}
pero ¿cómo puedo hacer que Mathematica trace esto para poder ver la forma resultante?Preferiblemente, me gustaría que la trama considere que cada "punto" es un cuadrado de 1x1.
Además, me pregunto si existe una mejor manera de hacer esas cosas.Gracias.
Solución
Defina los datos que desea trazar transformando la lista Solve[]
devoluciones.Esto se puede hacer como
data = {x, y} /. Solve[0 < x - y < 3 && -1 < 2 x - y < 2, {x, y}, Integers]
De manera más general, puedes hacer Solve
Devuelva la solución en formato de lista (en lugar de como un conjunto de reglas) usando el siguiente truco:
data = Solve[0 < x - y < 3 && -1 < 2 x - y < 2, {x, y}, Integers] /. Rule[a_,b_]->b
Para trazar, entre muchas alternativas, puede utilizar ListPlot
como
ListPlot[data, PlotMarkers -> {Style["\[FilledSquare]", FontSize -> 16]}]
para obtener el siguiente resultado
Puedes refinarlo aún más usando muchos estilos y otras opciones de ListPlot
.Por ejemplo, puedes unir los puntos.
ListPlot[data, PlotMarkers -> {Style["\[FilledSquare]", FontSize -> 16]},
Joined -> True]
Llegar
EDITAR:Para jugar con la colocación y el tamaño del marcador existen varias alternativas.Usando ListPlot
podrás conseguir lo que necesitas de cualquiera de las dos formas:
(* Alternative 1: use fontsize to change the marker size *)
lp1 := ListPlot[{#} & /@ #1,
PlotMarkers -> {Style["\[FilledSquare]", FontSize -> Scaled[#2]]},
AspectRatio -> 1, AxesOrigin -> {0, 0},
PlotRange -> {{-5, 1}, {-5, 1}},
PlotStyle -> Hue /@ RandomReal[1, {Length@#1}],
Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick,
Line@#1}, Frame -> True, FrameTicks -> All] &;
(* usage example *)
lp1 @@ {data, .30}
(* Alternative 2: use the second parameter of PlotMarkers to control scaled size *)
lp2 := ListPlot[{#} & /@ #1,
PlotMarkers -> {Graphics@{Rectangle[]}, #2}, AspectRatio -> 1,
AxesOrigin -> {0, 0}, PlotRange -> {{-5, 1}, {-5, 1}},
PlotStyle -> Hue /@ RandomReal[1, {Length@#1}],
Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick,
Line@#1}, Frame -> True, FrameTicks -> All] &
(* usage example *)
lp2 @@ {data, 1/5.75}
En ambos casos es necesario utilizar Epilog
, de lo contrario, las líneas que unen los puntos quedarán ocluidas por los marcadores.Ambas alternativas producen el siguiente resultado:
Alternativamente, puedes usar Graphics
, RegionPlot
, ContourPlot
, BubbleChart
con transformaciones apropiadas de data
para obtener resultados similares al de ListPlot
salida arriba.
Usando primitivas de gráficos:
(* data transformation to define the regions *)
trdataG[data_, size_] := data /. {a_, b_} :>
{{a - size/2, b - size/2}, {a + size/2, b + size/2}};
(* plotting function *)
gr := Graphics[
{
{Hue[RandomReal[]], Rectangle[##]} & @@@ trdataG @@ {#1, #2},
GrayLevel[.3], PointSize[.02], Thick, Point@#1, Line@#1},
PlotRange -> {{-5, 1}, {-5, 1}
},
PlotRangePadding -> 0, Axes -> True, AxesOrigin -> {0, 0},
Frame -> True, FrameTicks -> All] &
(* usage example *)
gr @@ {data, .99}
Usando BubbleChart:
(* Transformation of data to a form that BubbleChart expects *)
dataBC[data_] := data /. {a_, b_} :> {a, b, 1};
(* custom markers *)
myMarker[size_][{{xmin_, xmax_}, {ymin_, ymax_}}, ___] :=
{EdgeForm[], Rectangle[{(1/2) (xmin + xmax) - size/2, (1/2) (ymin + ymax) -
size/2}, {(1/2) (xmin + xmax) + size/2, (1/2) (ymin + ymax) + size/2}]};
(* charting function *)
bc := BubbleChart[dataBC[#1], ChartElementFunction -> myMarker[#2],
ChartStyle -> Hue /@ RandomReal[1, {Length@#1}], Axes -> True,
AxesOrigin -> {0, 0}, PlotRange -> {{-5, 1}, {-5, 1}},
PlotRangePadding -> 0, AspectRatio -> 1, FrameTicks -> All,
Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick, Line@#1}] &
(* usage example *)
bc @@ {data, .99}
Usando RegionPlot:
(* Transformation of data to a form that RegionPlot expects *)
trdataRP[data_, size_] := data /. {a_, b_} :>
a - size/2 <= x <= a + size/2 && b - size/2 <= y <= b + size/2
(* charting function *)
rp := RegionPlot[Evaluate@trdataRP[#1, #2], {x, -5, 1}, {y, -5, 1},
AspectRatio -> 1, Axes -> True, AxesOrigin -> {0, 0},
PlotRange -> {{-5, 1}, {-5, 1}},
PlotStyle -> Hue /@ RandomReal[1, {Length@#1}], FrameTicks -> All,
PlotPoints -> 100, BoundaryStyle -> None,
Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick, Line@#1}] &
(* usage example *)
rp @@ {data, .99}
Usando ContourPlot:
(* Transformation of data to a form that ContourPlot expects *)
trdataRP[data_, size_] := data /. {a_, b_} :>
a - size/2 <= x <= a + size/2 && b - size/2 <= y <= b + size/2;
trdataCP[data_, size_] := Which @@ Flatten@
Thread[{trdataRP[data, size], Range@Length@data}];
(* charting function *)
cp := ContourPlot[trdataCP[#1, #2], {x, -5, 1}, {y, -5, 1},
AspectRatio -> 1, Axes -> True, AxesOrigin -> {0, 0},
PlotRange -> {{-5, 1}, {-5, 1}}, FrameTicks -> All,
ExclusionsStyle -> None, PlotPoints -> 100,
ColorFunction -> Hue,
Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick, Line@#1}] &
(* usage example *)
cp @@ {data, .99}
Otros consejos
puede ser
sol = Solve[0 < x - y < 3 && -1 < 2 x - y < 2, {x, y}, Integers];
pts = Cases[sol, {_ -> n_, _ -> m_} :> {n, m}];
ListPlot[pts, Mesh -> All, Joined -> True, AxesOrigin -> {0, 0},
PlotMarkers -> {Automatic, 10}]
también puede extraer los puntos para trazar usando
{#[[1, 2]], #[[2, 2]]} & /@ sol