Skip to content

Commit 154a38c

Browse files
committed
Add NL docs
1 parent e8c7524 commit 154a38c

File tree

3 files changed

+163
-6
lines changed

3 files changed

+163
-6
lines changed

README.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,110 @@ Here is a summary of the functions defined by MathOptFormat.
182182
| `"VectorAffineFunction"` | The function `Ax + b`, where `A` is a sparse matrix specified by a list of `VectorAffineTerm`s in `terms` and `b` is a dense vector specified by `constants`. | {"head": "VectorAffineFunction", "constants": [1.0], "terms": [{"output_index": 1, "scalar_term": {"coefficient": 2.5, "variable": "x"}}]} |
183183
| `"VectorQuadraticFunction"` | The vector-valued quadratic function `q(x) + Ax + b`, where `q(x)` is specified by a list of `VectorQuadraticTerm`s in `quadratic_terms`, `A` is a sparse matrix specified by a list of `VectorAffineTerm`s in `affine_terms` and `b` is a dense vector specified by `constants`. | |
184184

185+
#### Nonlinear functions
186+
187+
Nonlinear functions are encoded in MathOptFormat by an expression graph. Each
188+
expression graphs is stored in Polish prefix notation. For example, the
189+
nonlinear expression `sin²(x)` is expressed as `^(sin(x), 2)`.
190+
191+
The expression graph is stored as an object with three required fields:
192+
`"head"`, which must be `"Nonlinear"`, as well as `"root"` and `"node_list"`.
193+
194+
`"root"` contains an object defining the root node of the expression graph. All
195+
other nodes are stored as a flattened list in the `"node\_list"` field. We
196+
elaborate on permissible nodes and how to store them in the following
197+
subsections.
198+
199+
##### Leaf nodes
200+
201+
Leaf nodes in the expression graph are data: they can either reference
202+
optimization variables, or be real or complex valued numeric constants. They are
203+
described as follows.
204+
205+
| Head | Description | Example |
206+
| ---- | ----------- | ------- |
207+
| `"real"` | A real-valued numeric constant | {"head": "real", "value": 1.0} |
208+
| `"complex"` | A complex-valued numeric constant | {"head": "complex", "real": 1.0, "imag": 2.0} |
209+
| `"variable"` | A reference to an optimization variable | {"head": "variable", "name": "x"} |
210+
211+
Nodes in the flattened list `"node_list"` can be referenced by an object with
212+
the `"head"` field `"node"` and a field `"index"` that is the one-based index of
213+
the node in `"node_list"`.
214+
215+
| Head | Description | Example |
216+
| ---- | ----------- | ------- |
217+
| `"node"` | A pointer to a (1-indexed) element in the `node_list` field in a nonlinear function | {"head": "node", "index": 2} |
218+
219+
##### Other nodes
220+
221+
| Name | Arity |
222+
| `"log"` | Unary |
223+
| `"log10"` | Unary |
224+
| `"exp"` | Unary |
225+
| `"sqrt"` | Unary |
226+
| `"floor"` | Unary |
227+
| `"ceil"` | Unary |
228+
| `"abs"` | Unary |
229+
| `"cos"` | Unary |
230+
| `"sin"` | Unary |
231+
| `"tan"` | Unary |
232+
| `"acos"` | Unary |
233+
| `"asin"` | Unary |
234+
| `"atan"` | Unary |
235+
| `"cosh"` | Unary |
236+
| `"sinh"` | Unary |
237+
| `"tanh"` | Unary |
238+
| `"acosh"` | Unary |
239+
| `"asinh"` | Unary |
240+
| `"atanh"` | Unary |
241+
| `"/"` | Binary |
242+
| `"^"` | Binary |
243+
| `"+"` | N-ary |
244+
| `"-"` | N-ary |
245+
| `"*"` | N-ary |
246+
| `"min"` | N-ary |
247+
| `"max"` | N-ary |
248+
249+
##### Example
250+
251+
As an example, consider the function `f(x, y) = (1 + 3i) ⋅ x + sin^2(x) + y`.
252+
In Polish notation, the expression graph is:
253+
```f(x, y) = +(1 + 3i, ^(sin(x), 2), y)
254+
```
255+
In MathOptFormat, this expression graph can be encoded as follows:
256+
```json
257+
{
258+
"head": "Nonlinear",
259+
"root": {
260+
"head": "+",
261+
"args": [
262+
{"head": "node", "index": 1},
263+
{"head": "node", "index": 3},
264+
{"head": "variable", "name": "y"}
265+
]
266+
},
267+
"node_list": [
268+
{
269+
"head": "*", "args": [
270+
{"head": "complex", "real": 1, "imag": 3},
271+
{"head": "variable", "name": "x"}
272+
]
273+
}, {
274+
"head": "sin",
275+
"args": [
276+
{"head": "variable", "name": "x"}
277+
]
278+
}, {
279+
"head": "^",
280+
"args": [
281+
{"head": "node", "index": 2},
282+
{"head": "real", "value": 2}
283+
]
284+
}
285+
]
286+
}
287+
```
288+
185289
### List of supported sets
186290

187291
The list of sets supported by MathOptFormat are contained in the

mof.schema.json

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@
154154
"type": "object",
155155
"required": ["head"],
156156
"oneOf": [{
157-
"description": "Unary operators.",
157+
"description": "Unary operators",
158158
"required": ["args"],
159159
"properties": {
160160
"head": {
@@ -174,7 +174,7 @@
174174
}
175175
}
176176
}, {
177-
"description": "Binary operators.",
177+
"description": "Binary operators",
178178
"required": ["args"],
179179
"properties": {
180180
"head": {
@@ -190,7 +190,7 @@
190190
}
191191
}
192192
}, {
193-
"description": "N-ary operators.",
193+
"description": "N-ary operators",
194194
"required": ["args"],
195195
"properties": {
196196
"head": {
@@ -205,7 +205,8 @@
205205
}
206206
}
207207
}, {
208-
"description": "A real-valued numeric constant.",
208+
"description": "A real-valued numeric constant",
209+
"example": "{\"head\": \"real\", \"value\": 1.0}",
209210
"required": ["value"],
210211
"properties": {
211212
"head": {
@@ -216,7 +217,8 @@
216217
}
217218
}
218219
}, {
219-
"description": "A complex-valued numeric constant.",
220+
"description": "A complex-valued numeric constant",
221+
"example": "{\"head\": \"complex\", \"real\": 1.0, \"imag\": 2.0}",
220222
"required": ["real", "imag"],
221223
"properties": {
222224
"head": {
@@ -231,6 +233,7 @@
231233
}
232234
}, {
233235
"description": "A reference to an optimization variable",
236+
"example": "{\"head\": \"variable\", \"name\": \"x\"}",
234237
"required": ["name"],
235238
"properties": {
236239
"head": {
@@ -242,6 +245,7 @@
242245
}
243246
}, {
244247
"description": "A pointer to a (1-indexed) element in the `node_list` field in a nonlinear function",
248+
"example": "{\"head\": \"node\", \"index\": 2}",
245249
"required": ["index"],
246250
"properties": {
247251
"head": {

readme_builder/readme_builder.go

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ func generateDocs(jsonSchemaFilename string) (string, string, error) {
128128
"",
129129
processStrings("Vector Functions", data, "vector_functions")}, "\n")
130130

131-
return setSummary, functionSummary, nil
131+
nlSummary := processNonlinear(data)
132+
return setSummary, functionSummary + nlSummary, nil
132133
}
133134

134135
func processStrings(title string, data map[string]interface{}, key string) string {
@@ -148,3 +149,51 @@ func processStrings(title string, data map[string]interface{}, key string) strin
148149
}
149150
return strings.Join(setStrings, "\n")
150151
}
152+
153+
func processNonlinear(data map[string]interface{}) string {
154+
definitions := data["definitions"].(map[string]interface{})
155+
nonlinearTerm := definitions["NonlinearTerm"].(map[string]interface{})
156+
functionStrings := []string{
157+
"##### Functions",
158+
"",
159+
"| Name | Arity |"}
160+
161+
leafStrings := []string{
162+
"#### Nonlinear functions",
163+
"",
164+
"##### Leaf nodes",
165+
"| Name | Description | Example |",
166+
"| ---- | ----------- | ------- |"}
167+
168+
for _, setData := range nonlinearTerm["oneOf"].([]interface{}) {
169+
object := setData.(map[string]interface{})
170+
objects := processOneOf(object)
171+
172+
switch object["description"] {
173+
case "Unary operators":
174+
for _, f := range objects {
175+
functionStrings = append(functionStrings,
176+
fmt.Sprintf("| `\"%s\"` | Unary |", f.Head))
177+
}
178+
case "Binary operators":
179+
for _, f := range objects {
180+
functionStrings = append(functionStrings,
181+
fmt.Sprintf("| `\"%s\"` | Binary |", f.Head))
182+
}
183+
case "N-ary operators":
184+
for _, f := range objects {
185+
functionStrings = append(functionStrings,
186+
fmt.Sprintf("| `\"%s\"` | N-ary |", f.Head))
187+
}
188+
default:
189+
if len(objects) == 1 {
190+
leafStrings = append(leafStrings,
191+
fmt.Sprintf("| `\"%s\"` | %s | %s |", objects[0].Head, objects[0].Description, objects[0].Example))
192+
} else {
193+
fmt.Println("Unsupported object: %s", object)
194+
}
195+
}
196+
}
197+
return "\n" + strings.Join(leafStrings, "\n") + "\n\n" +
198+
strings.Join(functionStrings, "\n")
199+
}

0 commit comments

Comments
 (0)