Difference between revisions of "Draw arrows to build models"

(new page copied and edited from release notes)
 
 
(16 intermediate revisions by 3 users not shown)
Line 1: Line 1:
These new and improved features let you build and modify model expressions just by drawing arrows between variables -- without typing:
+
[[Category: Concepts]]
 +
[[Category: Diagrams]]
  
* If you draw an arrow from index I to variable A defined as a Table (or a ProbTable, DetermTable), if I is not an index of A, it will ask if you want to add I as an extra dimension of A. If I is already an index of A, it will ask if you want to remove it.  
+
You can do quite a bit of modeling just by drawing arrows between variables and modules without having to type in definitions explicitly. This works when the definition of the destination variable contains various kinds of list. For example, if variable <code>Y</code> is defined as a simple list in square brackets and you draw an arrow from variable <code>X</code> to <code>Y</code>, it automatically adds <code>X</code> into the list. You can also connect modules in a similar way by drawing arrows to and from Modules with  [[TemplateInput and TemplateOutput Attributes]].
  
* If you draw an arrow from array A to B and A is already in the definition of B:  
+
== Draw arrows to add variables into a definition ==
* Deleting arrows or input variables: If you delete an arrow from A to B (select and press "delete" key, or just redraw an arrow), Analytica changes the definition of B. It used to substitute "expr" in place of A and surround the entire definition with [[FunctionOf]](...).  That was inconvenient and lost information about the former input.  Now, if the Mid value of A is a scalar (single number or text), it substitutes it into the definition of B. Otherwise, it replaces A by '{A}' (a comment).  Or if you delete A, it doesn't change the definition of B, but B will no longer parse, and its node is cross-hatched.
+
Suppose you draw an arrow from variable <code>A</code> to <code>B</code>. It automatically adds <code>A</code> into the definition of <code>B</code> when the definition of <code>B</code> contains one of these kinds of list:
 +
; A list in square brackets:
 +
For example:
 +
:<code>B := Sum([X])</code>
 +
* If <code>A</code> isn't already in the list, it adds <code>A</code>:
 +
:<code>B := Sum([X, A])</code>
 +
* Or, if <code>A</code>, is already in the list, it removes it
 +
:<code>B := Sum([X])</code>
 +
If A is the only element in the list, it replaces it by expr, for example:
 +
:<code>B := Sum([A])</code>
 +
* After redrawing the arrow from <code>A</code>, is already in the list, it removes it: 
 +
:<code>B := Sum([expr])</code>
  
* Auto definitions: If you draw an arrow from A to B:
+
; If <code>A</code> is an Index:
** If B is a list of zero or more variables ''not including'' A, or if B is a function call whose first parameters is such a list, it adds A into the list. For example
+
If <code>B</code> is an Atom (single number or text value) or an [[Edit table]], it offers to add <code>A</code> as an Index of <code>B</code>. This offers a convenient way to add an index dimension to a model. For example:
  B := Sum([X])
+
:<code>B := 100</code>
 +
* If <code>A</code> isn't already an index of the table, it offers to add <code>A</code> as an index. If you accept, the result is:
 +
:<code>B := Table(A)(...)</code>
 +
* Or, if <code>A</code>, is already an index, it offers to remove it (after warning you that it will lose data by removing a dimension). If you accept, it shows this result:
 +
:<code>B := 100</code>
 +
 
 +
; [[Handle Functions#Function ListOfHandles|ListOfHandles]]:
 +
For example:
 +
:<code>B := ListofHandles([X])</code>
 +
* If <code>A</code> isn't already in the list, it adds <code>A</code>:
 +
:<code>B := ListofHandles([X, A])</code>
 +
* Or, if <code>A</code>, is already in the list, it removes it: 
 +
:<code>B := ListofHandles([X])</code>
 +
 
 +
; Repeated parameters:
 +
If <code>B</code> uses a function whose first parameter is qualified as [[Function_Parameter_Qualifiers#Repeated_parameters_.28....29|Repeated]] (or "..."), it behaves like an explicit list in square brackets. For example,
 +
<pre style="background:white; border:white; margin-left: 1em;">
 +
Function ObjList(vars: ... Variable)
 +
B := Objlist(X)
 
   draw an arrow from A to B
 
   draw an arrow from A to B
  B := Sum([X, A])
+
B := Objlist(X, A)
 +
</pre>
 +
 
 +
Note: "Repeated" means ''one or more'' elements. If you remove the last input by redrawing an arrow from <code>A</code> to <code>B</code>, it replaces it by "expr", which will not parse. If you want ''zero or more'' elements, you should qualify the parameter with [[Function_Parameter_Qualifiers#Optional_qualifier|Optional]] along with "...", for example:
 +
:<code>Function ObjList(vars: ... Optional Variable)</code>
 +
 
 +
'''Note:''' It automatically adds <code>A</code> into the list in <code>B</code> (or removes it if it's already there) if the defintion of <code>B</code> contains one of the above constructs as its ''only'' element. If the Definition contains one of these constructs along with others, e.g.
 +
:<code>B := [X] + 3</code>
 +
it does not do automatic insertion or removal. It simply adds <code>A</code> as a ''possible'' input to <code>B</code>, and leaves it to the modeler as to where to insert it into the definition.
 +
 
 +
== Delete an arrow ==
 +
 
 +
If there is an arrow from variable <code>A</code> to <code>B</code>, you can delete it
 +
* either by selecting the arrow and pressing the "delete" key,
 +
* or by redrawing the arrow from <code>A</code> to <code>B</code>.
 +
If <code>A</code> is already in the definition of <code>B</code>, it asks if you want to remove <code>A</code> from the Definition of <code>B</code>. If so, it puts comment brackets around the origin variable <code>{A}</code>, in the definition of <code>B</code>, so you can see what was removed. Often, the resulting definition will have bad syntax, indicated by the node for <code>B</code> becoming cross-hatched.
 +
 
 +
; Redraw a deleted arrow: If you delete an input to <code>B</code> as above, and then redraw an arrow from <code>A</code> to <code>B</code>, it restores the original definition by removing the comment brackets <code>{A}</code> around the variable, <code>A</code>.
  
** If B is a list of variables ''including'' A, or is a function whose first parameter is such a list, it removes A from the list. For example,
+
== Drawing arrows to Modules with TemplateInput and TemplateOutput attributes ==
  B := Sum([X, A])
 
  draw an arrow from A to B
 
  B := Sum([X])
 
** If B uses a function whose first parameter is an ellipsis (repeating) variable, it similarly adds A (or removes A if it is already there). For example,
 
Function ObjList(vars: ... Optional Variable)
 
B := Objlist(X)
 
    draw an arrow from A to B
 
B := Objlist(X, A)
 
Note: If you want Objlist to have no parameters, you must use the '''Optional''' qualifier along with "..." -- otherwise, the function needs at least one parameter.
 
** If you draw an arrow from index I to and Edit table B, if B is not indexed by I, it  askif you want to add I as an index. If so, it adds the index to the table, repeating the current value over each value of I. If B is already indexed by I, it will ask if you want to remove I as an index. If so, the new value of B will be the first slice of its old value over I. It will lose all other data.
 
  
* When you drag a nodes into a module, or use the "Move to Parent" action, the location of the node in the module is not so crammed up so tightly in the top-left corner.
+
You can even construct models by drawing arrows to and from modules, if the modules are set up as '''templates'''. A Template module should have one of its variables as the [[TemplateInput]] attribute of the module, and another variable as the [[TemplateOutput]] attribute. When you draw an arrow into a template module, it's the same as drawing an arrow into its template input variable.  So, if the definition of the Template input variable contains a list [], ListofVariables, Edit table, or uses a function with a repeated parameter (as described above),  when you draw an arrow into the module, it inserts the origin variable into the list. When you draw an arrow from a module with a  [[TemplateOutput]], it's as if you were drawing an arrow from the variable in the [[TemplateOutput]].
  
* Undo also works for:
+
It's often useful to create a template module and then make copies of it for particular instantiations. You can link them together by drawing arrows.
** Move Into Parent
 
** Move node(s) using the arrow keys
 
  
* A couple UI glitches fixed: Stray compute button, result windows immediately recomputing after invalidation.
+
==See Also==
 +
* [[Draw arrows]]
 +
* [[Draw arrows between modules]]
 +
* [[Template Modules]]
 +
* [[TemplateInput and TemplateOutput Attributes]]
 +
* [[Creating or editing a definition]]
 +
* [[Function Parameter Qualifiers]]

Latest revision as of 22:43, 24 May 2021


You can do quite a bit of modeling just by drawing arrows between variables and modules without having to type in definitions explicitly. This works when the definition of the destination variable contains various kinds of list. For example, if variable Y is defined as a simple list in square brackets and you draw an arrow from variable X to Y, it automatically adds X into the list. You can also connect modules in a similar way by drawing arrows to and from Modules with TemplateInput and TemplateOutput Attributes.

Draw arrows to add variables into a definition

Suppose you draw an arrow from variable A to B. It automatically adds A into the definition of B when the definition of B contains one of these kinds of list:

A list in square brackets

For example:

B := Sum([X])
  • If A isn't already in the list, it adds A:
B := Sum([X, A])
  • Or, if A, is already in the list, it removes it:
B := Sum([X])

If A is the only element in the list, it replaces it by expr, for example:

B := Sum([A])
  • After redrawing the arrow from A, is already in the list, it removes it:
B := Sum([expr])
If A is an Index

If B is an Atom (single number or text value) or an Edit table, it offers to add A as an Index of B. This offers a convenient way to add an index dimension to a model. For example:

B := 100
  • If A isn't already an index of the table, it offers to add A as an index. If you accept, the result is:
B := Table(A)(...)
  • Or, if A, is already an index, it offers to remove it (after warning you that it will lose data by removing a dimension). If you accept, it shows this result:
B := 100
ListOfHandles

For example:

B := ListofHandles([X])
  • If A isn't already in the list, it adds A:
B := ListofHandles([X, A])
  • Or, if A, is already in the list, it removes it:
B := ListofHandles([X])
Repeated parameters

If B uses a function whose first parameter is qualified as Repeated (or "..."), it behaves like an explicit list in square brackets. For example,

Function ObjList(vars: ... Variable)
B := Objlist(X)
   draw an arrow from A to B
B := Objlist(X, A)

Note: "Repeated" means one or more elements. If you remove the last input by redrawing an arrow from A to B, it replaces it by "expr", which will not parse. If you want zero or more elements, you should qualify the parameter with Optional along with "...", for example:

Function ObjList(vars: ... Optional Variable)

Note: It automatically adds A into the list in B (or removes it if it's already there) if the defintion of B contains one of the above constructs as its only element. If the Definition contains one of these constructs along with others, e.g.

B := [X] + 3

it does not do automatic insertion or removal. It simply adds A as a possible input to B, and leaves it to the modeler as to where to insert it into the definition.

Delete an arrow

If there is an arrow from variable A to B, you can delete it

  • either by selecting the arrow and pressing the "delete" key,
  • or by redrawing the arrow from A to B.

If A is already in the definition of B, it asks if you want to remove A from the Definition of B. If so, it puts comment brackets around the origin variable {A}, in the definition of B, so you can see what was removed. Often, the resulting definition will have bad syntax, indicated by the node for B becoming cross-hatched.

Redraw a deleted arrow
If you delete an input to B as above, and then redraw an arrow from A to B, it restores the original definition by removing the comment brackets {A} around the variable, A.

Drawing arrows to Modules with TemplateInput and TemplateOutput attributes

You can even construct models by drawing arrows to and from modules, if the modules are set up as templates. A Template module should have one of its variables as the TemplateInput attribute of the module, and another variable as the TemplateOutput attribute. When you draw an arrow into a template module, it's the same as drawing an arrow into its template input variable. So, if the definition of the Template input variable contains a list [], ListofVariables, Edit table, or uses a function with a repeated parameter (as described above), when you draw an arrow into the module, it inserts the origin variable into the list. When you draw an arrow from a module with a TemplateOutput, it's as if you were drawing an arrow from the variable in the TemplateOutput.

It's often useful to create a template module and then make copies of it for particular instantiations. You can link them together by drawing arrows.

See Also

Comments


You are not allowed to post comments.