QUINNDO is a language designed for linear optimization and statistical analysis.
Basic Data Types
Number (num)
num
a
=
5
|
5 | |
num
a
=
5.5
|
5.5 | |
num
a
=
5.5e6
|
5,500,000 | These syntaxes are why no symbol can be named "e" |
num
a
=
1e-3
|
0.001 | |
num
a
=
1_000_000
|
1,000,000 | Numbers can use underscores as a thousands separator |
Variable (var)
var
a
|
|
var
a,b
|
More than one variable can be declared per line |
Alias (alias)
Aliases are linear combinations of variables and numbers used in linear programming models.
alias
a
=
2b
+
5
|
|
alias
a
=
b
|
Numbers and variables are castable to aliases |
alias
a
=
5
|
Number Vector (nvec)
nvec
v
=
[2,a]
|
|
nvec
v
=
[2i
for
i=1
to
5]
|
=> [2,4,6,8,10] |
nvec
v
=
[2i
for
i=1
until
7
step
2]
|
=> [2,6,10] |
nvec
v
=
[2i
for
i
in
[6,9]
]
|
=> [12,18] |
Variable Vector (vvec)
vvec
v
=
[a,b]
|
|
vvec
v
=
[x{i}
for
i=1
to
5]
|
=> [x1,x2,x3,x4,x5] |
Alias Vector (avec)
avec
v
=
[a,b]
|
Number Matrix (nmtx)
nmtx
A
=
[
[1,2]
,
[3,4]
]
|
|
nmtx
A
=
ntmx(
[1,2,3,4]
)
|
Variable Matrix (vmtx)
vmtx
A
=
[
[a,b]
,
[c,d]
]
|
|
vmtx
A
=
vtmx(
[a,b,c,d]
)
|
Boolean (bool)
bool
b
=
true
|
Boolean Vector (bvec)
bvec
v
=
[true,b]
|
String (str)
str
s
=
"Hello World!"
|
String Vector (svec)
svec
v
=
["a",s]
|
Advanced Data Types
Number Matrix (nmtx)
nmtx( values:nvec , nrow?:num , ncol?:num , byrow?:bool=true ) | |||
---|---|---|---|
values | nvec | The values to insert into the number matrix | |
nrow? | num | The number of rows the matrix should have | If neither option is provided, the most square matrix will be built |
nrow? | num | The number of columns of the matrix should have | |
byrow? | bool | Whether values should be inserted row first |
Variable Matrix (vmtx)
vmtx( values:vvec , nrow?:num , ncol?:num , byrow?:bool=true ) | |||
---|---|---|---|
values | vvec | The values to insert into the variable matrix | |
nrow? | num | The number of rows the matrix should have | If neither option is provided, the most square matrix will be built |
nrow? | num | The number of columns of the matrix should have | |
byrow? | bool | Whether values should be inserted row first |
Model (model)
A Model is used to represent an optimization problem.
model( obj:alias ) | ||
---|---|---|
obj | alias | The objective value to optimize |
Network (ntwk)
A Network is used with its appended Nodes and Edges.
ntwk( bi?:bool=false ) | ||
---|---|---|
bi? | bool | Whether to make the network bidirectional |
Node (node)
A Node is used to represent a node/vertex in a Network.
node( id:str|num , source?:bool=false , sink?:bool=false ) | ||
---|---|---|
id | str|num | The id of the node |
source? | bool | Whether to make the node a source node |
sink? | bool | Whether to make the node a sink node |
Edge (edge)
A Node is used to represent an edge/arc in a Network.
edge( start:str|num|node , end:str|num|node , weight?:num=1 ) | |||
---|---|---|---|
start | str|num|node | The starting node or the id of the starting node | If no matching node is present in the network, a matching node will be created and added |
end | str|num|node | The ending node or the id of the ending node | |
weight? | num | The weight assigned to this edge |
Date (date)
If no values are provided, date() returns the current data and time in the user's time zone.
date( year?:num , month?:num , day?:num , hour?:num , minute?:num , second?:num ) |
|||
---|---|---|---|
year? | num | The year in the Gregorian calendar | |
month? | num | The month in the Gregorian calendar (Jan=1,Feb=2,...,Dec=12) | Note: Throws if present without year |
day? | num | The day in the month | Note: Throws if present without month |
hour? | num | The hour of the day in 24-hour format [0-23] | |
minute? | num | The minute of the hour [0-59] | Note: Throws if present without hour |
second? | num | The second of the minute [0-59] | Note: Throws if present without minute |
Date Vector (dvec)
A Date Vector is an enumerated vector of Date values.
Date Offset (offset)
A Date Offset is used to add or subtract period of time from a date.
offset( year?:num=0 , month?:num=0 , day?:num=0 , hour?:num=0 , minute?:num=0 , second?:num=0 ) |
||
---|---|---|
year? | num | The number of years to offset |
month? | num | The number of months to offset |
day? | num | The number of days to offset |
hour? | num | The number of hours to offset |
minute? | num | The number of minutes to offset |
second? | num | The number of seconds to offset |
Date Offset Vector (ovec)
A Date Offset Vector is an enumerated vector of Date Offset values.
Measurement (meas)
A Measurement value is a scalar with associated units.
meas( value:num , units:str ) | ||
---|---|---|
value | num | The scalar of the measurement |
units | str | The units of the measurement |
Measurement Vector (mvec)
A Measurement Vector is an enumerated vector of Measurement values.
Plot (plot)
A plot is used to render visualization of objects.
plot() |
---|
This Inator takes no arguments. |
Statistic Test Result (test)
A test object is used to hold the result of a statistical test.
test |
---|
This type cannot be created, only returned from another function. |
Operators
Assignment (=)
The assignment operator is used to store values and to establish equality constraints in conjunction with a model object.
Addition (+)
Subtraction (-)
Mutliplication (*)
Division (/)
Percent (%)
The percent operator is used to divide a value by 100. For example, 5% is the same as 0.05.
Exponentiation (^)
Modulus (mod)
Factorial (!)
Transpose (')
The transpose operator only works on matrices.
Pointwise Addition (addeach)
Pointwise Subtraction (subeach)
Pointwise Mutliplication (multeach)
Pointwise Division (diveach)
Not (~)
And (&)
Or (|)
Exclusive Or (xor)
Not Or (nor)
Equality (==)
Not Equal (~=)
This symbol is typed as a tilde "~" followed by an equal sign "=".
Strict Equality (===)
When comparing numbers, equality returns true if two numbers are within 10-8 of each other to avoid floating point errors. However, when comparing numbers, strict equality only returns true if two values are exactly equal. Also applies to inner values within a vector.
Strict Not Equal (~==)
Same difference as Equality versus Strict Equality, but negated. This symbol is typed as a tilde "~" followed by two equal signs "==".
Conditional Ternary (?:)
The conditional ternary operator switches between two values based on the value of a boolean
expression. For example,
b?1:0
evaluates to 1 if b is true and
0 if b is false.
If-Then (=>)
See description of If-And-Only-If.
If-And-Only-If (<=>)
If-Then and If-And-Only-If are used in constraints when appending to a model object. If-Then and If-And-Only-If are written as "=",">" and "<","=",">", respectively.
Append (<|)
Appends an object to another object. All object that can have values appended to them are the same color. Written as "<" followed by "|".
Piping (|>)
Pipes the previous result into the following function. By default, the piped value will be passed as the first parameter in the following function. This can be changed with the result keyword. Written as "|" followed by ">".
Spread (...)
Spreads the values of a list over the parameters of a function or values of a vector. For example,
range(1,10,3)
and
range(...[1,10,3])
are equivalent.
Similarly,
[
0
,
1
,
2
,
3
]
and
[
0
,
...[
1
,
2
]
,
3
]
are equivalent.
Vector Syntax
Vector Indexes
Vector indexes in QUINNDO are indexed from 1. Negative indexes count from the end. Non-integer indexes are not allowed.
nvec
a
=
[4,5,6]
assert
a[1]
==
4
assert
a[-1]
==
6
assert
a[0]
==
none
# Error: No value at index 0
assert
a[1.5]
==
none
# Error: Non-integer index
Vector Slicing
Vectors can be sliced with the
[start?:end?:step?]
syntax. If not provided, the default value of start, end, and step is 1, the end of the vector, and 1, respectively.
The sliced vector will include the end index.
nvec
a
=
[4,5,6,7,8]
assert
a[1:3]
==
[4,5,6]
assert
a[:3]
==
[4,5,6]
assert
a[2::2]
==
[5,7]
Vector Filtering
Vectors can be filtered by using the val keyword in the vector index with a filtering condition.
nvec
a
=
[5,6,7,8,9]
assert
a[val>6]
==
[7,8,9]
assert
a[val>=6]
==
[6,7,8,9]
assert
a[val
mod
2==0]
==
[6,8]
list
b
=
[6,true,none,8,a,10]
assert
b[val
is
num]
==
[6,8,10]
Matrix Indexes
Similar to vector indexes, matrix rows can by retrieved with
[index]
.
Matrix columns can be retrieved with
{index}
.
Matrix rows and columns have the same abilities and restrictions as vector indexes.
Useful Keywords
in
in is used to check if a value is present in a vector.
nvec
a
=
[6,7.5,9]
bool
b
=
6
in
a
# true
bool
c
=
8
in
a
# false
num
d
=
6
bool
f
=
d
in
a
# true
keyof
keyof is used to check if a given object has a given property.
test
a
=
ttest(
[1,2]
,
~=
,
5
)
bool
b
=
"rejected"
keyof
a
# true
bool
c
=
"abcdef"
keyof
a
# false
is and can
is and can are used to check the data-type of a value. is returns true if the data type exactly matches, while can returns true if a value can be casted to a given data type.
list
a
=
[6,7.5,9]
bool
b
=
a
is
list
# true
bool
c
=
a
is
nvec
# false because a is a list
bool
d
=
a
can
nvec
# true because a contains only numbers
fa and fo
fa and fo make up QUINNDO's try...catch syntax. Use these statements to provide a fallback value if code encounters an error.
num
a
=
1
/
0
# Throws error
num
b
=
fa
1
/
0
fo
5
# b=5
num
c
=
fa
1
/
2
fo
5
# b=1/2
stfu
stfu ("Suppress This Faulty Utterance") is used to disable warnings and recommendations on a line-by-line basis. stfu must the last command on its line.
num
a
=
4
mod
-3
# Raises warning because one parameter is negative
num
b
=
4
mod
-3
stfu
# Warning is suppressed
num
c
=
4
mod
-3
stfu
*
8
# Throws error because stfu is not at end of line
assert
assert evaluates a condition and throws an error if the condition is false.
assert
5
==
3
+
2
assert
6
==
3
+
2
# Throws error because assertion failed
Macros
Macros are special functions that handle larger operations and do not return a value.
Model Maximizer (maximize)
maximize( lp:model , thres?:num=1 ) | ||
---|---|---|
lp | model | The model to be maximized |
thres? | num | The solver tolerance for problem that contain integer constraints |
Model Minimizer (minimize)
minimize( lp:model , thres?:num=1 ) | ||
---|---|---|
lp | model | The model to be minimized |
thres? | num | The solver tolerance for problem that contain integer constraints |
Convert to LINDO (lindoize)
Converts a QUINNDO Model object to a LINDO program.
lindoize( lp:model , type:str ) | ||
---|---|---|
lp | model | The model to be converted to LINDO |
type | str | Must be one of "max" or "min" |
Shortest Path Finder (min_path)
min_path( net:ntwk , anchor:str|num|node , render?:bool=false ) | ||
---|---|---|
net | ntwk | The network in which to find the shortest path |
anchor | str|num|node | The point from which to find the shortest path |
render? | bool | Whether to print the model to the console on completion |
Renderer (render)
render is used to draw plots in the console.
render( obj:plot ) | ||
---|---|---|
obj | plot | The plot to draw in the console |
Print (print)
print is used to print objects to the console.
print( obj:any ) | ||
---|---|---|
obj | any | The object to print to the console |
Math Operations
Sign (sign)
Returns 1 if a number is greater than 0, -1 if a number is less than 0, and 0 if the number is 0.
Natural Logarithm (log)
Base-2 Logarithm (log2)
Base-10 Logarithm (log10)
Exponential (exp)
Absolute Value (abs)
Floor (floor)
Round (round)
Ceiling (ceil)
Square Root (sqrt)
Cube Root (cbrt)
Cosine (cos)
Arc-Cosine (acos)
Sine (sin)
Arc-Sine (asin)
Tangent (tan)
Arc-Tangent (atan)
Statistical Summaries
Sum (sum)
Mean (mean)
Median (median)
Mode (mode)
List Maximum (max)
List Minimum (min)
Sample Standard Deviation (samsd)
Sample Variance (samvar)
Population Standard Deviation (popsd)
Population Variance (popvar)
R-Squared (rsq)
Least Squares Linear Regression (lsr)
lsr( x:nvec|nmtx , y:nvec , int?:bool=true ): nvec | ||
---|---|---|
x | nvec|nmtx | A vector containing x values for single-variate regression or a matrix with entries in rows and variables in columns for multivariate regression |
y | nvec | The expected output values |
int? | bool | Whether to include the intercept in the regression - ignored for single-variate regressions |
Statistical Tests
One-Sample Z-Test (ztest)
ztest does a one-sample z-test.
ztest( sample:nvec , alt:operator , val:num , sigma:num , alpha?:num=5% ): test | ||
---|---|---|
sample | nvec | The sample data |
alt | operator | The sign of the alternative hypothesis - must be one of ~=, >, or < |
val | num | The threshold value of the alternative hypothesis |
sigma | num | The population standard deviation |
alpha? | num | The significance level of the test |
Two-Sample Z-Test (ztest2)
ztest2 does a two-sample z-test.
ztest2( sample1:nvec , sample2:nvec , sigma1:num , sigma2:num , alt?:operator= ~= , val?:num=0 , alpha?:num=5% ): test |
||
---|---|---|
sample1 | nvec | The sample data from the first sample |
sample2 | nvec | The sample data from the second sample |
sigma1 | num | The population standard deviation for sample1 |
sigma2 | num | The population standard deviation for sample2 |
alt? | operator | The sign of the alternative hypothesis - must be one of ~=, >, or < |
val? | num | The threshold value of the alternative hypothesis |
alpha? | num | The significance level of the test |
One-Sample T-Test (ttest)
ttest does a one-sample t-test.
ttest( sample:nvec , alt:operator , val:num , alpha?:num=5% ): test | ||
---|---|---|
sample | nvec | The sample data |
alt | operator | The sign of the alternative hypothesis - must be one of ~=, >, or < |
val | num | The threshold value of the alternative hypothesis |
alpha? | num | The significance level of the test |
Two-Sample T-Test (ttest2)
ttest2 does a two-sample t-test.
ttest2( sample1:nvec , sample2:nvec , alt?:operator= ~= , val?:num=0 , alpha?:num=5% , type?:num=0 ): test |
||
---|---|---|
sample1 | nvec | The sample data from the first sample |
sample2 | nvec | The sample data from the second sample |
alt? | operator | The sign of the alternative hypothesis - must be one of ~=, >, or < |
val? | num | The threshold value of the alternative hypothesis |
alpha? | num | The significance level of the test |
type? | num | The type of t-test to run (0=Welch's,1=Pooled,2=Student's) |
F-Test (ftest)
ftest does an F-test.
ftest( sample1:nvec , sample2:nvec , alt?:operator= ~= , alpha?:num=5% ): test | ||
---|---|---|
sample1 | nvec | The sample data from the first sample |
sample2 | nvec | The sample data from the second sample |
alt? | operator | The sign of the alternative hypothesis - must be one of ~=, >, or < |
alpha? | num | The significance level of the test |
ANOVA (anova)
anova does an ANOVA.
anova( samples:nmtx , alpha?:num=5% ): test | ||
---|---|---|
samples | nmtx | The data for the ANOVA - each factor must be a row |
alpha? | num | The significance level of the test |
Goodness of Fit Test (goftest)
goftest does a Χ2 goodness of fit test.
goftest( observed:nvec , expected:nvec , alpha?:num=5% ): test | ||
---|---|---|
observed | nvec | The observed values |
expected | nvec | The expected values to compare against |
alpha? | num | The significance level of the test |
Χ2 Test for Independence (indtest)
indtest does a Χ2 test for independence.
indtest( values:nmtx , alpha?:num=5% ): test | ||
---|---|---|
values | nmtx | The data for the independence test |
alpha? | num | The significance level of the test |
Vector & Matrix Functions
Vector Range Builder (range)
range( start?:num=1 , end:num , step?:num=1 ): nvec | ||
---|---|---|
start? | num | The start value of the final array |
end | num | The end value of the final array, which will be included |
step? | num | The step between values |
Vector Size (size)
size( x:list|str ): num | ||
---|---|---|
x | list|str | The value of which to find the size |
Matrix Row Count (nrow)
An alias of size for matrices.
nrow( x:nmtx|vmtx ): num | ||
---|---|---|
x | nmtx|vmtx | The matrix from which to find the number of rows |
Matrix Column Count (ncol)
Gets the number of column from a rectangular matrix.
ncol( x:nmtx|vmtx ): num | ||
---|---|---|
x | nmtx|vmtx | The matrix from which to find the number of columns |
Matrix Max Column Count (maxcol)
Gets the number of elements in the longest row of a matrix.
maxcol( x:nmtx|vmtx ): num | ||
---|---|---|
x | nmtx|vmtx | The matrix from which to find the max row length |
Matrix Min Column Count (mincol)
Gets the number of elements in the shortest row of a matrix.
mincol( x:nmtx|vmtx ): num | ||
---|---|---|
x | nmtx|vmtx | The matrix from which to find the min row length |
Unit Vector Normalizer (unit)
Returns a vector normalized to a magnitude of 1.
unit( v:nvec ): nvec | ||
---|---|---|
v | nvec | The vector to normalize |
Probability Normalizer (prob)
Returns a vector normalized to a valid probability distribution.
prob( v:nvec ): nvec | ||
---|---|---|
v | nvec | The vector to convert to a probability distribution |
Z-Score Normalizer (norm)
Returns a vector normalized to a mean of 0 and a sample standard deviation of 1.
norm( v:nvec ): nvec | ||
---|---|---|
v | nvec | The vector to normalize |
Vector Sorter (sort)
sort( v:nvec|svec , reverse?:bool=false ): nvec | ||
---|---|---|
v | nvec|svec | The vector to sort |
reverse? | bool | The direction in which to sort the list - ascending if false, descending if true |
Matrix Trace (trace)
trace( m:nmtx ): num | ||
---|---|---|
m | nmtx | The matrix of which to find the trace |
Matrix Determinant (deter)
deter( m:nmtx ): num | ||
---|---|---|
m | nmtx | The matrix of which to find the determinant |
Matrix Diagonal Elements (diag)
diag( values:nmtx ): nvec | ||
---|---|---|
values | nmtx | The matrix of which to find the diagonal elements |
Identity Matrix (identity)
identity( n:num ): nmtx | ||
---|---|---|
n | num | The dimension of the identity matrix |
Matrix Inversion (inv)
inv( m:nmtx ): nmtx | ||
---|---|---|
m | nmtx | The matrix to invert |
Unique Elements (unique)
Returns a copy of a list with duplicates removed.
unique( x:list ): list | ||
---|---|---|
x | list | The list from which to remove duplicates |
Common Elements (union)
Returns a list with values common to two lists.
union( list1:list , list2:list ): list | ||
---|---|---|
list1 | list | The first list |
list2 | list | The second list |
Miscellaneous Functions
String Vector Joiner (join)
Joins a String Vector into a String with a given string.
join( v:svec , sep?:str=" " ): str | ||
---|---|---|
v | svec | The string vector to join |
sep? | str | The string with which to join the vector |
String Splitter (split)
Splits a String into a String Vector with a given string.
split( s:str , sep?:str=" " ): svec | ||
---|---|---|
s | str | The string to split |
sep? | str | The string with which to split the string |
Examples
Scatter Plot
nvec
x
=
range(5)
# [1,2,3,4,5]
nvec
y
=
range(
5
,
13
,
2
)
# [5,7,9,11,13]
plot
p
=
plot.scatter(
x
,
y
)
render(p)
Student's 2-Sample T-Test
nvec
s1
=
[7,2,4]
nvec
s2
=
range(3)
# [1,2,3]
test
t
=
ttest2(
s1
,
s2
,
type=ttest2.student
)
Integer Programming
The Lotus Point Condo Project will contain both homes and apartments. The site can accommodate up to 10,000 dwelling units. The project must contain a recreation project: either a swimming-tennis complex or a sailboat marina, but not both. If a marina is built, then the number of homes in the project must be at least triple the number of apartments in the project. A marina will cost $1.2 million, and a swimming-tennis complex will cost $2.8 million. The developers believe that each apartment will yield revenues with an NPV of $48,000, and each home will yield revenues with an NPV of $46,000. Each home (or apartment) costs $40,000 to build. Formulate an IP to help Lotus Point maximize profits.
Problem From: Winston, W. L., & Goldberg, J. B. (2004). Operations research: Applications and Algorithms. Brooks/Cole.
var
a,h,m,t
# apartments, homes, marina, tennis complex
model
p
=
model(
8a
+
6h
-
1200m
-
2800t
)
p
<|
a
+
h
<=
10_000
# building constraint
p
<|
m
=
1
xor
t
=
1
# either marina or tennis/swimming
p
<|
m
=
1
=>
h
>=
3a
# marina building type constraint
p
<|
a,h
is
int
# integer constraint
p
<|
m,t
is
bin
# binary constraint
maximize(p)
Shortest Path
ntwk
n
=
ntwk()
n
<|
edge(
1
,
2
,
1
)
# start,end,weight
n
<|
edge(
1
,
3
,
2
)
n
<|
edge(
2
,
3
,
3
)
n
<|
edge(
3
,
2
,
1
)
n
<|
edge(
2
,
4
,
3
)
n
<|
edge(
3
,
4
,
2
)
min_path(
n
,
1
)
# Get shortest path to all other nodes from node 1