15

I'm trying to figure out whether it's possible to implement the following Mathematica interface.

I would like to create an interface in Mathematica whereby the user would be able to define graphically and interactively an arbitrary number of numerical parameters, subject to a constraint.

The parameters in questions are numerical weights [0,1], each associated to a corresponding criterion and constrained to summing to one. Obvously, this constraint induces a trade-off to the weights that can be associated to each criterion and I wanted to make such trade-off evident graphically, by having an interactive plot along the line of what follows (made in Excel, unfortunately):

Example of graphical weight definition

In this example, there are 6 criteria, but I would like to generalize that to an arbitrary number (between 2 and 7, for instance).

The interface would work by dragging each of the polygon vertices (corresponding to a specific weight) along the corresponding axis, and having the others adjust uniformely so that they always sum to 1.

The numerical values would then be returned to be used in subsequent computations.

I have looked around and do not seem to be able to find someone who had the same problem (the definition of the search queries is non-trivial, probably).

The closest thing I've found among Mathematica's examples is the following application of the locator pane, where 3 points are allowed to be moved on a square and their position is returned:

DynamicModule[{pt = {{1, 1}/2, {-1, 1}/2, {1, -1}/2}}, {LocatorPane[ Dynamic[pt], Graphics[{Gray, Disk[]}]], Dynamic[pt]}]

double-beep
  • 5,031
  • 17
  • 33
  • 41
MatteoS
  • 745
  • 2
  • 6
  • 17
  • Please note that Dynamic[] and its friends are tough to tame. I don't recommend starting to learn Mma by using them. – Dr. belisarius Oct 24 '11 at 02:46
  • Point taken, thank you! ;-) Actually, I'm trying to build up gradually, but I needed to ensure that this particular interface could be done in Mathematica because I'm thinking about porting an entire software I wrote in MMA and this is an essential part of it. – MatteoS Oct 24 '11 at 07:57
  • Remember you can interface other languages – Dr. belisarius Oct 24 '11 at 11:03

2 Answers2

13

Perhaps something like this:

n = 6;
posText[x_List] := Text[Round[Norm@#/Total@(Norm /@ x), .01], 1.3 #, 
                        Background -> LightRed] & /@ x;
rot = RotationMatrix[Pi/15];
DynamicModule[{
  pt = pti = {Re@#, Im@#} &@(E^(2 I Pi #/n)) & /@ Range@n,
  r  = Array[1 &, n]},
 Column@{LocatorPane[
    Dynamic[pt],
    Framed@Graphics[
      {(*The Arrows*)
       Black, Arrow[{{0, 0}, 1.2 #}] & /@ pt,

       (*The Criteria Numbers*)
       MapIndexed[{Text[Style[#2[[1]],20], #1],Circle[#1,.1]}&, 1.1 rot.#&/@pti],

       (*The Cyan Polygons*)
       FaceForm[None], EdgeForm[Cyan], Polygon[pt #] & /@ Range[.2, 1, .2],

       (*The Points*)
       Black, Dynamic[Point[r = MapThread[#1 Clip[#1.#2, {0, 1}] &, {pti, pt}]]],

       (*The Text legends*)
       Dynamic[posText@ r],

       (*The Red Polygon*)
       EdgeForm[{Red, Thick}], Dynamic[Polygon@r]},

      ImageSize -> 550, PlotRange ->1.5 {{-1, 1}, {-1, 1}}], 
    Appearance -> None],
   (*The Footer*)
   Dynamic[Grid[{Table[Norm@r[[i]], {i, n}]}/Total@(Norm /@ r), Dividers->All]]}]

enter image description here

enter image description here

Dr. belisarius
  • 60,527
  • 15
  • 115
  • 190
  • Thank you! Almost there! It works numerically, in the sense that the results indeed sum to 1 when rescaling the polygon. However, the actual size of the red polygon is unconstrainded and can be made arbitrarily small. I was hoping to make the trade-off apparent graphically by having every vertex rescaled uniformly when one is moved. Also, the initial (graphical) size should be 1/n for every weight (1/6 in this case). – MatteoS Oct 23 '11 at 20:32
  • @MatteoS Having all points to move when you change only one is very disturbing. I prefer this kind of interface where you set up the values by relatively (vs. absolutely) change the vector values. – Dr. belisarius Oct 23 '11 at 20:46
  • I see. Just for the sake of comparison, could you please show how you would have the size of other weight graphically re-adjusted? (I'm tweaking the code, but it fails me at the moment) I appreciate your help! – MatteoS Oct 23 '11 at 20:54
  • Twenty edits? I thought *I* was bad about that! (You may have noticed that most of my comments show the edit icon next to them.) – Mr.Wizard Oct 24 '11 at 02:57
  • @Mr. Yep. I am using this answer to learn some tricks ... a pity it turned out to CW :) – Dr. belisarius Oct 24 '11 at 03:31
  • 1
    @Mr. BTW I believe a good programmer must have the perfectionism virus running into his veins. Punishing perfectionism by converting answers to CW after N edits is (I think) the silliest rule around here. – Dr. belisarius Oct 24 '11 at 03:50
  • I don't see that rule as being much help. I suppose this has been discussed before; I shall try to find that discussion. EDIT: here is one of them: http://meta.stackexchange.com/questions/333/is-there-any-point-forcing-a-post-to-community-wiki-after-6-owner-edits – Mr.Wizard Oct 24 '11 at 05:09
  • BTW, currently there is a "reflection" off of the center point when moving the controls; that is, moving past the center causes the control to start moving backward. Can you fix that? – Mr.Wizard Oct 24 '11 at 05:21
  • @Mr. corrected in the above code. I changed the (* The Points *) part. – Dr. belisarius Oct 24 '11 at 05:58
  • 1
    That's great, but I just wanted you to make another edit. ;-) http://www.youtube.com/watch?v=UI1zKC02IoI – Mr.Wizard Oct 24 '11 at 06:54
  • Very nice and clean interface, belisarius, thank you for your effort! – MatteoS Oct 24 '11 at 08:06
  • @Mr. I broke my previous record indeed http://stackoverflow.com/questions/3265986/an-algorithm-to-space-out-overlapping-rectangles/3279877#3279877 :D – Dr. belisarius Oct 24 '11 at 11:09
  • 2
    @belisarius Mods can remove CW. The CW for 10 edits rule was in place because people kept editing repeatedly to bump it to the front page and hence more votes. Given that most of your edits here have been substantial, within a few hours of original posting _and_ mathematica is a small tag that won't show up in most people's front pages, I reckon you could try asking a moderator to review your case. You might want to explain it in a flag. – abcd Oct 24 '11 at 14:49
  • @yoda Thanks a lot. I don't think it is _that_ important. I enjoyed polishing the code and _that_ is important. – Dr. belisarius Oct 24 '11 at 23:49
  • @belisarius I'd have been surprised if you had gone along... you have more than enough rep. And rep is meaningless anyway :) – abcd Oct 25 '11 at 00:11
10

Maybe something like this

Manipulate[
 DynamicModule[{mags, pts, bkgrnd, corners},
  corners = N@Table[{Sin[2 Pi i/n], Cos[2 Pi i/n]}, {i, n}];
  mags = N@Table[1/n, {n}];
  pts = mags corners;
  bkgrnd = {{FaceForm[Opacity[0]], EdgeForm[Gray], 
     Polygon[ Table[r corners, {r, .2, 1, .2}]]},
    Table[
     Text[Row[{"Criterion ", i}], 
      1.05 corners[[i]], -corners[[i]]], {i, n}]};

  LocatorPane[
   Dynamic[
    pts, (mags = Norm /@ #; mags = mags/Total[mags]; 
      pts = mags corners) &],
   Dynamic@Graphics[{bkgrnd,
      {FaceForm[], EdgeForm[{Thick, Blue}], Polygon[pts]},
      Table[
       Text[NumberForm[mags[[i]], {4, 2}], 
        pts[[i]], -1.8 corners[[i]]], {i, n}]}, PlotRange -> All],
   Appearance -> Graphics[{PointSize[.02], Point[{0, 0}]}]]],

 {{n, 3}, Range[3, 7]}]

Screenshot:

screenshot

Heike
  • 24,102
  • 2
  • 31
  • 45
  • Not your fault, of course, but I find this kind of UI almost impossible to use. – Dr. belisarius Oct 23 '11 at 22:18
  • 1
    When you move one point, the rest shrink. For example try moving one point and then set all of them equal again by moving them. – Dr. belisarius Oct 23 '11 at 22:33
  • 1
    I must say, I'm impressed by both answers, but this one conveys exactly the graphical trade-off I had in mind. Well done and thank you to the both of you! Concerning @belisarius 's comment, I see what he means, but could this difficulty be solved simply by having a "reset" button that sets all of the weights to 1/n? – MatteoS Oct 24 '11 at 08:02
  • Of course, in this case, when the number of criteria increases, the default size of the interactive polygon gets comparatively smaller and small changes in values around 1/n are tricky to achieve. Maybe one could set the scale of the axis on a logarithmic scale to get around this, what do you think? – MatteoS Oct 24 '11 at 08:12
  • @MateoS So try to set two weights to a value which is the double of the rest – Dr. belisarius Oct 24 '11 at 12:40