Creating a new set from components of an existing set in OPL/CPLEX - optimization

I have a set that I have read into my OPL project that looks like this:
S = {<"A","">, <"B","">, <"AB","A">, <"AB","B">, <"C","">, <"ABC","A">,<"ABC","B">, <"ABC","C">, <"ABC","AB">},
where each element <,> is a tuple with two string elements. This set represents parent-child relationships between items of interest.
From this set I need to create a new set:
S' = {<"A",{""}>, <"B",{""}>, <"C",{""}>, <"AB",{"A","B"}>, <"ABC",{"A","B","C","AB"}>},
where each element <,> is a tuple with the first element of each tuple a string and the second element of each tuple a set of strings. My attempt at creating this set is:
tuple child{
string Item;
string Child;
}
{child} Children = ...; //Reads in the set S
tuple dependents{
string Item;
{string} ItemChildren;
}
{dependents} dependentsSet = {<x.Item, y.Child> | x in Children, (y in Children : <x,y> in Children)};
Using the variable names from the above code, the purpose of creating S' is because later in my program I need to create a collection of constraints, one for each Item, and within each constraint I need to index over the ItemChildren. I'm a relative novice with OPL so I know I'm using the syntax incorrectly in the initialization of the dependentsSet variable, but I don't know how to write this statement correctly such that it creates the set I'm looking for.
Can anyone help me understand the statements required to create the set I'm after?

tuple child{
string Item;
string Child;
}
{child} Children
= {<"A","">, <"B","">, <"AB","A">, <"AB","B">, <"C","">, <"ABC","A">,
<"ABC","B">, <"ABC","C">, <"ABC","AB">};
{string} setOfParents={i.Item | i in Children};
{string} setOfChildren={i.Child | i in Children};
tuple dependents{
string Item;
{string} ItemChildren;
}
{string} kids[p in setOfParents]={k | k in setOfChildren : <p,k> in Children};
{dependents} dependentsSet = {<x, kids[x]> | x in setOfParents};
execute
{
writeln(dependentsSet);
}
gives
{<"A" {""}> <"B" {""}> <"AB" {"A" "B"}> <"C" {""}>
<"ABC" {"A" "B" "C" "AB"}>}

Related

Restart numeration in multiple tables with docx4j

I need to create a .docx file using docx4j with many tables based on a template.
Tables must have rows with automatic numeration.
After copying table from template numeration continues in consecutive tables, like this:
table 1
List item
List item
table 2
List item
List item
How can I restart numeration for every table to obtain this:
table 1
List item
List item
table 2
List item
List item
I found that there exists NumberingDefinitionPart.restart() method that could be helpful but how can I apply it on each table?
Could you give example with java code?
For each table after the first, you need to create/add a list level override to the numbering definitions part, then use that in your numPr (ie in your "list item").
The method you mentioned does this:
/**
* For the given list numId, restart the numbering on the specified
* level at value val. This is done by creating a new list (ie <w:num>)
* which uses the existing w:abstractNum.
* #param numId
* #param ilvl
* #param val
* #return
*/
public long restart(long numId, long ilvl, long val)
throws InvalidOperationException {
// Find the abstractNumId
// (Ensure maps are initialised)
if (em == null ) {
getEmulator();
}
ListNumberingDefinition existingLnd = instanceListDefinitions.get( Long.toString(numId) );
if (existingLnd==null) {
throw new InvalidOperationException("List " + numId + " does not exist");
}
BigInteger abstractNumIdVal = existingLnd.getNumNode().getAbstractNumId().getVal();
// Generate the new <w:num
long newNumId = instanceListDefinitions.size() + 1;
org.docx4j.wml.ObjectFactory factory = Context.getWmlObjectFactory();
Num newNum = factory.createNumberingNum();
newNum.setNumId( BigInteger.valueOf(newNumId) );
AbstractNumId abstractNumId = factory.createNumberingNumAbstractNumId();
abstractNumId.setVal(abstractNumIdVal);
newNum.setAbstractNumId(abstractNumId);
LvlOverride lvlOverride = factory.createNumberingNumLvlOverride();
lvlOverride.setIlvl(BigInteger.valueOf(ilvl));
newNum.getLvlOverride().add(lvlOverride);
StartOverride start = factory.createNumberingNumLvlOverrideStartOverride();
start.setVal(BigInteger.valueOf(val));
lvlOverride.setStartOverride(start);
// Add it to the jaxb object and our hashmap
((Numbering)getJaxbElement()).getNum().add(newNum);
ListNumberingDefinition listDef
= new ListNumberingDefinition(newNum, abstractListDefinitions);
instanceListDefinitions.put(listDef.getListNumberId(), listDef);
// Return the new numId
return newNumId;
}
https://github.com/plutext/docx4j/blob/master/src/samples/docx4j/org/docx4j/samples/NumberingRestart.java is an example of using it.
In your numPr element in your w:p "list item":
<w:pPr>
<w:numPr>
<w:ilvl w:val="0"/>
<w:numId w:val="1"/>
</w:numPr>
</w:pPr>
set level (ilvl) to the level you used in the method; set numid to the value the method returns.
As noted in the sample, after the first paragraph using newNumId, it doesn't matter whether subsequent paragraphs use that or the original numId.

how to update just one element of array when updating

I have a doc like the following:
as you can see I have an array entity: {1,3,4}
Now I want to just change 4 to 10 in that array and update it for that I have the following code:
DBCollection coll = db.getCollection("test");
BasicDBObject newDocument = new BasicDBObject();
BasicDBObject searchQuery = new BasicDBObject().append("time", "20141105230000");
coll.update(searchQuery, newDocument);
String[] str = { "1", "3", "10" };
DBObject updateMatchingElem = new BasicDBObject("$set",
new BasicDBObject().append("entity", str));
coll.update(searchQuery, updateMatchingElem);
But this way is not a good way because I kind of remove entity and then insert the whole array again. Is there anyway that I can just change the one element like 4 to 10?
Now I want to just change 4 to 10 in that array and update it
You can do it in the following way, using the $ positional operator.
//db.collection.update({"entity":4},{$set:{"entity.$":10}})
DBObject find = new BasicDBObject( "entity", 4);
DBObject set = new BasicDBObject( "entity.$", 10);
DBObject update = new BasicDBObject().append("$set", set);
coll.update(find, update);
Note that you can at most update only one single matching array element, even if there are other matching elements in the array. For instance, if there are two 4s in the array, only the first occurrence of 4 will get updated. This is how the positional operator works.
Whenever you use the positional operator in the update query, the find query must contain the field in the find part of the query.

hibernate how to assign ParameterList for the IN clause

I need to use the IN clause in the SQL sentence.
I have data in one table with the type on Int(11).
And Y have a String from another table that is the criteria.
For example, in table A i have the value 3 of type Int.
In table/process B i have the String "0123".
I need to query table A to meet this criteria:
Select * from Table A where attrib_1 IN (0,1,2,3)
Because record n have value 3, it should be returned.
So i'm trying to use .setParameterList, like this:
List<BloqueCruzamiento> bloques = session.createQuery("FROM BloqueCruzamiento AS b WHERE b.anio=:anio AND b.activo=true AND b.grupo=:categoria AND b.pr IN(:pr_set)ORDER BY b.nroParcela, b.cruza, b.pedigree")
.setParameter("anio", grupo.getAnio())
.setParameter("categoria", grupo.getCategoria())
.setParameterList("pr_set", pr_parm)
.list();
the quid is on "pr_set" parameter.
I want to know how to convert a String , "0123", to a Collection of Integers (0,1,2,3).
So I can pass this parameter to setParameterList() method.
Anapproach that I'm right now is to convert the String to a Char Array, then loop, and convert each element into an Integer Array.
Can somebody give anothe solution ?
Regards
you can use code below to get list from String
String s = "0123";
List<Integer> pr_parm = new ArrayList<Integer>();
for(int i=0;i<s.length();i++) {
if (Character.isDigit(s.charAt(i))) {
pr_parm.add(Integer.parseInt(String.valueOf(s.charAt(i))));
}
}
System.out.println(pr_parm);
Then you can use the list in your setParameterList("pr_set", pr_parm)
this was the solution.
String[] sele = grupo.getPr_sel().split(",");
Integer[] pr_parm_int = new Integer[sele.length];
for (int x=0; x<sele.length;x++){
pr_parm_int[x] = Integer.valueOf(sele[x]);
}
the first line is to parse the string and strip comas.

How can I generate schema from text file? (Hadoop-Pig)

Somehow i got filename.log which looks like for example (tab separated)
Name:Peter Age:18
Name:Tom Age:25
Name:Jason Age:35
because the value of key column may differ i cannot define schema when i load text like
a = load 'filename.log' as (Name:chararray,Age:int);
Neither do i want to call column by position like
b = foreach a generate $0,$1;
What I want to do is, from only that filename.log, to make it possible to call each value by key, for example
a = load 'filename.log' using PigStorage('\t');
b = group b by Name;
c = foreach b generate group, COUNT(b);
dump c;
for that purpose, i wrote some Java UDF which seperate key:value and get value for every field in tuple as below
public class SPLITALLGETCOL2 extends EvalFunc<Tuple>{
#Override
public Tuple exec(Tuple input){
TupleFactory mTupleFactory = TupleFactory.getInstance();
ArrayList<String> mProtoTuple = new ArrayList<String>();
Tuple output;
String target=input.toString().substring(1, input.toString().length()-1);
String[] tokenized=target.split(",");
try{
for(int i=0;i<tokenized.length;i++){
mProtoTuple.add(tokenized[i].split(":")[1]);
}
output = mTupleFactory.newTupleNoCopy(mProtoTuple);
return output;
}catch(Exception e){
output = mTupleFactory.newTupleNoCopy(mProtoTuple);
return output;
}
}
}
How should I alter this method to get what I want? or How should I write other UDF to get there?
Whatever you do, don't use a tuple to store the output. Tuples are intended to store a fixed number of fields, where you know what every field contains. Since you don't know that the keys will be in Name,Age form (or even exist, or that there won't be more) you should use a bag. Bags are unordered sets of tuples. They can have any number of tuples in them as long as the tuples have the same schema. These are all valid bags for the schema B: {T:(key:chararray, value:chararray)}:
{(Name,Foo),(Age,Bar)}
{(Age,25),(Name,Jim)}
{(Name,Bob)}
{(Age,30),(Name,Roger),(Hair Color,Brown)}
{(Hair Color,),(Name,Victor)} -- Note the Null value for Hair Color
However, it sounds like you really want a map:
myudf.py
#outputSchema('M:map[]')
def mapize(the_input):
out = {}
for kv in the_input.split(' '):
k, v = kv.split(':')
out[k] = v
return out
myscript.pig
register '../myudf.py' using jython as myudf ;
A = LOAD 'filename.log' AS (total:chararray) ;
B = FOREACH A GENERATE myudf.mapize(total) ;
-- Sample usage, grouping by the name key.
C = GROUP B BY M#'Name' ;
Using the # operator you can pull out all values from the map using the key you give. You can read more about maps here.

Get a value from array based on the value of others arrays (VB.Net)

Supposed that I have two arrays:
Dim RoomName() As String = {(RoomA), (RoomB), (RoomC), (RoomD), (RoomE)}
Dim RoomType() As Integer = {1, 2, 2, 2, 1}
I want to get a value from the "RoomName" array based on a criteria of "RoomType" array. For example, I want to get a "RoomName" with "RoomType = 2", so the algorithm should randomize the index of the array that the "RoomType" is "2", and get a single value range from index "1-3" only.
Is there any possible ways to solve the problem using array, or is there any better ways to do this? Thank you very much for your time :)
Note: Code examples below using C# but hopefully you can read the intent for vb.net
Well, a simpler way would be to have a structure/class that contained both name and type properties e.g.:
public class Room
{
public string Name { get; set; }
public int Type { get; set; }
public Room(string name, int type)
{
Name = name;
Type = type;
}
}
Then given a set of rooms you can find those of a given type using a simple linq expression:
var match = rooms.Where(r => r.Type == 2).Select(r => r.Name).ToList();
Then you can find a random entry from within the set of matching room names (see below)
However assuming you want to stick with the parallel arrays, one way is to find the matching index values from the type array, then find the matching names and then find one of the matching values using a random function.
var matchingTypeIndexes = new List<int>();
int matchingTypeIndex = -1;
do
{
matchingTypeIndex = Array.IndexOf(roomType, 2, matchingTypeIndex + 1);
if (matchingTypeIndex > -1)
{
matchingTypeIndexes.Add(matchingTypeIndex);
}
} while (matchingTypeIndex > -1);
List<string> matchingRoomNames = matchingTypeIndexes.Select(typeIndex => roomName[typeIndex]).ToList();
Then to find a random entry of those that match (from one of the lists generated above):
var posn = new Random().Next(matchingRoomNames.Count);
Console.WriteLine(matchingRoomNames[posn]);