how can I sort parameters in pyomo? - sorting

I am working with the Pyomo package(for mathematical modeling in python).I have a parameter defined as: model.D=Param(model.t,model.i) .this is a multi-dimensional parameter. t is for the range of time periods, i is for the range of instances and D is the value of the demand. how can I sort this parameter by its value and get the corresponding t and i ?

Do all that data cleaning/sorting stuff with basic python before you build the model. Part of this answer depends on the original format of the data and the format you'd like your answer in, but I think the overall gist is clear....
Code
import pyomo.environ as pyo
d = { 0: [1.2, 3.1, 0.5],
1: [9.5, 2.0, 3.1] }
# a good format to pass in to a parameter, tuple-indexed dictionary
d_data = {(t, i): d[t][i] for t in d for i in range(len(d[t]))}
# now let's sort the values in d for the missing info on order
d_tuples = {t: sorted([(val, idx) for idx, val in enumerate(d[t])]) for t in d}
d_sorted = {t: [temp[1] for temp in d_tuples[t]] for t in d}
print(d_data)
print(d_tuples)
print(d_sorted)
# now set up the model...
m = pyo.ConcreteModel()
m.T = pyo.Set(initialize=d.keys())
m.I = pyo.Set(initialize=list(range(len(d[0])))) # assumes all d[t] are equal length
m.D = pyo.Param(m.T, m.I, initialize=d_data)
m.pprint()
Yields:
{(0, 0): 1.2, (0, 1): 3.1, (0, 2): 0.5, (1, 0): 9.5, (1, 1): 2.0, (1, 2): 3.1}
{0: [(0.5, 2), (1.2, 0), (3.1, 1)], 1: [(2.0, 1), (3.1, 2), (9.5, 0)]}
{0: [2, 0, 1], 1: [1, 2, 0]}
3 Set Declarations
D_index : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : T*I : 6 : {(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)}
I : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 3 : {0, 1, 2}
T : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {0, 1}
1 Param Declarations
D : Size=6, Index=D_index, Domain=Any, Default=None, Mutable=False
Key : Value
(0, 0) : 1.2
(0, 1) : 3.1
(0, 2) : 0.5
(1, 0) : 9.5
(1, 1) : 2.0
(1, 2) : 3.1
4 Declarations: T I D_index D

Related

trax tl.Relu and tl.ShiftRight layers are nested inside Serial Combinator

I am trying to build an attention model but Relu and ShiftRight layer by default nested inside the Serial Combinator.
This further gives me errors in training.
layer_block = tl.Serial(
tl.Relu(),
tl.LayerNorm(), )
x = np.array([[-2, -1, 0, 1, 2],
[-20, -10, 0, 10, 20]]).astype(np.float32)
layer_block.init(shapes.signature(x)) y = layer_block(x)
print(f'layer_block: {layer_block}')
Output
layer_block: Serial[
Serial[
Relu
]
LayerNorm
]
Expected Output
layer_block: Serial[
Relu
LayerNorm
]
The same problem arises with tl.ShiftRight()
The code above is taken from official documentation Example 5
Thanks in advance
I could not found the exact solution to the above problem, but you can create a custom Function using tl.Fn() and add the Relu and ShiftRight function code in it.
def _zero_pad(x, pad, axis):
"""Helper for jnp.pad with 0s for single-axis case."""
pad_widths = [(0, 0)] * len(x.shape)
pad_widths[axis] = pad # Padding on axis.
return jnp.pad(x, pad_widths, mode='constant')
def f(x):
if mode == 'predict':
return x
padded = _zero_pad(x, (n_positions, 0), 1)
return padded[:, :-n_positions]
# set ShiftRight parameters as global
n_positions = 1
mode='train'
layer_block = tl.Serial(
tl.Fn('Relu', lambda x: jnp.where(x <= 0, jnp.zeros_like(x), x)),
tl.LayerNorm(),
tl.Fn(f'ShiftRight({n_positions})', f)
)
x = np.array([[-2, -1, 0, 1, 2],
[-20, -10, 0, 10, 20]]).astype(np.float32)
layer_block.init(shapes.signature(x))
y = layer_block(x)
print(f'layer_block: {layer_block}')
Output
layer_block: Serial[
Relu
LayerNorm
ShiftRight(1)
]

Assign + or - sign to the first n natural numbers to get the given value

Given the first 9 natural numbers we have to assign + or - sign to each number such that the sum of the resulting sequence is equal to the required number.
For example, we are given the first 9 natural numbers {1,2,3,4,5,6,7,8,9} and have to get the value 1.
The output can be {1,-2,3,4,-5,-6,7,8,-9} or any one of the other possibilities.
if the value is -5, then the output can be {-1,-2,-3,4,-5,-6,7,-8,9}.
We know that the sum will always be odd.
I am unable to come up with an algorithm that could solve this problem.
My idea was to use a greedy approach.(we can assume the sequence is sorted)
Start from the largest value (right side of the sequence).
Sum the numbers till current index.
Check if the sum of sequence is lower than absolute value of the target number.
If yes, then assign the + to the number at the current index otherwise a -.
Repeat till we reach the first number.
Based on my algorithm the output for,
1 is {1 -2 3 4 -5 6 -7 8 -9}
15 is {1 2 -3 4 -5 6 7 -8 9}. Giving me the sum of the sequence as 13 (completely wrong).
Here is my code,
public static int[] sequenceOfSigns(int[] num, int sum) {
int n = num[num.length - 1];
int upperBound = (n * (n + 1)) / 2;
if (sum % 2 == 0 || sum < -upperBound || sum > upperBound)
return null;
int tempSum = 0;
for (int i = num.length - 1; i >= 0; i--) {
tempSum += num[i];
boolean flag;
if (i != 0)
flag = tempSum >= Math.abs(sum);
else
flag = tempSum > Math.abs(sum);
if (flag) {
num[i] = -num[i];
tempSum += num[i] * 2;
}
}
return num;
}
Any ideas on how to modify the algorithm would be greatly appreciated.
Additionally can we extend the problem to n natural numbers? or is it an NP-problem?
EDIT
I have solved this problem another way.
Here is the solution with proof that was inspired by my brother's suggestion on how to solve the problem. His suggestion is superbly elegant.
My Proof
Given a sequence of natural numbers {1,2,3,4,5,6,7,8,9} and an odd target sum of x; we are to modify the sign(+/-) of the numbers in the sequence such that the sum of the elements equals the target number.
Let A = {1,2,3,4,5,6,7,8,9}
x is the target number (odd).
Let us consider a set S which contains all the elements of A that should be made negative.
Then we have the relation,
Sum of all elements in A - (2 * Sum of all elements in S) = |x|
[This is the key idea suggested by my brother]
Rearranging the equation we get,
Sum of all elements in S = (Sum of all elements in A - |x|)/2 .... (1)
Now, we select the largest value in A which is lesser than or equal to the sum in (1).
We subtract this from the sum in (1).
We perform this operation, iteratively, till the sum in (1) becomes 0.
A point to note is that each value from A can only be selected once.
This is our greedy algorithm.
This choice of largest element in A which is lesser than or equal to the sum at each step is a safe greedy choice. Since, the selected values will form the set of numbers which should be negative the sum of the selected values and the sum in (1) should be same.
Now, if we select a value greater than the sum in (1) the difference would be a negative value and that is a contradiction. Hence, we cannot select a greater value.
If we arbitrarily choose any value that is lesser than or equal to the sum in (1), the difference is positive or 0. We can easily replace the selected value with the largest value that satisfies the conditions and the constraints are still obeyed. So, our choice is a safe choice.
The values selected in the previous step form the set S.
and our required sequence is the ordered set formed from the set,
(A - S) U -(elements in S)
If x is negative we simply flip the signs in the ordered set obtained above. Since, the solutions for x and -x are symmetric.
This concludes our proof and solution for the greedy algorithm
CODE
public static int[] sequenceOfSigns(int[] num, int sum) {
int n = num[num.length - 1];
int upperBound = (n * (n + 1)) / 2;
if (sum % 2 == 0 || sum < -upperBound || sum > upperBound)
return null;
int negativeSeqSum = (upperBound - Math.abs(sum)) / 2;
for (int i = num.length - 1; i >= 0; i--) {
if (num[i] <= negativeSeqSum) {
negativeSeqSum -= num[i];
num[i] = -num[i];
}
if (negativeSeqSum == 0)
break;
}
if (sum == -Math.abs(sum))
for (int i = 0; i < num.length; i++)
num[i] = -num[i];
return num;
}
You could solve this by using the following intuition:
Any number could get a + or - sign.
Lets say the last number is 'n' and you could mark it positive or negative
If you mark it positive:
Then remaining sum is S - n and you have to solve the problem for n-1 numbers and target sum = S - n
If you mark it negative:
Then remaining sum is S + n and you have to solve the problem for n-1 numbers and target sum = S + n
Therefore you could write the following recursion:
isPossible(N, S) = isPossible(N-1, S-N) || isPossible(N-1, S+N)
You could memoize the solution at each combination of (N, S) and store the result in a map of
Pair ( N, S) => Boolean
Now from the map you could go through the pairs which have true values i.e. ( for the pair's 'N' numbers it is possible to get sum equal to the pair's S) and get the appropriate signs like below example :
The map for the case N = 9 and S = -5 looks like:
{(1, -31)=false, (2, -33)=false, (6, -29)=false, (2, -37)=false, (5, -35)=false, (4, -4)=true, (2, -41)=false, (3, -10)=false, (3, -14)=false, (4, -16)=false, (3, -18)=false, (3, -22)=false, (3, -26)=false, (7, -22)=true, (4, -28)=false, (3, -30)=false, (1, -1)=true, (3, -34)=false, (2, -3)=true, (1, -5)=false, (2, -7)=false, (1, -9)=false, (4, -40)=false, (1, -49)=false, (2, -11)=false, (1, -13)=false, (5, -9)=true, (9, -5)=true, (1, -45)=false, (2, -15)=false, (1, -17)=false, (1, -41)=false, (2, -19)=false, (6, -15)=true, (1, -21)=false, (1, -37)=false, (2, -23)=false, (1, -25)=false, (5, -21)=false, (1, -33)=false, (2, -27)=false, (1, -29)=false, (2, -31)=false, (3, 0)=true, (2, -35)=false, (2, -39)=false, (3, -8)=false, (3, -12)=false, (2, -47)=false, (4, -14)=false, (4, -18)=false, (8, -14)=true, (3, -20)=false, (3, -24)=false, (4, -26)=false, (4, -30)=false, (3, -32)=false, (1, -3)=false, (3, -36)=false, (2, -5)=false, (1, -7)=false, (2, -9)=false, (1, -11)=false, (3, -44)=false, (2, -13)=false, (1, -15)=false, (1, -43)=false, (2, -17)=false, (1, -19)=false, (1, -39)=false, (2, -21)=false, (1, -23)=false, (1, -35)=false, (2, -25)=false, (1, -27)=false, (5, -23)=false, (2, -29)=false}
Start with the key = Pair(9, -5) is it there in the map with a value of "true"?
Yes it is there, now look for two possibilities : Pair(8, -5-9) or Pair(8, -5+9)
It turns out that Pair(8, -14) exists, so you need to add +9 to the list because you need to look for S - n i.e. you are subtracting n from the remaining S you are looking for. Then update S = S- n = -5 - 9 = -14.
Now look for two possiblities : Pair(7, -14-8) or Pair(7, -14+8). It turns out that Pair(7, -22) exists, so you need to add +8 to the list because you need to look for S - n which means you subtracted n = 8 from the remaining S you are looking for. Then update S = S - n = -14 - 8 = -22
....
....
The final result will be [-1, -2, 3, -4, -5, -6, -7, 8, 9]
Code is - ( you can play with the code here by modifying N, S)
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class Main {
private static Map<Pair, Boolean> map = new HashMap<>();
public static void main(String... args) {
int N = 9;
int S = -5;
Integer[] result = sequenceOfSigns(N, S);
System.out.println(("Input = " + N + ", " + S + " : ") + ( result == null ? "Not possible" : Arrays.toString(result)));
S = 15;
result = sequenceOfSigns(N, S);
System.out.println(("Input = " + N + ", " + S + " : ") + ( result == null ? "Not possible" : Arrays.toString(result)));
S = 45;
result = sequenceOfSigns(N, S);
System.out.println(("Input = " + N + ", " + S + " : ") + ( result == null ? "Not possible" : Arrays.toString(result)));
S = -45;
result = sequenceOfSigns(N, S);
System.out.println(("Input = " + N + ", " + S + " : ") + ( result == null ? "Not possible" : Arrays.toString(result)));
S = 4;
result = sequenceOfSigns(N, S);
System.out.println(("Input = " + N + ", " + S + " : ") + ( result == null ? "Not possible" : Arrays.toString(result)));
}
public static Integer[] sequenceOfSigns(int N, int sum) {
boolean isPossible = helper(N, sum);
if ( isPossible ) {
int s = sum;
List<Integer> res_list = new ArrayList<>();
for ( int n = N; n >= 1; n-- ) {
Pair p = new Pair(n, s);
if ( n == 1 ) {
res_list.add(s);
} else if ( map.containsKey(p) && map.get(p) ) {
Pair p1 = new Pair(n-1, s+n);
Pair p2 = new Pair(n-1, s-n);
if (map.containsKey(p1)) {
res_list.add(-n);
s = s + n;
} else if ( map.containsKey(p2)) {
res_list.add(n);
s = s - n;
}
}
}
Collections.reverse(res_list);
if ( !res_list.isEmpty() ) return res_list.toArray(new Integer[] {});
}
return null;
}
private static boolean helper(int N, int S) {
if ( N == 0 ) return S == 0;
Pair p = new Pair(N, S);
if ( map.containsKey(p) ) {
return map.get(p);
}
boolean val = helper(N-1, S - N) || helper(N-1, S + N);
map.put(p, val);
return val;
}
static class Pair {
int N, S;
public Pair(int N, int S) {
this.N = N;
this.S = S;
}
#Override
public boolean equals(Object obj) {
if ( obj instanceof Pair ) {
Pair other = (Pair)obj;
return other.N == N && other.S == S;
}
return false;
}
#Override
public int hashCode() {
return 31*31*N + 31*S;
}
#Override
public String toString() {
return "(" + N + ", " + S + ")";
}
}
}
Output:
Input = 9, -5 : [-1, -2, 3, -4, -5, -6, -7, 8, 9]
Input = 9, 15 : [-1, -2, -3, -4, -5, 6, 7, 8, 9]
Input = 9, 45 : [1, 2, 3, 4, 5, 6, 7, 8, 9]
Input = 9, -45 : [-1, -2, -3, -4, -5, -6, -7, -8, -9]
Input = 9, 4 : Not possible
There are 2^9 = 512 possibilities. Why not brute force?
var hash = {0: [[]]};
for (let i=1; i<=9; i++){
let new_hash = {};
for (let _sum in hash){
let sum = Number(_sum);
let new_sum = sum + i;
if (new_sum in new_hash)
new_hash[new_sum] = new_hash[new_sum].concat(hash[sum].map(x => x.concat(i)));
else
new_hash[new_sum] = hash[sum].map(x => x.concat(i));
new_sum = sum - i;
if (new_sum in new_hash)
new_hash[new_sum] = new_hash[new_sum].concat(hash[sum].map(x => x.concat(-i)));
else
new_hash[new_sum] = hash[sum].map(x => x.concat(-i));
}
hash = new_hash;
}
console.log(JSON.stringify(hash[1]));
console.log('');
console.log(JSON.stringify(hash[15]));

Turning a Matrix into a Vector

This might be more of a mathematical question, but it's for use in a code.
Suppose you have a N x N grid, or matrix. If you wanted to somehow "stretch it", turning it into an array of sorts, such that now every element is to the right or left of each other, like in a vector. But you would like to keep referring to each element by their original reference -- that is row and col. What you would do is divide it's index in the vector by N. It's row would be index//N and column, index % N.
My question is: what if the grid were N x M, resulting in an array of size N*M, how would you get the corresponding position of each element in the grid?
This "stretching" is called flattening. This is almost always done in row-major or column-major order. Row-major is also known as C style where column-major is known as Fortran style.
Assuming you use row-major order to flatten a M x N matrix where M is the number of rows and N the number of columns the correct conversion expressions for row-major order are:
col = i % N
row = i / N
-----------
i = row*N + col
For column major order they are:
col = i / M
row = i % M
-----------
i = col*M + row
Both are assuming zero-based indexing for i, col and row, as well as truncating division.
I assume by "stretch" you mean you lay the rows next to each other to form a 1-d vector as in
for a 3x4 matrix
a00 a01 a02 a03
a10 a11 a12 a13
a20 a21 a22 a23
you stretch it into 1-d vector like:
a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23
Now given k an index in the above vector, how will you get its corresponding (i,j) in the N x M grid ?
You get them by
i = k / M
j = k - i*M
where M is number of columns
You can check :
for k = 7 (a13) => i = 7/4 = 1 and j = 7 - (1*4) = 3 => (1,3)
for k = 1 (a01) => i = 1/4 = 0 and j = 1 - 0*4 = 1 => (0,1)
for k = 9 (a21) => i = 9/4 = 2 and j = 9 - 2*4 = 1 => (2,1)
An example code in Java is like below:
private static void printPositions(int N, int M) {
int count = 0;
for ( int k = 0; k < N*M; k++ ) {
int i = k/M;
int j = k - i*M;
System.out.print( "(" + i + ", " + j + ")" + " " );
count++;
if ( count == M ) {
System.out.println();
count = 0;
}
}
}
And output for different values of N and M is:
printPositions(3, 4) :
(0, 0) (0, 1) (0, 2) (0, 3)
(1, 0) (1, 1) (1, 2) (1, 3)
(2, 0) (2, 1) (2, 2) (2, 3)
printPositions(4, 6) :
(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5)
(1, 0) (1, 1) (1, 2) (1, 3) (1, 4) (1, 5)
(2, 0) (2, 1) (2, 2) (2, 3) (2, 4) (2, 5)
(3, 0) (3, 1) (3, 2) (3, 3) (3, 4) (3, 5)
printPositions(1, 5) :
(0, 0) (0, 1) (0, 2) (0, 3) (0, 4)
Just define a mapping function, that takes a position in a NxM matrix and convert it to a position in the vector:
MATRIX CORRESPONDING VECTOR
| 0 1
--|------ 0 1 2 3 4 5
0 | 7 2 -------------
1 | 1 9 => 7 2 1 9 5 6
2 | 5 6
The mapping function can be f(x, y) = y * N + x.
Example 1
element 1 (position x = 0, y = 1)
f(0, 1) = y * N + x = 1 * 2 + 0 = 2.
1 should be in position 2 of the vector
Example 2
element 6 (position x = 1, y = 2)
f(0, 1) = y * N + x = 2 * 2 + 1 = 5.
6 should be in position 5 of the vector

SSRS expression for date difference to a number

I have this expression:
=COUNT(Fields!RecId.Value) -
IIF(Fields!Status.Value="Assigned",
DATEDIFF("d", Fields!CreatedDateTime.Value,Fields!ResolvedDateTime.Value),
DATEDIFF("d", Fields!CreatedDateTime.Value,Fields!AssignedDateTime.Value))
- IIF(Weekday(Parameters!StartDate.Value, 1) = 1, 1, 0)
- IIF(Weekday(Parameters!StartDate.Value, 1) = 7, 1, 0)
- IIF(Weekday(Parameters!EndDate.Value, 1) = 1, 1, 0)
- IIF(Weekday(Parameters!EndDate.Value, 1) = 7, 1, 0)
What I want to be able to return is the RecID value minus the date difference if the date is more than 1 day.
From the comment, it seems like you want the count of records minus the number of records where the work days between the Created Date and if Status is "Assigned" the Resolved Date else the Assigned Date.
=COUNT(Fields!RecId.Value) -
SUM(
IIF(Fields!Status.Value = "Assigned",
IIF(DATEDIFF("d", Fields!CreatedDateTime.Value, Fields!ResolvedDateTime.Value)
- (DateDiff(DateInterval.WeekOfYear, Fields!CreatedDateTime.Value, Fields!ResolvedDateTime.Value)*2)
- (IIF(WEEKDAY(Fields!CreatedDateTime.Value) = 7, 1, 0)
- (IIF(WEEKDAY(Fields!ResolvedDateTime.Value) = 6, 1, 0))
- 1) > 1, 0, 1)
,
IIF(DATEDIFF("d", Fields!CreatedDateTime.Value, Fields!AssignedDateTime.Value) > 1, 0, 1)
- (DateDiff(DateInterval.WeekOfYear, Fields!CreatedDateTime.Value, Fields!AssignedDateTime.Value) * 2)
- (IIF(WEEKDAY(Fields!CreatedDateTime.Value) = 7, 1, 0)
- (IIF(WEEKDAY(Fields!AssignedDateTime.Value) = 6, 1, 0))
- 1) > 1, 0, 1)
)

Pattern recognition in binary numbers (pseudo code or MQL5)

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
. . 1 1 1 1 1 0 0 0 1 1 1 1 1 0 0 0
Recognition starts at 17 and goes backwards to 0.
What can be seen is the most simple pattern.
Pattern starts with at least three 0s or three 1s but could be more of each but not mixed!
First pattern is then followed by at least five 0s or five 1s depending on what came in the first pattern. Since pattern one contains three 0, there must be at least five 1s and vice versa
Then we want to see the first pattern again. At least three 0s or three 1s, again, depending wheather there were 1s or 0s before
Finally we want to see the second pattern again, which means at least five 0s or five 1s, again, depending on which pattern was seen before
I tried using for loops and counters but did not manage to work it out. What is struggling me is the fact, that the pattern is not of fixed size as there can be more than three or five 0s and 1s in succession.
Is anybody able to provide some pseudo code how to implement this or even some MQL5 code?
The following Swift code is everything else than optimal. It should just give you hints how you could implement it.
A function to match a single pattern:
func matchPattern(numbers: [Int], startIndex: Int, number: Int) -> Int {
var actualIndex = startIndex
while numbers[actualIndex] == number && actualIndex > 0 {
actualIndex = actualIndex - 1
}
return startIndex - actualIndex
}
A function to match the 4 patterns:
func match(binNrs: [Int]) -> Bool {
let firstPatternNr = binNrs[17]
let secondPatternNr = firstPatternNr == 0 ? 1 : 0
let pattern1Length = matchPattern(numbers: binNrs,
startIndex: 17,
number: firstPatternNr)
if pattern1Length < 3 { return false }
let pattern2Length = matchPattern(numbers: binNrs,
startIndex: 17 - pattern1Length,
number: secondPatternNr)
if pattern2Length < 5 { return false }
let pattern3Length = matchPattern(numbers: binNrs,
startIndex: 17 - pattern1Length - pattern2Length,
number: firstPatternNr)
if pattern3Length < 3 { return false }
let pattern4Length = matchPattern(numbers: binNrs,
startIndex: 17 - pattern1Length - pattern2Length - pattern3Length,
number: secondPatternNr)
return pattern4Length >= 5
}
Some test patterns with results:
let match1 = match(binNrs: [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0]) // true
let match2 = match(binNrs: [1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]) // false (4th sequence < 5)
let match3 = match(binNrs: [0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0]) // false (1st sequence < 3)
let match4 = match(binNrs: [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1]) // false (2nd sequence < 5)

Resources