ojAlgo - Expressing Variables as Boundaries in Optimization? - kotlin

I've been playing around with ojAlgo and I've been pretty thrilled with it so far. I've worked through a few studies with it but I'm having trouble with this problem described in this article.
I'm using Kotlin instead of Java, but that shouldn't cause any issues. I'm stuck trying to input an expression into my model but bounding on a variable rather than a literal numeric value. How do I input that?
Here is my work so far:
import org.ojalgo.optimisation.ExpressionsBasedModel
import org.ojalgo.optimisation.Variable
fun main(args: Array<String>) {
val model = ExpressionsBasedModel()
val ingredients = sequenceOf(
Ingredient("Pork", 4.32, 30),
Ingredient("Wheat", 2.46, 20),
Ingredient("Starch", 1.86, 17)
).map { it.name to it }
.toMap()
val sausageTypes = sequenceOf(
SausageType("Economy", .40),
SausageType("Premium", .60)
).map { it.description to it }
.toMap()
// Map concatenated string keys to variables
val variables = ingredients.values.asSequence().flatMap { ingredient ->
sausageTypes.values.asSequence()
.map { type -> Combo(ingredient,type)}
}.map { it.toString() to Variable.make(it.toString()).lower(0).weight(it.ingredient.cost) }
.toMap()
// add variables to model
model.addVariables(variables.values)
// Pe + We + Se = 350 * 0.05
model.addExpression("EconomyDemand").level(350.0 * 0.05).apply {
set(variables["Pork-Economy"], 1)
set(variables["Wheat-Economy"], 1)
set(variables["Starch-Economy"], 1)
}
// Pp + Wp + Sp = 500 * 0.05
model.addExpression("PremiumDemand").level(500.0 * 0.05).apply {
set(variables["Pork-Premium"], 1)
set(variables["Wheat-Premium"], 1)
set(variables["Starch-Premium"], 1)
}
// Pe >= 0.4(Pe + We + Se)
// compile error?
model.addExpression("EconomyGovRestriction").upper(variables["Pork-Economy"]).apply {
set(variables["Pork-Economy"], .4)
set(variables["Wheat-Economy"], .4)
set(variables["Starch-Economy"], .4)
}
}
data class Combo(val ingredient: Ingredient, val sausageType: SausageType) {
override fun toString() = "$sausageType-$ingredient"
}
data class SausageType(val description: String, val porkRequirement: Double) {
override fun toString() = description
}
data class Ingredient(val name: String, val cost: Double, val availability: Int) {
override fun toString() = name
}

For future readers, here is the full working solution I came up with.
import org.ojalgo.optimisation.ExpressionsBasedModel
import org.ojalgo.optimisation.Variable
import java.math.RoundingMode
fun main(args: Array<String>) {
val model = ExpressionsBasedModel()
val ingredients = sequenceOf(
Ingredient("Pork", 4.32, 30),
Ingredient("Wheat", 2.46, 20),
Ingredient("Starch", 1.86, 17)
).map { it.name to it }
.toMap()
val sausageTypes = sequenceOf(
SausageType("Economy", .40),
SausageType("Premium", .60)
).map { it.description to it }
.toMap()
// Map concatenated string keys to variables
val variables = ingredients.values.asSequence().flatMap { ingredient ->
sausageTypes.values.asSequence()
.map { type -> Combo(ingredient,type)}
}.map { it.toString() to Variable.make(it.toString()).lower(0).weight(it.ingredient.cost) }
.toMap()
// add variables to model
model.addVariables(variables.values)
// Pe + We + Se = 350 * 0.05
model.addExpression("EconomyDemand").level(17.5).apply {
set(variables["Pork-Economy"], 1)
set(variables["Wheat-Economy"], 1)
set(variables["Starch-Economy"], 1)
}
// Pp + Wp + Sp = 500 * 0.05
model.addExpression("PremiumDemand").level(25).apply {
set(variables["Pork-Premium"], 1)
set(variables["Wheat-Premium"], 1)
set(variables["Starch-Premium"], 1)
}
// Pe >= 0.4(Pe + We + Se)
model.addExpression("EconomyPorkRatio").upper(0.0).apply {
set(variables["Pork-Economy"], -0.6)
set(variables["Wheat-Economy"], .4)
set(variables["Starch-Economy"], .4)
}
// Pe >= 0.6(Pp + Wp + Sp)
model.addExpression("PremiumPorkRatio").upper(0.0).apply {
set(variables["Pork-Premium"], -0.4)
set(variables["Wheat-Premium"], .6)
set(variables["Starch-Premium"], .6)
}
// Se <= .25(Pe + We + Se)
// Sp <= .25(Pp + Wp + Sp)
sausageTypes.values.forEach {
model.addExpression("${it}StarchRestriction").lower(0.0).apply {
set(variables["Pork-$it"], .25)
set(variables["Wheat-$it"], .25)
set(variables["Starch-$it"], -0.75)
}
}
// Pe + Pp <= 30
// We + Wp <= 20
// Se + Sp <= 17
ingredients.values.forEach { ingredient ->
model.addExpression("${ingredient}SupplyConstraint").upper(ingredient.availability).apply {
sausageTypes.values.forEach { sausageType ->
set(variables["$ingredient-$sausageType"], 1)
}
}
}
// Pe + Pp >= 23
model.addExpression("ContractPorkRestriction").lower(23).apply {
set(variables["Pork-Economy"], 1)
set(variables["Pork-Premium"], 1)
}
// go!
val result = model.minimise()
println("OPTIMIZED COST: ${result.value}")
model.variables.asSequence()
.map { it.name }
.zip(result.asSequence().map { it.setScale(3, RoundingMode.HALF_DOWN) })
.forEach(::println)
}
data class Combo(val ingredient: Ingredient, val sausageType: SausageType) {
override fun toString() = "$ingredient-$sausageType"
}
data class SausageType(val description: String, val porkRequirement: Double) {
override fun toString() = description
}
data class Ingredient(val name: String, val cost: Double, val availability: Int) {
override fun toString() = name
}
OUTPUT:
OPTIMIZED COST: 140.955
(Pork-Economy, 8.000)
(Pork-Premium, 15.000)
(Wheat-Economy, 5.125)
(Wheat-Premium, 3.750)
(Starch-Economy, 4.375)
(Starch-Premium, 6.250)

You can't do that. You can't directly model expr1 >= expr2. Instead you have to model (expr1 - expr2) >= 0. There is an example on the ojAlgo wiki describing how to model a similar problem: https://github.com/optimatika/ojAlgo/wiki/The-Diet-Problem

Related

Using abstract with Binary Search in Kotlin

I have a task in kotlin to use an abstract class, and the example was about binary search
so it shows an error message in the run.
first class is non
first class there's a non abstract class but it a parent class
second an abstract class the inherite the parent classes
third a class that display the operation
and that's my code:
open class BinarySearch() {
fun BinarySearchFunction(arr: Array<Int>, l: Int, r: Int, x: Int): Int {
if(r >= 1) {
var mid:Int=1+(r-1)/2
if (arr[mid] == x) {
return mid
}
if(arr[mid] > x){
return BinarySearchFunction(arr,l,mid-1,x)
}
return BinarySearchFunction(arr,mid+1,r,x)
}
return -1
}
open fun displayMassage(Massage:String){}
}
abstract class print(): BinarySearch() {
fun Function() {
var obj = BinarySearch()
var a = arrayOf<Int>(2, 3, 4, 10, 40)
var n = a.size
var x = 10
var result = obj.BinarySearchFunction(a, 0, n - 1, x)
if(result == -1)
println("Element not present")
else
println("Element found at index $result")
}
}
class display():print(){
override fun displayMassage(massage:String){
println(massage)
}
}
fun main() {
var dis=display()
dis.displayMassage("The Binary Search : ")
dis.Function()
}
You have an error in the implementation of the algorithm causing it to do infinite recursion.
I believe
var mid: Int = 1 + (r - 1) / 2
actually needs to be
var mid: Int = l + (r - 1) / 2

Kotlin - Random.nextInt Range

Aim of code: Shopping system,function which shows a matched product name from the warehouse
what is the no. range of Random.nextInt() if no no. is assigned inside ()?
in fun fillWarehouse, if i do not set no. inside "StockUnit(Random.nextInt(),Random.nextInt())", when i call println("Number of items: ${p.availableItems}") in main, No. -890373473 / 1775292982 etc. were generated.
if i set 100 inside like "StockUnit(Random.nextInt(100),Random.nextInt(100))", No. 263 / 199 etc. were generated. why is it not within 0-100? may i know how to change my code, so that "Number of items" is within 100?
any links or topics should i work for, to write better code?
i cannot find the answers from https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.random/
Sincere thanks!
fun main(args: Array<String>) {
val warehouse = Warehouse()
...
println("Show info")
showInfo(warehouse)
}
fun showInfo(warehouse: Warehouse) {
println("Get Info")
val input = readLine() ?: "-"
val p = warehouse.getProductByName(input)
if (p != null) {
println("Product: $p")
println("Number of items: ${p.availableItems}")
println("Profit: ${p.profitPerItem}")
}
}
class Warehouse {
private val products = mutableListOf<Product>()
...
fun getProductByName (productName: String): Product? {
for (prod in products)
if (prod.productName == productName) return prod
return null
}
fun fillWarehouse (productName: String,
basePrice: Double,
productDescription: String,
chargeOnTop: Double = 50.0,
intialStockUnits: Int = 3) {
val newProduct = Product(productName, basePrice, basePrice * (1 + chargeOnTop / 100), productDescription)
//add quantity, daysBeforeExpiration
for (i in 1 .. intialStockUnits){
val unit = StockUnit(Random.nextInt(),Random.nextInt() )
newProduct.addStock(unit)
}
open class Product(
val productName: String,
var basePrice: Double,
open val salesPrice: Double,
val description: String) {
...
var stockUnits = mutableListOf<StockUnit>()
...
// availableItems = Total of stockUnits
var availableItems: Int = 0
get() = stockUnits.sumBy { it.quantity }
}
class StockUnit(var quantity:Int, var daysBeforeExpiration:Int){
...
}

Is there a function to search in a ArrayList from a position?

I read carefully the ArrayList documentation in Kotlin and apparently there is no way to search a value in ArrayList starting from a pointer. The alternative is write your own function iterating the right elements in ArrayList and testing the condition.
So I've programmed the following code:
fun <T> ArrayList<T>.findNext(cond: (T) -> Boolean, p: Int = 0): Int {
for (i in p..this.lastIndex)
if (cond(this[i])) return i
return -1
}
data class Person (
var name: String,
var age: Int
)
fun main() {
var v = arrayListOf<Person>()
v.add(Person("Paul", 22))
v.add(Person("Laura", 24))
v.add(Person("Paul", 50))
v.add(Person("Mary", 24))
println(v.findNext({it.name=="Paul"})) // 0
println(v.findNext({it.name=="Paul"}, 1)) // 2
println(v.findNext({it.name=="Paul"}, 3)) // -1
}
Is there something better than this?
You can avoid any intermediate collections:
inline fun <T> List<T>.findNext(p: Int = 0, cond: (T) -> Boolean) =
listIterator(p).withIndex().asSequence().find { cond(it.value) }?.let { it.index + p }
By swapping the arguments you can call it like this:
println(v.findNext {it.name=="Paul"}) // 0
println(v.findNext(1) {it.name=="Paul"}) // 2
println(v.findNext(3) {it.name=="Paul"}) // null
fun main() {
var v = arrayListOf<Person>()
v.add(Person("Paul", 22))
v.add(Person("Laura", 24))
v.add(Person("Paul", 50))
v.add(Person("Mary", 24))
println(v.findNext({ it.name == "Paul" },0))//IndexedValue(index=0, value=Person(name=Paul, age=22))
println(v.findNext({ it.name == "Paul" },2))//IndexedValue(index=2, value=Person(name=Paul, age=50))
println(v.findNext({ it.name == "Paul" },3))//null
}
private fun <T> List<T>.findNext(cond: (T) -> Boolean, position: Int): IndexedValue<T>? {
return withIndex().filter { it.index >= position }.firstOrNull { cond(it.value) }
}
maybe use withIndex and a filter ?
val arrayNames = listOf<String>("Paul", "Ann", "Paul", "Roger","Peter")
arrayNames.withIndex().filter {
it.value == "Paul" //value contains the original name
}.forEach{
println(it.index) //indext contains the position.
}
this will give you the output 0 and 2
for your case (person object instead of String) you will use
it.value.name == "Paul"

List<List<Char>> + List<Char> = List<Any>?

I have a below code which works.
class ListManipulate(val list: List<Char>, val blockCount: Int) {
val result: MutableList<List<Char>> = mutableListOf()
fun permute(sequence: List<Int> = emptyList(), start: Int = 0, count: Int = blockCount) {
if (count == 0) {
result.add(constructSequence(sequence))
return
}
for (i in start .. list.size - count) {
permute(sequence + i, i + 1, count - 1)
}
}
private fun constructSequence(sequence: List<Int>): List<Char> {
var result = emptyList<Char>()
for (i in sequence) {
result += list[i]
}
return result
}
}
However, when I change the result from MutableList to normal List, i.e.
var result: List<List<Char>> = emptyList()
// ...
result += constructSequence(sequence)
I got this error Type mismatch. Require: List<List<Char>>; Found: List<Any>
The full code as below
class ListManipulate(val list: List<Char>, val blockCount: Int) {
var result: List<List<Char>> = emptyList()
fun permute(sequence: List<Int> = emptyList(), start: Int = 0, count: Int = blockCount) {
if (count == 0) {
result += constructSequence(sequence)
return
}
for (i in start .. list.size - count) {
permute(sequence + i, i + 1, count - 1)
}
}
private fun constructSequence(sequence: List<Int>): List<Char> {
var result = emptyList<Char>()
for (i in sequence) {
result += list[i]
}
return result
}
}
Why result + constructSequence(sequence) would result in List<Any> instead of List<List<Char>>?
Is there a way I could still use the normal List> and not the mutable list?
CTRL + click on the + in IDEA, you'll see that it takes you to the following function:
/**
* Returns a list containing all elements of the original collection and then all elements of the given [elements] collection.
*/
public operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T> {
/* ... */
}
Which means that you add all the individual elements of elements to the receiver. That is, you'll add all T's to the List<List<T>>. Since List<T> is not T, you'll get List<Any> as a result.
The problem is that += is overloaded. If it sees an Iterable, Array or Sequence it behaves differently. You have to explicitly use plusElement() to achieve the behaviour you intend.
Consider the following code.:
class ListManipulate(val list: List<Char>, val blockCount: Int) {
var result: List<List<Char>> = emptyList()
fun permute(sequence: List<Int> = emptyList(), start: Int = 0, count: Int = blockCount) {
if (count == 0) {
result = result.plusElement(constructSequence(sequence))
return
}
for (i in start..list.size - count) {
permute(sequence + i, i + 1, count - 1)
}
}
private fun constructSequence(sequence: List<Int>): List<Char> =
List(sequence.size, { i -> list[sequence[i]] })
}
PS: I also took the liberty to update your constructSequence() to something more concise.
Btw: += uses addAll internally.
/**
* Returns a list containing all elements of the original collection and then all elements of the given [elements] collection.
*/
public operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T> {
if (elements is Collection) {
val result = ArrayList<T>(this.size + elements.size)
result.addAll(this)
result.addAll(elements)
return result
} else {
val result = ArrayList<T>(this)
result.addAll(elements)
return result
}
}
Side note: you can also do:
result.toMutableList().add(constructSequence(sequence))
It is fine to return a MutableList, the only difference really is that the List interface doesnt have the manipulation methods. Internally both are represented by an ArrayList
#SinceKotlin("1.1")
#kotlin.internal.InlineOnly
public inline fun <T> List(size: Int, init: (index: Int) -> T): List<T> = MutableList(size, init)

Multidimensional '3D' Matrix in Kotlin

What will be the syntax of creating a 3D matrix in Kotlin. It's Java equivalent is as follows:
public static final int[][][] data = {{{0,0},{0}},{{0,1},{0}},{{1,0},{0}},{{1,1},{1}}};
Thanks
Edit:
Also how can I print the Kotlin code using the simple println?
When working with arrays in most languages I find it nice to create a helper class, rather than working directly with an int[][][] type. This way you can ensure certain invariants hold (such as all rows having the same length), and ensure better data locality. It can also let you efficiently implement certain operations such as slicing, sub-matrices, transpose etc.
My usual set of classes would look something like this for 3D. (though I'd probably template on the stored type, rather than hard code it for Int)
Its pretty incomplete, but the main at the end shows how many of the functions work.
But to show how you can create a 3D array from values you can do
val V = /* .. as in mEQ5aNLrK3lqs3kfSa5HbvsTWe0nIu's answer */
val M = Matrix3D(NX,NY,NZ).transform( { v, ix, iy, iz -> V[ix][iy][iz] } )
Further examples are
fun main(args: Array<String>) {
// Create an empty matrix
val v = Matrix3D(4,4,2);
// We can access elements via [a,b,c] or [a][b][c]
v[0,1,1] = 7;
print(v)
println("v[0,1,1]=" + v[0,1,1])
println("v[0][1][1]=" + v[0][1][1])
println("-----")
// Make the matrix a little more interesting
v.transform({ w,ix,iy,iz -> ix+iy+iz})
print(v)
println("-----")
// Transform just the slice with ix=2
// Slices are fast, as they copy no elements.
// but if you change them you change the original
v[2].transform({w,iy,iz -> w+3})
print(v)
// If you dont want to change the original you can always
// create an independent copy
print(v[2].bake().transform({w,iy,iz -> w-3}))
println("-----")
// W is the slice of v with ix=0
// Can easily extend the slicing options to allow slicing along
// any axis - I'd like to add v[_,1,_] to mean the slice with iy=1
// but I've not got to that yet.
val W = v[0]
print("W=\n")
print(v[0])
print("W^T=\n")
// Fast transpose, no elements are copied.
val WT=v[0].transpose()
print(WT)
// Changing the transpose slice writes back into the original
WT[1,1]=5
print(V)
}
fun print(M:Matrix3D) {
for(iz in 0..(M.nz-1)) {
for(iy in 0..(M.ny-1)) {
for(ix in 0..(M.nx-1)){
print("%d ".format(M[ix,iy,iz]))
}
print("\n")
}
print("\n")
}
}
fun print(M:Matrix2D) {
for(iy in 0..(M.ny-1)) {
for(ix in 0..(M.nx-1)){
print("%d ".format(M[ix,iy]))
}
print("\n")
}
}
The library code looks like this:
class Matrix1D(
val v:Array<Int>,
val nx:Int,
val offset:Int,
val xstride:Int) {
// TODO: Check that the nx,offset,strides etc are valid
constructor(nx:Int) : this(Array(nx,{i->0}), nx, 0, 1) {
}
fun offsetof(ix:Int):Int {
return offset + ix*xstride
}
operator fun get(ix:Int): Int {
return v[offsetof(ix)]
}
operator fun set(ix:Int, v:Int) {
this.v[offsetof(ix)] = v
}
fun reverse() : Matrix1D {
return Matrix1D(v, nx, offsetof(nx-1), -xstride)
}
fun submatrix(startx:Int, newNX:Int) : Matrix1D {
return Matrix1D(v,newNX,offsetof(startx), xstride)
}
fun transform(body: (Int, Int) -> Int ) {
for(ix in 0..(nx-1)){
this[ix] = body(this[ix], ix)
}
}
fun bake() : Matrix1D {
val rv = Matrix1D(nx);
for(ix in 0..(nx-1)) {
rv[ix] = this[ix]
}
return rv
}
}
class Matrix2D(
val v:Array<Int>,
val nx:Int, val ny:Int,
val offset:Int,
val xstride:Int, val ystride:Int) {
// TODO: Check that the nx,ny,offset,strides etc are valid
constructor(nx:Int, ny:Int) : this(Array(nx*ny,{i->0}), nx, ny, 0, 1, nx ) {
}
fun offsetof(ix:Int,iy:Int): Int {
return offset + ix*xstride + iy*ystride
}
operator fun get(ix:Int,iy:Int): Int {
return v[offsetof(ix,iy)]
}
operator fun set(ix:Int,iy:Int,v:Int) {
this.v[offsetof(ix,iy)] = v
}
operator fun get(ix:Int): Matrix1D {
return Matrix1D(v, ny, offsetof(ix,0), ystride)
}
fun transpose(): Matrix2D {
return Matrix2D(v,ny,nx,offset,ystride,xstride)
}
fun submatrix(startx:Int, starty:Int, newNX:Int, newNY:Int) : Matrix2D {
return Matrix2D(v,newNX,newNY,offsetof(startx,starty), xstride, ystride)
}
fun transform(body: (Int, Int, Int) -> Int ) {
for(iy in 0..(ny-1)) {
for(ix in 0..(nx-1)){
this[ix,iy] = body(this[ix,iy], ix,iy)
}
}
}
fun bake() : Matrix2D {
val rv = Matrix2D(nx,ny);
for(ix in 0..(nx-1)) {
for(iy in 0..(ny-1)) {
rv[ix,iy] = this[ix,iy]
}
}
return rv
}
}
class Matrix3D(
val v:Array<Int>,
val nx:Int, val ny:Int, val nz:Int,
val offset:Int,
val xstride:Int, val ystride:Int, val zstride:Int) {
// TODO: Check that the nx,ny,nz,offset,strides etc are valid
constructor(nx:Int, ny:Int, nz:Int) : this(Array(nx*ny*nz,{i->0}), nx, ny, nz, 0, 1, nx, nx*ny ) {
}
operator fun get(ix:Int,iy:Int,iz:Int): Int {
return v[offset + ix*xstride + iy*ystride + iz*zstride]
}
operator fun set(ix:Int,iy:Int,iz:Int, v:Int) {
this.v[offset + ix*xstride + iy*ystride + iz*zstride] = v
}
operator fun get(ix:Int): Matrix2D {
return Matrix2D(v, ny, nz, offset + ix*xstride, ystride, zstride )
}
fun transform(body: (Int, Int, Int, Int) -> Int ) {
for(iz in 0..(nz-1)) {
for(iy in 0..(ny-1)) {
for(ix in 0..(nx-1)){
this[ix,iy,iz] = body(this[ix,iy,iz], ix,iy,iz)
}
}
}
}
fun bake() : Matrix3D {
val rv = Matrix3D(nx,ny,nz);
for(ix in 0..(nx-1)) {
for(iy in 0..(ny-1)) {
for(iz in 0..(nz-1)){
rv[ix,iy,iz] = this[ix,iy,iz]
}
}
}
return rv
}
}
Kotlin currently does not support array literals.
You can use a combination of arrayOf() and intArrayOf():
val data = arrayOf(
arrayOf(intArrayOf(0, 0), intArrayOf(0)),
arrayOf(intArrayOf(0, 1), intArrayOf(0)),
arrayOf(intArrayOf(1, 0), intArrayOf(0)),
arrayOf(intArrayOf(1, 1), intArrayOf(1))
)
You can cut down a little bit on the verbosity using import aliasing if needed:
import kotlin.arrayOf as arr
import kotlin.intArrayOf as iarr
val data = arr(
arr(iarr(0, 0), iarr(0)),
arr(iarr(0, 1), iarr(0)),
arr(iarr(1, 0), iarr(0)),
arr(iarr(1, 1), iarr(1))
)
Also note that you can auto-convert Java code to Kotlin
in IntelliJ IDEA: copy Java code into a Kotlin file, a confirmation prompt will open.
online: using http://try.kotlinlang.org.
Using Multik
Multik Multidimensional array library for Kotlin.
Syntax for creating 3D array
mk.d3array(2, 2, 3) { it * it }
//output
/*[[[0, 1, 4],
[9, 16, 25]],
[[1, 0, 0],
[1, 1, 1]]]
*/
Note:Multik supports up to 4 dimensions
The Multik project’s GitHub repository
For more info check Jetbrain blog post