[F#] Dev Life's Little Pleasures

Different languages have some little things that make the life easier: for devs, their QAs and customers. The app is fast and behaves correctly, the code looks simple and understandable - everyone is happy.

Here is the slides and a couple of code samples from my talk “[F#] Dev Life’s Little Pleasures”. Briefly, it takes some real-world problems 1 and provides the simple solutions.

[Originally posted here.]

Captain Kitteh - Mutability

  1. Units of Measure - need to admit, I was a long time sceptic (c’mon, how can you get kg and m^2 mixed up?)… until was given a spreadsheet with a “correct formula”, but its result didn’t make sense at all.

  2. Generic Restrictions - one of my favourite features! A lot of people don’t even know about it. That’s unfair. The most complex example I could think of - a static member with out-parameter) is included. But as always - use with care, it might become quite cryptic.

  3. Immutability as a default - mostly for the devs with C# or similar background. Great to be sure the things won’t change.

  4. Nulls and Options - the classic.

  5. Discriminated Unions and Pattern-Matching - invalid states shouldn’t have a possibility to appear (and yes, sometimes it’s better to forget about the underscores).

Let the compiler help you!

  1. simplified a bit

The World Around Us: back to words with J

The most exciting phrase to hear in science, the one that heralds new discoveries, is not “Eureka!” (I’ve found it!), but “That’s funny…” (Isaac Asimov)

[Originally posted here.]

Sometimes everybody wants to get off the beaten track and see the world. See how many exciting discoveries are waiting for you there.

J Logo

I want to bring your attention to a language, which changed the vision of some things for me. This language is J.

J is an array programming language; it is also functional and even object-oriented. And extremely concise. If you ever called F# ‘cryptic’ because of its operators or started to hate a Scala dev writing /: instead of fold – stop right here, because this language is definitely not for you.

If you have a suspicion that J is for aliens, relax – it’s just different. In terms of grammar J is literally closer to English than C or Java. Who said ‘token’? It’s time to remember the good old ‘word’. Functions are verbs, objects – nouns, statements - sentences etc.

Now let’s experiment!

It’s really funny, that whys start with:

J is a very rich language. You could study and use it for years, and still consider yourself a beginner.

You’ll get it later =).

But what trapped me for a weekend? I suspect it’s all about unusual code and the new ways of thinking. Maybe something is wrong with me, but J is really fun to write and read! (though the latter requires more effort…)

Some operators

*: - square
/ - ‘insert’, f/ x y z = x f y f z
% - division
_ - unary minus
>: - increment
# - ‘tally’, the number of elements
@ - ‘atop’, composition
@. – ‘agenda’/switch conjunction
=: - assignment
` - ‘tie’ conjunction
|. – reverse the order
|: - transpose matrix
+/ .* - matrix multiplication

Conjunctions

First of all, note, that the rightmost function is applied first, so 3*2+1 = 3*(2+1) = 9. How do we calculate, say, the sum of squares?

Square numbers (command output is green):

 1: *: 1 2 3
    1 4 9

J has a special operator /, called ‘insert’, I prefer to think about it as ‘reduce’:

 1: +/ 1 2 3
    6

The equivalent is 1 + 2 + 3.
So the sum of squares can be written as

 1: +/ *: 1 2 3
    14

Conjunction & allows to ‘fix’ the left or right argument:

 1: (^&2) 1 2 3
    1 4 9
 2: (2&^) 1 2 3
    2 4 8

Monads and Dyads

Those who like the forbidden M-word may be confused. But APL-style definition is actually older: monad is a function taking a single argument on the right (like *: above). Dyad takes two arguments, on the left and on the right (40 + 2).

Hooks and Forks

When two verbs come together, we call it a hook:
(f g) y = y f (g y)

Let’s normalize the list of elements so that their sum is equal to 1 (note, that division is denoted with %). See the naïve variants and a hook:

 1: 1 2 5 % (1 + 2 + 5)
 2: 1 2 5 % +/ 1 2 5
 3: (% +/) 1 2 5
    0.125 0.25 0.625

Three verbs form a fork:
(f g h) y = (f y) g (h y)

My favorite fork example is mean:

 1: (+/ % #) 1 2 3 4
    2.5

The same as

 1: (+/ 1 2 3 4) % (# 1 2 3 4)
 2: +/ 1 2 3 4 % # 1 2 3 4

Gerund

The things are getting even more interesting: meet a gerund (the result of `)! The sense is similar to English: derived from a verb, but functions as a noun.

 1: + ` -
    ┌─┬─┐
    │+│-│
    └─┴─┘

We can choose one of the ‘boxes’ with switch conjunction @.:

 1: + ` - @. 0
    +
 2: + ` - @. 1
    -

Look at the abs implementation:

 1: abs =: + ` - @. (< & 0)
 2: abs 42
    42
 3: abs _42
    42

Gerund can be used together with ‘insert’, e.g. the following statement sentence is equivalent to (50 * 2 % 100):

 1: * ` % / 50 2 100
    1

More Verbs!

#. – dyad ‘base’ or monad ‘from base 2’

 1: #. 1 0 0 1   
    9  
 2: 3 #. 2 1   
    7

[ and ] – ‘same’, id or argument

 1: [ 2   
    2
 2: 1 [ 2   
    1  
 3: ] 2   
    2  
 4: 1 [ 2   
    2

+/\ – running sum (the same works for * etc)

 1: +/\ 2 3 4   
    2 5 9
 2: acc =: /\
 3: + acc 2 3 4
    2 5 9
 4: * acc 2 3 4
    2 6 24

{. - take (n {. L)

 1: 2 {. 3 4 5   
    3 4

}. - drop (n }. L)

 1: 2 }. 3 4 5   
    5

{ - fetch

 1: 1 { 3 4 5 6   
    4
 2: _1 { 3 4 5 6   
    6

/: - sorting

 1: /: 10 2 5 3   
    1 3 2 10

Remember fork, id and fetch?

 1: (/: { ]) 10 2 5 3   
    2 3 5 10

q: - prime factors

 1: q: 20   
    2 2 5

p: - generate nth prime

 1: p: 3   
    7

sum 100 primes:

 1: +/ p: i. 100   
    24133

Modelling Transitions

Having several states and markov-process like transitions probabilities, what is the probability of one of these states at some time? Credit rating migrations can be taken as an example of such transitions.

So we define matrix and initial state probabilities:

 1: T =: 3 3 $ 0.6 0.3 0.1 0.1 0.5 0.4 0 0.1 0.9
 2: x =: 0.3 0.2 0.5

At time y the result is T^y (x u^:n y is equivalent to x u x u …(n times) y). What is the probability of state 3?

 1: T3 =: T +/ .*^:2 T
 2: +/ x * (2 {|: T3)
    0.6668
 3: +/ x * [ 2 {|: T3
    0.6668
 4:  2 { x +/ .* T3
    0.6668

The first two options transpose matrix, select the column with index 2 and calculate dot-product with x. The last one uses matrix multiplication verb.

Present Value

Given the stream of cashflows and rate (in %), we want to calculate PV.
Cashflows: 100 50
Rate: 5%
PV = 100 + 50 / (1 + 5%) = 147.61905

Splitting by steps:
- transform %

 1: pv =: >:@(] % 100"_)
 2: pv 5
    1.05
  • compute discount factor
 1: pv =: %@>:@(] % 100"_)
 2: pv 5
    0.952381
 3: 1 % 1.05
    0.952381
  • reverse cashflows list and sum the discounted values (50*df^1 + 100*df^0):
 1: |. 100 50
    50 100
 2: 0.952381 #. |. 100 50
    147.619
  • combine everything
 1: pv =: %@>:@(] % 100"_) #. |.@[
 2: 100 50 pv 5
    147.619

Bonus

If you’re still able to follow this post, here’s a couple of references:
- J Reference Card (2 pages to your rescue);
- financial phrases;
- essay on piano tuning;
- linear recurrences and matrix powers;
- simplex method in J.

Happy crazy coding!

 

 

Excel-DNA: Three Stories

Intro: Simulation

A couple of days ago I found a spreadsheet, potentially quite an interesting one. In theory, it should run a simple simulation (50000 paths by default) written in VBA - I’d say it’s several minutes of work in the worst case. However, it took slightly more. One working day, to be precise. I still have no idea what it tried to do, why it ate 97% of CPU and even what exactly it computed, because all that ended with a weird error and crashed Excel. The code is of unknown origin and protected, so no way to check it and I just gave up.

[Originally posted here.]

Now think about an average Excel user. He/she doesn’t care about how exactly it works, in which language written or how difficult it was for you to implement. What is important then?

  • functionality: everything what comes to mind can become a function;

  • simplicity: nobody wants to write VBA (and usually anything else too), but it’s always nice to have some useful UDFs at hand;

  • reliability: you have a well-tested library already, so why not to call it instead of rewriting in a poor language?

  • performance: why wait for a day when there’re highly optimized libraries and distributed computing is already invented?

For those who hasn’t tried it yet - check Excel-DNA. It’s an open-source project, which allows to integrate .NET into Excel. And yes, actually not only .NET ;) Documentation, samples, links to related posts can be found on the project page.

Spreadsheet

 

Keep Simple Things Simple

Let’s take log-linear interpolation as an example. Simple? Sure. We want to keep calculations clear in case if someone’d like to modify it - took 9 rows for me: functions like OFFSET and MATCH are not very friendly. And you still need to remember about sorting, extrapolation, duplicate values. What if there’re thousands of points?

Instead we call a UDF, which does all the work, it behaves in a specified way and can be reused in the future. I won’t describe how to create an addin - for more information check the project homepage. Briefly, in addition to a standard F# project we need a reference to ExcelDna.Integration.dll, interpolation.dna file with a reference to our library and a copy of ExcelDna.xll (x64 version is also available), renamed to interpolation.xll.

The future UDF has ExcelFunction attribute 1. For consistency with Excel function names it’s called LOGLINEAR. You can also add a description, category and so on. All parameters and output here are float arrays.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16:   

17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
open ExcelDna.Integration

[<AutoOpen>]
module Interpolation =

    let private interpolate curve (point: float) =
        let len = Array.length curve
        let u =
            if point < fst curve.[0] then 1
            elif point > fst curve.[len-1] then len-1
            else Array.findIndex (fun (v, _) -> point < v) curve
        let (xu, yu), (xd, yd) = curve.[u], curve.[u-1]
        let lnp = log yd + (log yu - log yd) / (xu - xd) * (point - xd)
        exp lnp

    [<ExcelFunction(Name="LOGLINEAR", Description="Log-Linear Interpolation",
Category="Custom", IsThreadSafe = true)>]
    let loglinear (xs: _[]) (ys: _[]) points =
        let curve =
            Seq.zip xs ys
            |> Seq.distinctBy fst
            |> Seq.sort
            |> Seq.toArray

        if curve.Length < 2 then failwith "at least 2 points are required"
        Array.map (interpolate curve) points

After loading the add-in in Excel (double-click on interpolation.xll in output folder), you can just type LOGLINEAR and see the results!2.

Excel-Interpolation

 

Make Complex Things Simple

Well, it’s cool, but I still can do this interpolation by hands - and it’ll work, you don’t need to be super-smart to do a couple of subtractions and multiplications without mistakes. But things are getting more interesting when a bunch of standard functions is not enough.

How about machine learning with Excel? Of course, it can be handy only for experiments with adequately small amounts of data. But for sure, not something I’d want to write in VBA.

A lot of my fellow traders use random forests for feature selection (it is actually what I like about RF most) before feeding the data into actual models, neural nets or anything else. So let’s take a look at rtp addin, which can help to find important features and get rid of useless (and potentially harmful?) ones. Important point: this example is for demo purposes only! I took some Yahoo stock prices - it’s not that easy to get good data for free, so can’t call it realistic; the same works for features3. If you want a bit more for free, there’re also two old kaggle competitions: Benchmark Bond Trade Price Challenge  and Algorithmic Trading Challenge  (the winners used RF).

Anyway, we are lucky because all data is numeric. Even more than that - we have F# R Type Provider and can use R’s randomForest package!

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
open RProvider
open RProvider.``base``
open RProvider.randomForest

open ExcelDna.Integration

[<ExcelFunction(Name = "IMPORTANCE", 
    Description = "Variable importance measures as produced by R's randomForest ")>]
let importance (names: obj[]) (values: float[,]) (ys: float[]) =
    let cols = min names.Length (values.GetLength 1)
    let rows = min ys.Length (values.GetLength 0)

    let xs = 
        names
        |> Seq.take cols
        |> Seq.mapi (fun j name ->
            string name, Array.init rows (fun i -> values.[i, j]))
        |> namedParams
        |> R.data_frame            

    let rf = R.randomForest(xs, ys)
    (R.importance rf).Value

Look at the R-Importance tab: we call the function {=IMPORTANCE(Names,Data,Result)} and get a nice set of values - the greater the value, the greener and more important it is. For example, P5 and P6 (close prices for day-5 and day-6 respectively) seem to be not very useful.

Spreadsheet

Adding features is pretty straightforward too. Say, we want to calculate Simple Moving Average with different offsets:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
[<ExcelFunction(Name = "SMA", Description="Simple Moving Average")>]
let sma (values: float[]) (nobj: float) =
    let n = int nobj
    let len = values.Length
    if len < n || n < 2 then box ExcelError.ExcelErrorNA
    else 
        let res = Array2D.zeroCreate len 1

        Seq.windowed n values
        |> Seq.map Seq.average
        |> Seq.iteri (fun i v -> res.[i+n-1, 0] <- box v)
        resize res

The interesting thing here is resize function: it allows you not to select the whole output range when calling a function, but just type =SMA(Values,5) in the top cell and result array is automatically resized. The code of these examples is available on github.

Excel-DNA makes it possible to bring all .NET power to the spreadsheets. Just try it ^_^

 

 

  1. see interpolation project here.

  2. as a reminder, array formulae are entered with Ctrl+Shift+Enter.

  3. and also my experience has nothing to do with trading.

Days and Ghost Refinements

Let’s look at the simple function, which calculates the number of days between dates, when there’re 30 days in a month (and 360 in a year).

[Originally posted here.]

Something like this F# code:

 1: 
 2: 
let days360 sy sm sd ey em ed =
    (ey - sy)*360 + (em - sm)*30 + (ed - sd)

We can even write a bunch of tests to be sure the function works:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
let tests = [
    DateTime(2012,2,29), DateTime(2013,2,28), 359
    DateTime(2012,2,29), DateTime(2012,3,01), 2
    DateTime(2012,2,29), DateTime(2013,3,01), 362
    DateTime(2012,3,01), DateTime(2013,3,01), 360
    DateTime(2011,2,28), DateTime(2013,2,28), 720
    DateTime(2012,5,31), DateTime(2012,7,31), 60
]

//true
tests |> Seq.forall(fun (s,e,res) ->
    days360 s.Year s.Month s.Day e.Year e.Month e.Day = res)

As you see days360 doesn’t take .NET DateTime` as parameters, but ints. Would be nice to check them. Say, a month can take value from 1 to 12 - so what we need is a refinement type. F* supports two types of refinements: concrete and ghost. Here is how they are defined in “Secure Distributed Programming with Value-Dependent Types” paper:

Concrete refinements are pairs representing a value and a proof term serving as a logical evidence of the refinement property, similar to those in Coq and Fine.

Ghost refinements are used to state specifications for which proof terms are not maintained at run time. Ghost refinements have the form where is a value variable, is a type, and is a logical formula, itself represented as a type that must have kind and may depend on and other in-scope variables. Ghost refinements provide the following benefits:
- they enable precise symbolic models for many cryptographic patterns and primitives, and evidence for ghost refinement properties can be constructed and communicated using cryptographic constructions, such as digital signatures;
- they benefit from a powerful subtyping relation: is a subtype of ; this structural subtyping is convenient to write and verify higher-order programs;
- they provide precise specification to legacy code without requiring any modifications; - when used in conjunction with concrete refinements, they support selective erasure and dynamic reconstruction of evidence, enabling a variety of new applications and greatly reducing the performance penalty for runtime proofs.

Here we use the numbers as an example, because they are simple and intersections/unions of types are obvious. Note that we don’t verify that the dates are entirely valid. This is an artificial example - small enough to try it online =).

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
type year = x:int{ 1900 <= x /\ x <= 9999 }
type month = x:int{ 1 <= x /\ x <= 12 }
type day = x:int{ 1 <= x /\ x <= 31 }  

val days360: year -> month -> day -> int

let days360 sy sm sd ey em ed =
    (ey - sy)*360 + (em - sm)*30 + (ed - sd)

let _ = days360 2013 6 1 2013 6 42

We run F* - and get a type check time failure!

input(12,8-12,34) : Error : Expected an expression of type:
x_5_1:int{((LTE 1 x_5_1) && (LTE x_5_1 31))}
but got (42): int
Type checking failed

Well, 12 was supposed to be here:

1: 
let _ = days360 2013 6 1 2013 6 12 //ok

But wait, there’re still 31-day months… and February. With EU 30/360 convention 31 is simply replaced with 30, so we modify the function:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
let adjDay d = if d = 31 then 30 else d

let days360 sy sm sd ey em ed =
    let sd, ed = adjDay sd, adjDay ed
    (ey - sy)*360 + (em - sm)*30 + (ed - sd)

//DateTime(2012,4,25), DateTime(2012,7,31), 95
//DateTime(2012,6,30), DateTime(2012,7,31), 30
//DateTime(2012,2,28), DateTime(2012,3,31), 32
//DateTime(2012,2,29), DateTime(2012,3,31), 31

In this case start and end dates can’t be greater than 30. Can we define that with types? Sure!

 1: 
 2: 
 3: 
 4: 
type day30 = x:day{ x <> 31 }

val adjDay: day -> day30
let adjDay d = if d = 31 then 30 else d //try to leave only d here - it fails to typecheck

What if we want to add another convention? US 30/360 handles EOM dates differently, so if a start date is greater than end date the function results can become inconsistent. So we expect start date to be less than (or equal to) end date. A type checker can verify this requirement too:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
val daysInMonth: year -> month -> day

val lastDay: year -> month -> day -> bool -> bool
//EU 30/360: the last day of Feb is not changed to 30
let lastDay y m d eu =
    if eu && (m = 2) then false
    else d = (daysInMonth y m)

let adjDay d last = if last then 30 else d

val days360: sy:year -> sm:month -> sd: day
    -> ey:year{ey >= sy}
    -> em:month{ey > sy \/ (ey = sy /\ em >= sm)}
    -> ed:day{ey > sy \/ em > sm \/ ed >= sd}
    -> bool
    -> int

let days360 sy sm sd ey em ed convEU =
    let slast, elast = lastDay sy sm sd convEU, lastDay ey em ed convEU in

    //EU: 31 -> 30
    //US: 31 -> 30; end of Feb -> 30
    let sd = adjDay sd slast in
    //EU: 31 -> 30
    //US: 31 -> 30 if sd is EOM; end of Feb -> 30 if sd was end of Feb too
    let checkEndDate = convEU || (slast && ((sm = 2) || not (em = 2))) in
    let ed = adjDay ed (elast && (convEU || checkEndDate)) in

    (ey - sy)*360 + (em - sm)*30 + (ed - sd)

let _ = days360 2013 7 6 2015 7 6 true
let _ = days360 2015 7 6 2013 7 6 true //error

The last line gives the following error:

input(44,8-44,29) : Error :
Expected an expression of type: x_23_6: Dates.year{GTE x_23_6 2013}
but got (2013): int
Type checking failed

All these >, \/, /\, < look funny, if it’s not enough – just imagine the effect of adding time components. Fortunately, the relation between the dates can be defined as a separate type:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
//start date <= end date
type LTE = fun sy sm sd ey em ed => 
    ey > sy \/ (ey = sy /\ (em > sm \/ (em = sm /\ ed >= sd)))

val days360: sy:year -> sm:month -> sd:day
    -> ey:year -> em:month -> ed:day{LTE sy sm sd ey em ed}
    -> bool
    -> int

Now let’s assume that a date is valid when it’s not 2/30 or 2/31. We can define a logical function using logic val construct. Such functions can be used in refinements but not in code itself. The axioms are defined using the assume construct:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
logic val isValidDate: year -> month -> day -> bool
assume Valid: forall y m (d:day{m <> 2 \/ d < 30}). isValidDate y m d = true 

val days360: sy:year -> sm:month -> sd:day{isValidDate sy sm sd = true}
    -> ey:year -> em:month -> ed:day{isValidDate ey em ed = true /\ LTE sy sm sd ey em ed}
    -> bool
    -> int

Well, quite enough of refinements for a start. There’s much more ways to apply them: for example, refinements with affine values are great for verification of stateful programs (see the “Secure multi-party sessions in F” section in the paper). With rise4fun you may get a request timeout in more complex cases, so I’d recommend to download the F package for your experiments.

References

1. “Secure Distributed Programming with Value-Dependent Types” paper.
2. F* home page.
3. Rise4fun tutorial.

Bonus

Time to get back to the good old tests: the obvious idea is to compare the results with Excel. We are interested in two functions: DAYS360 and YEARFRAC - multiplying the result with 360. Look at the following comparison (when the spreadsheet was converted to Google Docs format, the results were changed, so I added separate rows with Excel output):

There’re obvious problems with DAYS360 when the dates are swapped (start date > end date) and end-of-Feb cases. But our function is different from YEARFRAC too.

Date adjustments rules for 30/360US:
1. If the investment is EOM and D1, D2 are the last day of Feb, then D2 = 30.
2. If the investment is EOM and D1 is the last day of Feb, then D1 = 30.
3. If D2 is 31 and D1 is 30 or 31, then D2 = 30.
4. If D1 is 31, then D1 = 30.

Let the start and end dates be 2/29/2012 and 3/31/2012 respectively. The rules are applied in order:
D2 - D1 = D2 - 30 = 30 - 30 = 0

But in Excel the rule 3 goes before the rule 2 (our function can be simply modified to behave the same way: sm = 2 || em <> 2 should be replaced with (sm = 2) = (em = 2)):
D2 - D1 = 31 - D1 = 31 - 30 = 1

So we expect to see (2012 – 2012)*360 + (3 – 2)*30 + 0 = 30 and not 31.
F# version is available here.

 

 

LP: Simplex Draft

Everybody solves some optimization problems – the airlines schedule flights, companies manage production facilities, salesman still looks for traveling options… When you need to achieve the best outcome minimizing/maximizing a linear cost functions you meet linear programming.

[Originally posted here].

LP was developed for military purposes in 1939, so it has a long history. Now it is one of the most important problems in operations research and heavily used in different areas directly or as sub-problems.

###Intro The standard algorithm here is the simplex method. Lots of information is floating around, but let’s review the basics. There’re several forms for expressing linear programs. Standard form:

We assume that the rows of matrix (m x n) are linearly independent.

The form above can be easily converted to slack form with a help of the new variables (slack variables):

So the problem now is

Simplex

Geometrical interpretation for 2 variables is very intuitive: all and satisfying the constraints are feasible solutions, and an optimal solution – maximum or minimum – is at a vertex. This feasible region, for n variables – in n-dimensional space, is called a simplex. The algorithm terminates when it reaches an optimal objective value at some vertex.

Why write a custom implementation? For me Excel solver is usually a solution 1, works like a charm – when it’s not a Mac version. The naïve version of algorithm is quite simple to implement, it’s also a nice refresher and managed to solve the problem, so why not?

Consider the following problem:

The solution is very straightforward:
1. Convert to slack form

2. We see that the cost can be reduced with increasing (it’s also obvious that max value is equal to 3). If the cost is already optimal the solution is found.

For each the reduced cost is defined as

3. Look for a direction of cost decrease, when moving into the new direction we replace a basic variable with a new one; go to the next iteration.

###Implementation The first version I came up with was entirely immutable – with all the costs of creating new sets, matrices etc. But there’s no sense to recreate the whole matrix when only one column is changed for the next iteration. This version is listed below – not that functional, more dangerous, with a mutable state, but cares about time/memory. Note, that this implementation doesn’t handle some corner-cases as it was not a part of my goal.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
(Math.Net references)

type SimplexResult =
    | Success of Vector<float>
    | Error of string

/// Simplex method implementation
let simplexImpl (A: _ Matrix) b (c: _ Vector) (x: _ Vector, Ib: _[], In: _[]) =
    ...
    // 1. start with basic matrix
    let B = Seq.map A.Column Ib |> DenseMatrix.ofColumns m m
    
    let rec calc (Binv: _ Matrix) iter =
        // 2. reduce costs and check optimality conditions
        let p = cb * Binv * A
        c.MapIndexedInplace (fun i ci -> ci - p.[i])

        match Seq.tryFindIndex (fun i -> c.[i] < 0.) In with
        | Some jind ->
            let j = In.[jind]
            // 3. unboundness check
            let u = Binv * A.Column j
            if Seq.forall (fun ui -> ui <= 0.) u then Error "cost unbounded"
            else
                // 4. improvement
                let l, theta =
                    Seq.mapi (fun i ui -> i, x.[i] / ui) u
                    |> Seq.filter (fun (_, di) -> di > 0.)
                    |> Seq.minBy snd
               
                // 5. update solution
                x.MapIndexedInplace (fun i xi -> if i=l then theta else xi - theta*u.[i])

                // 6. update basis, indices and cost
                B.SetColumn(l, A.Column j)
                In.[jind] <- Ib.[l]
                Ib.[l] <- j
                cb.[l] <- c.[j]

                let Binv = inverse B
                calc Binv (iter + 1)
        | _ -> 
            // fill solution vector x0, x1, ..., xn
            let res = DenseVector.zeroCreate n
            Seq.iteri (fun i ib -> res.[ib] <- x.[i]) Ib
            Success res

    calc (B.Inverse()) 1

For simplicity we use the naïve initialization – all given variables become nonbasic, the slack ones – basic and their values are equal to constraints vector . The full method returns the solution vector and cost function value:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
/// naive initialization function - simply set basic x to b
let initSimplex (A0: _ Matrix) (b0: _ Vector) (c0: _ Vector) = (...)

/// Revised Simplex implementation: min cx, Ax <= b, x >= 0, b >= 0
let simplex A0 b0 (c0: _ Vector) =
    let A, b, c, x, Ib, In = initSimplex A0 b0 c0
    match simplexImpl A b c (x, Ib, In) with
    | Success xs -> 
        let x0 = xs.[ .. c0.Count-1]
        let cx = c0 * x0
        Some (x0, cx)
    | _ -> None

And now time for my favorite part of the method and one the best ways to improve performance – reuse the data you already have to avoid recomputations whenever it’s possible. In this case it’s about inverting the basis matrix. We know that $latex B$ at the next iteration is the same as current, except one column. There’s also the current . The naïve simplex + math = revised simplex method.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
/// invert matrix given inverse of one column different matrix
let inv (a: _ Matrix) (aprev: _ Matrix, u: float Vector, l) iter =
    // recompute from scratch, because errors accumulate
    if iter % 20 = 0 then a.Inverse() 
    else
        let ul = u.[l]
        let lrow = aprev.Row l
        Matrix.mapRows (fun i row -> 
            if i = l then row / ul else row - lrow * u.[i] / ul) aprev

Sample

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
standard problem form   
let A = matrix [[1.; 1.; 1.]
                [1.; 0.; 0.]
                [0.; 0.; 1.]
                [0.; 3.; 1.]]

let c = vector [1.; 5.; -2.]
let b = vector [4.; 2.; 3.; 6.]
    
simplex A b c |> printfn "%A" //[0.0;0.0;3.0],-6.0

Complete snippet version is available at github.

Summing up

  • mutability may be evil, but sometimes it’s a way to go;
  • reusing the computation results and the parts of datastructures ftw.

What to look at

  • MS Solver Foundation – quite a nice tool to check too (with msi downloads, but I tried it a long time ago with mono – and it worked).
  • some theory: Introduction to Linear Optimization book (Dimitris Bertsimas and John N. Tsitsiklis) or anything else.

 

 

val inv : Matrix<float> -> Matrix<float> * Vector<float> * int -> int -> Matrix<float>

Full name: Simplex2.inv

invert matrix given inverse of one column different matrix

val a : Matrix<float>

type: Matrix<float>
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable

Multiple items

type Matrix<'T (requires default constructor and value type and 'T :> System.ValueType and 'T :> System.IEquatable<'T> and 'T :> System.IFormattable)> =
class
member Add : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Add : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member Append : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Append : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member At : int * int -> 'T
member At : int * int * 'T -> unit
member Clear : unit -> unit
member ClearColumn : int -> unit
member ClearRow : int -> unit
member ClearSubMatrix : int * int * int * int -> unit
member Clone : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Column : int -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Column : int * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member Column : int * int * int -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Column : int * int * int * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member ColumnCount : int with get, set
member ColumnEnumerator : unit -> System.Collections.Generic.IEnumerable<System.Tuple<int,MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>>>
member ColumnEnumerator : int * int -> System.Collections.Generic.IEnumerable<System.Tuple<int,MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>>>
member ConditionNumber : unit -> 'T
member Conjugate : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Conjugate : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member ConjugateTranspose : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member CopyTo : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member CreateMatrix : int * int * bool -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member CreateVector : int * bool -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Determinant : unit -> 'T
member Diagonal : unit -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member DiagonalStack : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member DiagonalStack : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member Divide : 'T -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Divide : 'T * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member Equals : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> bool
member Equals : obj -> bool
member FrobeniusNorm : unit -> 'T
member GetHashCode : unit -> int
member IndexedEnumerator : unit -> System.Collections.Generic.IEnumerable<System.Tuple<int,int,'T>>
member InfinityNorm : unit -> 'T
member InsertColumn : int * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member InsertRow : int * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Inverse : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member IsSymmetric : bool
member Item : int * int -> 'T with get, set
member KroneckerProduct : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member KroneckerProduct : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member L1Norm : unit -> 'T
member L2Norm : unit -> 'T
member LeftMultiply : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member LeftMultiply : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member LowerTriangle : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member LowerTriangle : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member MapIndexedInplace : System.Func<int,int,'T,'T> * bool -> unit
member MapInplace : System.Func<'T,'T> * bool -> unit
member Modulus : 'T -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Modulus : 'T * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member Multiply : 'T -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Multiply : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Multiply : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Multiply : 'T * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member Multiply : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member Multiply : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member Negate : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Negate : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member NormalizeColumns : int -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member NormalizeRows : int -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member PermuteColumns : MathNet.Numerics.Permutation -> unit
member PermuteRows : MathNet.Numerics.Permutation -> unit
member PointwiseDivide : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member PointwiseDivide : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member PointwiseMultiply : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member PointwiseMultiply : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member Rank : unit -> int
member Row : int -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Row : int * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member Row : int * int * int -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Row : int * int * int * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member RowCount : int with get, set
member RowEnumerator : unit -> System.Collections.Generic.IEnumerable<System.Tuple<int,MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>>>
member RowEnumerator : int * int -> System.Collections.Generic.IEnumerable<System.Tuple<int,MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>>>
member SetColumn : int * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member SetColumn : int * 'T [] -> unit
member SetDiagonal : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member SetDiagonal : 'T [] -> unit
member SetRow : int * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member SetRow : int * 'T [] -> unit
member SetSubMatrix : int * int * int * int * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member Stack : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Stack : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member Storage : MathNet.Numerics.LinearAlgebra.Storage.MatrixStorage<'T> with get, set
member StrictlyLowerTriangle : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member StrictlyLowerTriangle : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member StrictlyUpperTriangle : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member StrictlyUpperTriangle : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member SubMatrix : int * int * int * int -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Subtract : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Subtract : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member ToArray : unit -> 'T [,]
member ToColumnWiseArray : unit -> 'T []
member ToMatrixString : int * int * System.IFormatProvider -> string
member ToMatrixString : int * int * int * string * System.IFormatProvider -> string
member ToRowWiseArray : unit -> 'T []
member ToString : unit -> string
member ToString : string * System.IFormatProvider -> string
member ToString : int * int * System.IFormatProvider -> string
member ToTypeString : unit -> string
member Trace : unit -> 'T
member Transpose : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member TransposeAndMultiply : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member TransposeAndMultiply : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member TransposeThisAndMultiply : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member TransposeThisAndMultiply : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member TransposeThisAndMultiply : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member TransposeThisAndMultiply : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
member UpperTriangle : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member UpperTriangle : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> unit
static member CreateFromColumns : System.Collections.Generic.IList<MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
static member CreateFromRows : System.Collections.Generic.IList<MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
static member DimensionsDontMatch<'TException> : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> -> System.Exception
static member DimensionsDontMatch<'TException> : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * string -> System.Exception
static member DimensionsDontMatch<'TException> : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * string -> System.Exception
static member DimensionsDontMatch<'TException> : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * string -> System.Exception
static member DimensionsDontMatch<'TException> : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * string -> System.Exception
static member DimensionsDontMatch<'TException> : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * string -> System.Exception
static member DimensionsDontMatch<'TException> : MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * string -> System.Exception
endFull name: MathNet.Numerics.LinearAlgebra.Generic.Matrix<_>

type: Matrix<'T>
implements: System.IFormattable
implements: System.IEquatable<Matrix<'T>>
implements: System.ICloneable

--------------------

type Matrix =
class
inherit MathNet.Numerics.LinearAlgebra.Generic.Matrix<float>
member ConjugateTranspose : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<float>
member FrobeniusNorm : unit -> float
member InfinityNorm : unit -> float
member L1Norm : unit -> float
member Trace : unit -> float
end

Full name: MathNet.Numerics.LinearAlgebra.Double.Matrix

type: Matrix
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable
inherits: Matrix<float>

val aprev : Matrix<float>

type: Matrix<float>
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable

val u : Vector<float>

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

Multiple items

val float : 'T -> float (requires member op_Explicit)Full name: Microsoft.FSharp.Core.Operators.float

--------------------

type float<'Measure> = float

Full name: Microsoft.FSharp.Core.float<_>

type: float<'Measure>
implements: System.IComparable
implements: System.IConvertible
implements: System.IFormattable
implements: System.IComparable<float<'Measure>>
implements: System.IEquatable<float<'Measure>>
inherits: System.ValueType

--------------------

type float = System.Double

Full name: Microsoft.FSharp.Core.float

type: float
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<float>
implements: System.IEquatable<float>
inherits: System.ValueType

Multiple items

type Vector<'T (requires default constructor and value type and 'T :> System.ValueType and 'T :> System.IEquatable<'T> and 'T :> System.IFormattable)> =
class
member AbsoluteMaximum : unit -> 'T
member AbsoluteMaximumIndex : unit -> int
member AbsoluteMinimum : unit -> 'T
member AbsoluteMinimumIndex : unit -> int
member Add : 'T -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Add : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Add : 'T * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member Add : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member At : int -> 'T
member At : int * 'T -> unit
member Clear : unit -> unit
member ClearSubVector : int * int -> unit
member Clone : unit -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Conjugate : unit -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Conjugate : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member CopySubVectorTo : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * int * int * int -> unit
member CopyTo : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member CopyTo : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * int * int * int -> unit
member Count : int with get, set
member CreateMatrix : int * int -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member CreateVector : int -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Divide : 'T -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Divide : 'T * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member DotProduct : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> 'T
member Equals : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> bool
member Equals : obj -> bool
member GetEnumerator : unit -> System.Collections.Generic.IEnumerator<'T>
member GetHashCode : unit -> int
member GetIndexedEnumerator : unit -> System.Collections.Generic.IEnumerable<System.Tuple<int,'T>>
member Item : int -> 'T with get, set
member MapIndexedInplace : System.Func<int,'T,'T> * bool -> unit
member MapInplace : System.Func<'T,'T> * bool -> unit
member Maximum : unit -> 'T
member MaximumIndex : unit -> int
member Minimum : unit -> 'T
member MinimumIndex : unit -> int
member Modulus : 'T -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Modulus : 'T * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member Multiply : 'T -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Multiply : 'T * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member Negate : unit -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Negate : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member Norm : float -> 'T
member Normalize : float -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member OuterProduct : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member Plus : unit -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member PointwiseDivide : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member PointwiseDivide : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member PointwiseMultiply : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member PointwiseMultiply : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member SetSubVector : int * int * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member SetValues : 'T [] -> unit
member Storage : MathNet.Numerics.LinearAlgebra.Storage.VectorStorage<'T> with get, set
member SubVector : int * int -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Subtract : 'T -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Subtract : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Vector<'T>
member Subtract : 'T * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member Subtract : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> unit
member Sum : unit -> 'T
member SumMagnitudes : unit -> 'T
member ToArray : unit -> 'T []
member ToColumnMatrix : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member ToRowMatrix : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
member ToString : unit -> string
member ToString : System.IFormatProvider -> string
member ToString : string * System.IFormatProvider -> string
member ToString : int * int * System.IFormatProvider -> string
member ToTypeString : unit -> string
member ToVectorString : int * int * System.IFormatProvider -> string
member ToVectorString : int * int * int * string * System.IFormatProvider -> string
static member OuterProduct : MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> * MathNet.Numerics.LinearAlgebra.Generic.Vector<'T> -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<'T>
endFull name: MathNet.Numerics.LinearAlgebra.Generic.Vector<_>

type: Vector<'T>
implements: System.IFormattable
implements: System.IEquatable<Vector<'T>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<'T>
implements: System.Collections.Generic.ICollection<'T>
implements: seq<'T>
implements: System.Collections.IEnumerable
implements: System.ICloneable

--------------------

type Vector =
class
inherit MathNet.Numerics.LinearAlgebra.Generic.Vector<float>
member AbsoluteMaximum : unit -> float
member AbsoluteMaximumIndex : unit -> int
member AbsoluteMinimum : unit -> float
member AbsoluteMinimumIndex : unit -> int
member MaximumIndex : unit -> int
member MinimumIndex : unit -> int
member Norm : float -> float
member Normalize : float -> MathNet.Numerics.LinearAlgebra.Generic.Vector<float>
member Sum : unit -> float
member SumMagnitudes : unit -> float
end

Full name: MathNet.Numerics.LinearAlgebra.Double.Vector

type: Vector
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable
inherits: Vector<float>

val l : int

type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType

val iter : int

type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType

Matrix.Inverse() : Matrix<float>

val ul : float

type: float
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<float>
implements: System.IEquatable<float>
inherits: System.ValueType

val lrow : Vector<float>

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

Multiple overloads

Matrix.Row(index: int) : Vector<float>

Matrix.Row(index: int, result: Vector<float>) : unit

Matrix.Row(rowIndex: int, columnIndex: int, length: int) : Vector<float>

Matrix.Row(rowIndex: int, columnIndex: int, length: int, result: Vector<float>) : unit

val mapRows : (int -> Vector<float> -> Vector<float>) -> #Matrix<float> -> Matrix<float>

Full name: MathNet.Numerics.LinearAlgebra.Double.Matrix.mapRows

val i : int

type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType

val row : Vector<float>

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

#r "MathNet.Numerics.dll"
#r "MathNet.Numerics.FSharp.dll"

open MathNet.Numerics.LinearAlgebra.Double
open MathNet.Numerics.LinearAlgebra.Generic

type SimplexResult =
| Success of Vector<float>
| Error of string

Full name: Simplex2.SimplexResult

type: SimplexResult
implements: System.IEquatable<SimplexResult>
implements: System.Collections.IStructuralEquatable

union case SimplexResult.Success: Vector<float> -> SimplexResult
union case SimplexResult.Error: string -> SimplexResult

Multiple items

val string : 'T -> stringFull name: Microsoft.FSharp.Core.Operators.string

--------------------

type string = System.String

Full name: Microsoft.FSharp.Core.string

type: string
implements: System.IComparable
implements: System.ICloneable
implements: System.IConvertible
implements: System.IComparable<string>
implements: seq<char>
implements: System.Collections.IEnumerable
implements: System.IEquatable<string>

val simplexImpl : Matrix<float> -> 'a -> Vector<float> -> Vector<float> * int [] * int [] -> SimplexResult

Full name: Simplex2.simplexImpl

Simplex method implementation

Multiple items

val A : Matrix<float> type: Matrix<float>
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable

--------------------

val A : Matrix<float>

type: Matrix<float>
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable

val b : 'a

val c : Vector<float>

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

val x : Vector<float>

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

val Ib : int []

type: int []
implements: System.ICloneable
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.IStructuralComparable
implements: System.Collections.IStructuralEquatable
implements: System.Collections.Generic.IList<int>
implements: System.Collections.Generic.ICollection<int>
implements: seq<int>
implements: System.Collections.IEnumerable
inherits: System.Array

val In : int []

type: int []
implements: System.ICloneable
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.IStructuralComparable
implements: System.Collections.IStructuralEquatable
implements: System.Collections.Generic.IList<int>
implements: System.Collections.Generic.ICollection<int>
implements: seq<int>
implements: System.Collections.IEnumerable
inherits: System.Array

let cb = Seq.map c.At Ib |> DenseVector.ofSeq
let m, n = A.RowCount, A.ColumnCount

val B : DenseMatrix

type: DenseMatrix
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable
inherits: Matrix
inherits: Matrix<float>

module Seq

from Microsoft.FSharp.Collections

val map : ('T -> 'U) -> seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.map

val A : Matrix<float>

type: Matrix<float>
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable

Multiple overloads

Matrix.Column(index: int) : Vector<float>

Matrix.Column(index: int, result: Vector<float>) : unit

Matrix.Column(columnIndex: int, rowIndex: int, length: int) : Vector<float>

Matrix.Column(columnIndex: int, rowIndex: int, length: int, result: Vector<float>) : unit

type DenseMatrix =
class
inherit MathNet.Numerics.LinearAlgebra.Double.Matrix
new : MathNet.Numerics.LinearAlgebra.Storage.DenseColumnMajorMatrixStorage<float> -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
new : int -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
new : int * int -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
new : int * int * float [] -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
new : int * int * float -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
new : float [,] -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
new : MathNet.Numerics.LinearAlgebra.Generic.Matrix<float> -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
member CreateMatrix : int * int * bool -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<float>
member CreateVector : int * bool -> MathNet.Numerics.LinearAlgebra.Generic.Vector<float>
member Data : float []
member FrobeniusNorm : unit -> float
member InfinityNorm : unit -> float
member L1Norm : unit -> float
member Trace : unit -> float
member Transpose : unit -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<float>
member Values : float []
static member Create : int * int * System.Func<int,int,float> -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member CreateRandom : int * int * MathNet.Numerics.Distributions.IContinuousDistribution -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member Identity : int -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member OfArray : float [,] -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member OfColumnMajor : int * int * System.Collections.Generic.IEnumerable<float> -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member OfColumns : int * int * System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<float>> -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member OfColumnsCovariant<'TColumn> : int * int * System.Collections.Generic.IEnumerable<'TColumn> -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member OfIndexed : int * int * System.Collections.Generic.IEnumerable<System.Tuple<int,int,float>> -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member OfMatrix : MathNet.Numerics.LinearAlgebra.Generic.Matrix<float> -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member OfRows : int * int * System.Collections.Generic.IEnumerable<System.Collections.Generic.IEnumerable<float>> -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member OfRowsCovariant<'TRow> : int * int * System.Collections.Generic.IEnumerable<'TRow> -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
end

Full name: MathNet.Numerics.LinearAlgebra.Double.DenseMatrix

type: DenseMatrix
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable
inherits: Matrix
inherits: Matrix<float>

val ofColumns : int -> int -> #seq<'b> -> DenseMatrix (requires 'b :> seq<float>)

Full name: MathNet.Numerics.LinearAlgebra.Double.DenseMatrix.ofColumns

val m : int

type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType

val calc : (Matrix<float> -> int -> SimplexResult)

val Binv : Matrix<float>

type: Matrix<float>
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable

val p : Vector<float>

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

val cb : DenseVector

type: DenseVector
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable
inherits: Vector
inherits: Vector<float>

Vector.MapIndexedInplace(f: System.Func<int,float,float>, forceMapZeros: bool) : unit

val ci : float

type: float
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<float>
implements: System.IEquatable<float>
inherits: System.ValueType

val tryFindIndex : ('T -> bool) -> seq<'T> -> int option

Full name: Microsoft.FSharp.Collections.Seq.tryFindIndex

union case Option.Some: 'T -> Option<'T>

val jind : int

type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType

val j : int

type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType

val forall : ('T -> bool) -> seq<'T> -> bool

Full name: Microsoft.FSharp.Collections.Seq.forall

val ui : float

type: float
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<float>
implements: System.IEquatable<float>
inherits: System.ValueType

val theta : float

type: float
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<float>
implements: System.IEquatable<float>
inherits: System.ValueType

val mapi : (int -> 'T -> 'U) -> seq<'T> -> seq<'U>

Full name: Microsoft.FSharp.Collections.Seq.mapi

val filter : ('T -> bool) -> seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Collections.Seq.filter

val di : float

type: float
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<float>
implements: System.IEquatable<float>
inherits: System.ValueType

val minBy : ('T -> 'U) -> seq<'T> -> 'T (requires comparison)

Full name: Microsoft.FSharp.Collections.Seq.minBy

val snd : ('T1 * 'T2) -> 'T2

Full name: Microsoft.FSharp.Core.Operators.snd

val xi : float

type: float
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<float>
implements: System.IEquatable<float>
inherits: System.ValueType

Multiple overloads

Matrix.SetColumn(columnIndex: int, column: float []) : unit

Matrix.SetColumn(columnIndex: int, column: Vector<float>) : unit

inv B (Binv, u, l) iter

val res : DenseVector

type: DenseVector
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable
inherits: Vector
inherits: Vector<float>

type DenseVector =
class
inherit MathNet.Numerics.LinearAlgebra.Double.Vector
new : MathNet.Numerics.LinearAlgebra.Storage.DenseVectorStorage<float> -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
new : int -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
new : float [] -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
new : int * float -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
new : MathNet.Numerics.LinearAlgebra.Generic.Vector<float> -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
new : System.Collections.Generic.IEnumerable<float> -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
member AbsoluteMaximum : unit -> float
member AbsoluteMaximumIndex : unit -> int
member AbsoluteMinimum : unit -> float
member AbsoluteMinimumIndex : unit -> int
member CreateMatrix : int * int -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<float>
member CreateVector : int -> MathNet.Numerics.LinearAlgebra.Generic.Vector<float>
member MaximumIndex : unit -> int
member MinimumIndex : unit -> int
member Norm : float -> float
member OuterProduct : MathNet.Numerics.LinearAlgebra.Double.DenseVector -> MathNet.Numerics.LinearAlgebra.Generic.Matrix<float>
member Sum : unit -> float
member SumMagnitudes : unit -> float
member Values : float []
static member Create : int * System.Func<int,float> -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
static member CreateRandom : int * MathNet.Numerics.Distributions.IContinuousDistribution -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
static member OfEnumerable : System.Collections.Generic.IEnumerable<float> -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
static member OfIndexedEnumerable : int * System.Collections.Generic.IEnumerable<System.Tuple<int,float>> -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
static member OfVector : MathNet.Numerics.LinearAlgebra.Generic.Vector<float> -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
static member OuterProduct : MathNet.Numerics.LinearAlgebra.Double.DenseVector * MathNet.Numerics.LinearAlgebra.Double.DenseVector -> MathNet.Numerics.LinearAlgebra.Double.DenseMatrix
static member Parse : string -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
static member Parse : string * System.IFormatProvider -> MathNet.Numerics.LinearAlgebra.Double.DenseVector
static member TryParse : string * MathNet.Numerics.LinearAlgebra.Double.DenseVector -> bool
static member TryParse : string * System.IFormatProvider * MathNet.Numerics.LinearAlgebra.Double.DenseVector -> bool
end

Full name: MathNet.Numerics.LinearAlgebra.Double.DenseVector

type: DenseVector
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable
inherits: Vector
inherits: Vector<float>

val zeroCreate : int -> DenseVector

Full name: MathNet.Numerics.LinearAlgebra.Double.DenseVector.zeroCreate

val n : int

type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType

val iteri : (int -> 'T -> unit) -> seq<'T> -> unit

Full name: Microsoft.FSharp.Collections.Seq.iteri

val ib : int

type: int
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<int>
implements: System.IEquatable<int>
inherits: System.ValueType

val initSimplex : Matrix<float> -> Vector<float> -> Vector<float> -> DenseMatrix * DenseVector * DenseVector * DenseVector * int [] * int []

Full name: Simplex2.initSimplex

naive initialization function - simply set basic x to b

val A0 : Matrix<float>

type: Matrix<float>
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable

val b0 : Vector<float>

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

val c0 : Vector<float>

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

let m, n = A0.RowCount, A0.ColumnCount
let n' = m + nif Seq.exists (fun bi -> bi < 0.) b0 then failwith "b should be > 0"// A0*x <= b ---> A*x' = b
let A = DenseMatrix.init m n' (fun i j ->
if j < n then A0.[i, j]
elif i = j - n then 1.
else 0.)// copy b
let b = DenseVector.OfVector b0
// extend c
let c = DenseVector.init n' (fun i -> if i < n then c0.[i] else 0.)
// default solution (basis xs)
let x = DenseVector.OfVector b0
let In, Ib = [| 0..n-1 |], [| n..n'-1 |]A, b, c, x, Ib, In

val simplex : Matrix<float> -> Vector<float> -> Vector<float> -> (Vector<float> * float) option

Full name: Simplex2.simplex

Revised Simplex implementation: min cx, Ax <= b, x >= 0, b >= 0

val A : DenseMatrix

type: DenseMatrix
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable
inherits: Matrix
inherits: Matrix<float>

val b : DenseVector

type: DenseVector
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable
inherits: Vector
inherits: Vector<float>

val c : DenseVector

type: DenseVector
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable
inherits: Vector
inherits: Vector<float>

val x : DenseVector

type: DenseVector
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable
inherits: Vector
inherits: Vector<float>

val xs : Vector<float>

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

val x0 : Vector<float>

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

property Vector.Count: int

val cx : float

type: float
implements: System.IComparable
implements: System.IFormattable
implements: System.IConvertible
implements: System.IComparable<float>
implements: System.IEquatable<float>
inherits: System.ValueType

union case Option.None: Option<'T>
(*
min x1 + 5*x2 - 2*x3
subject to
x1 + x2 + x3 <= 4
x1 <= 2
x3 <= 3
3*x2 + x3 <= 6
x1, x2, x3 >= 0 *)

val A : Matrix<float>

Full name: Simplex2.A

type: Matrix<float>
implements: System.IFormattable
implements: System.IEquatable<Matrix<float>>
implements: System.ICloneable

val matrix : float list list -> Matrix<float>

Full name: MathNet.Numerics.LinearAlgebra.Double.Utility.matrix

val c : Vector<float>

Full name: Simplex2.c

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

val vector : float list -> Vector<float>

Full name: MathNet.Numerics.LinearAlgebra.Double.Utility.vector

val b : Vector<float>

Full name: Simplex2.b

type: Vector<float>
implements: System.IFormattable
implements: System.IEquatable<Vector<float>>
implements: System.Collections.IList
implements: System.Collections.ICollection
implements: System.Collections.Generic.IList<float>
implements: System.Collections.Generic.ICollection<float>
implements: seq<float>
implements: System.Collections.IEnumerable
implements: System.ICloneable

val printfn : Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn

  1. one of the side-effects of my work are numerous spreadsheets, and Solver proved to be incredibly helpful.