Search code examples
wolfram-mathematicaintegerplotdiophantine

How can I plot a list returned by the mathematica solution to in bounded integer equations


So I have a set of bounded diophantine equations that specify lines on the plane. I want to make mathematica plot the intersection of two of these equations so I can see what they look like.

So far I have something like:

Solve[0 < x - y < 3 && -1 < 2 x - y < 2, {x, y}, Integers]

which returns some structure like:

{{x -> -2, y -> -4}, {x -> -1, y -> -3}, {x -> -1, y -> -2}, {x -> 0, y -> -1}}

but how can I now make mathematica plot this so I can see the resulting shape. Preferably I would like the plot to consider every 'point' to be a 1x1 square.

Also, I wonder if there is a better way to do such things. Thanks.


Solution

  • Define the data you wish to plot by transforming the list Solve[] returns. This can done as

     data = {x, y} /. Solve[0 < x - y < 3 && -1 < 2 x - y < 2, {x, y}, Integers]
    

    More generally, you can make Solve return the solution in a list format (rather than as a set of rules) using the following trick:

     data = Solve[0 < x - y < 3 && -1 < 2 x - y < 2, {x, y}, Integers] /. Rule[a_,b_]->b
    

    For plotting, among many alternatives, you can use ListPlot as

    ListPlot[data, PlotMarkers -> {Style["\[FilledSquare]", FontSize -> 16]}]
    

    to get the following output

    output image

    You can further refine it using many styling and other options of ListPlot. For example, you can join the points

    ListPlot[data, PlotMarkers -> {Style["\[FilledSquare]", FontSize -> 16]}, 
     Joined -> True]
    

    to get

    joined plot

    EDIT: To play with the marker placement and size there are several alternatives. Using ListPlot you can get what you need in either of the two ways:

     (* 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}
    

    In both cases, you need to use Epilog, otherwise the lines joining points are occluded by the markers. Both alternatives produce the following output:

    listplot with markers

    Alternatively, you can use Graphics, RegionPlot, ContourPlot, BubbleChart with appropriate transformations of data to get results similar to the one in ListPlot output above.

    Using Graphics primitives:

     (* 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}
    

    Using 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}
    

    Using 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}
    

    Using 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}