I have a list that represent the connection between nodes (edges) in a ipotetically graph; the list is structured like that:
val def_graph : ((int * int) * (int * int)) list =
[((0, 0), (2, 1)); ((0, 0), (1, 2)); ((0, 1), (2, 0)); ((0, 1), (2, 2));
((0, 1), (1, 3)); ((0, 2), (2, 1)); ((0, 2), (2, 3)); ((0, 2), (1, 0));
((0, 2), (1, 4)); ((0, 3), (2, 2)); ((0, 3), (2, 4)); ((0, 3), (1, 1));
((0, 3), (1, 5)); ((0, 4), (2, 3)); ((0, 4), (2, 5)); ((0, 4), (1, 2));
((0, 4), (1, 6)); ((0, 5), (2, 4)); ((0, 5), (2, 6)); ((0, 5), (1, 3));
((0, 5), (1, 7)); ((0, 6), (2, 5)); ((0, 6), (2, 7)); ((0, 6), (1, 4));
((0, 7), (2, 6)); ((0, 7), (1, 5)); ((1, 0), (3, 1)); ((1, 0), (0, 2));
((1, 0), (2, 2)); ((1, 1), (3, 0)); ((1, 1), (3, 2)); ((1, 1), (0, 3));
((1, 1), (2, 3)); ((1, 2), (3, 1)); ((1, 2), (3, 3)); ((1, 2), (0, 0));
((1, 2), (0, 4)); ((1, 2), (2, 0)); ((1, 2), (2, 4)); ((1, 3), (3, 2));
((1, 3), (3, 4)); ((1, 3), (0, 1)); ((1, 3), (...)); ...]
where the nodes is rapresented by tuples ((0,0) is a node, (1,3) is a node and so on...) and ((0,0),(2,1)) represent a connection between node (0,0) and node (2,1);
How can I represent my "graph" by a list of successor of any node?
The result must be:
val succ_graph : ((int * int) * (int * int) list) list =
[((0,0),[(2,1),(1,2)]);((0,1),[(2,0),(2,2),(1,3)]);((0,2),[(2,1),(2,3),
(1,0),(1,4)]); .... ]
a list of tuples where the first param is the node himself and the second param is a list of any successor of him;
I wrote a function that extract the list of successor giving a specific node, but i don't know how to do the rest.
let succ arcs node =
let rec aux = function
[] -> []
| (x,y)::rest -> if x = node then y::aux rest
else aux rest
in aux arcs;;
Sorry but it's my first experience with ocaml, and sorry for the bad english!!!
Thank's.
As an initial comment, your problem statement and examples are a little confusing. The example result you give is not of the type you say you want. And your function doesn't compute a part of the type either. Let's say you really do want this type:
((int * int) * ((int * int) * (int * int)) list) list
For each node of your graph you want a list of pairs of nodes. An example of this would be:
[((0, 0), [((0, 0), (2, 1)); ((0, 0), (1, 2))]); ... ]
Your example result doesn't look like this, and your function is calculating a list of nodes (not a list of pairs of nodes).
So the first thing to do might be to resolve this disagreement.
After you figure this out, the code you have now is actually pretty close to the right answer. Instead of looking for links from a particular node, you would add every link you see to your answer. Instead of putting answers at the front of a list, you need to be able to insert answers down inside the result that you're constructing.
A good place to start, then, might be to write code to add a new link to an accumulated result of type ((int * int) * ((int * int) * (int * int)) list) list.
Lists in OCaml are immutable, so the way to do this is to construct a new list. The new list will contain many parts of the old list; you don't have to build it from scratch. (This is, in fact, why immutable data is actually usable in practice.)
Update
As I say, you can use your current code if you write a function that adds a new successor in the correct place. Then you use this new function instead of the simple function :: that you're using now.
But the notion of "adding" something to an immutable structure is a bit tricky at first.
Here's a function that "adds" an int to a list while keeping the list sorted. I.e., it returns a new list with the desired property. The old list is unchanged (being immutable, this is a given).
let rec insert l x = match l with
| [] -> [x]
| h :: t -> if x <= h then x :: l else h :: insert t x
It looks like this:
# insert [1; 1; 3; 4; 5; 9] 2;;
- : int list = [1; 1; 2; 3; 4; 5; 9]
You can use this insert function to sort a list (inefficiently):
let rec sort = function
| [] -> []
| h :: t -> insert (sort t) h
It looks like this:
# sort [3; 1; 4; 1; 5; 9; 2];;
- : int list = [1; 1; 2; 3; 4; 5; 9]
This is essentially what you want to do, except you have pairs instead of ints, and your structure is a little more complicated than a sorted list.
Related
I have a program where I use a vector to simulate all the possible outcomes when counting cards in blackjack. There's only three possible values, -1, 0, and 1. There's 52 cards in a deck therefore the vector will have 52 elements, each assigned one of values mentioned above. The program works when I scale down the size of the vector, it still works when I have it as this size however I get no output and get the warning "warning C4267: '=': conversion from 'size_t' to 'int', possible loss of data".
#include<iostream>
#include"subtracter.h"
#include<time.h>
#include<vector>
#include<random>
using namespace std;
int acecard = 4;
int twocard = 4;
int threecard = 4;
int fourcard = 4;
int fivecard = 4;
int sixcard = 4;
int sevencard = 4;
int eightcard = 4;
int ninecard = 4;
int tencard = 16;
// declares how many of each card there is
vector<int> cardvalues = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
// a vector that describes how many cards there are with a certain value
vector<int> deck = { acecard, twocard, threecard, fourcard, fivecard, sixcard, sevencard, eightcard, ninecard, tencard };
// a vector keeping track of how many of each cards there's left in the deck
int start()
{
int deckcount;
deckcount = 0;
int decksize;
decksize = cardvalues.size();
while (decksize >= 49)
{
deckcount += cardsubtracter(cardvalues);
};
return deckcount;
}
int cardcounting()
{
int deckcount;
deckcount = start();
deckcount += cardsubtracter(cardvalues);
return deckcount;
}
int main()
{
int value;
value = cardcounting();
int size;
size = cardvalues.size();
cout << value << "\n";
cout << size;
return 0;
}
#include<iostream>
#include<random>
using namespace std;
int numbergenerator(int x, int y)
{
int number;
random_device generator;
uniform_int_distribution<>distrib(x, y);
number = distrib(generator); //picks random element from vector
return number;
}
int cardsubtracter(vector<int> mynum)
{
int counter;
int size;
int number;
size = mynum.size() - 1;//gives the range of values to picked from the vectorlist
number = numbergenerator(0, size);//gives a random number to pick from the vectorlist
counter = mynum[number]; // uses the random number to pick a value from the vectorlist
mynum.erase(mynum.begin()+number); //removes that value from the vectorlist
return counter;
}
I looked up the max limit of vectors and it said that vectors can hold up 232 values with integers, which should work for this. So I also tried creating a new file and copying the code over to that in case there was something wrong with this file.
There could be different reasons why a vector may not be able to hold all 52 elements. Some possible reasons are:
Insufficient memory: Each element in a vector requires a certain amount of memory, and the total memory required for all 52 elements may exceed the available memory. This can happen if the elements are large, or if there are many other variables or data structures in the environment that consume memory.
Data type limitations: The data type of the vector may not be able to accommodate all 52 elements. For example, if the vector is of type "integer", it can only hold integers up to a certain limit, beyond which it will overflow or produce incorrect results.
Code errors: There may be errors in the code that prevent all 52 elements from being added to the vector. For example, if the vector is being filled in a loop, there may be a mistake in the loop condition or in the indexing that causes the loop to terminate early or skip some elements.
To determine the exact reason for the vector not being able to hold all 52 elements, it is necessary to examine the code, the data types involved, and the memory usage.
What is the best way to replace a specific portion of a vector with a new vector?
As of now, I am using hardcoded code to replace the vector. What is the most effective way to achieve this?
fn main() {
let mut v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9];
let u = vec![0,0,0,0];
v[2] = u[0];
v[3] = u[1];
v[4] = u[2];
v[5] = u[3];
println!("v = {:?}", v);
}
Permalink to the playground
Is there any function to replace the vector with given indices?
For Copy types:
v[2..][..u.len()].copy_from_slice(&u);
Playground.
For non-Copy types:
v.splice(2..2 + u.len(), u);
Playground.
Another way:
let offset : usize = 2;
u.iter().enumerate().for_each(|(index, &val)| {
v[index + offset] = val;
});
Playground
Me and my friend are trying to implement a paper and the last step requires solving a linear programming problem to get the final result. We are not so familiar with LP so i'd like to ask for your help.
Here's the function which is based on the PROFSET model
and here's the proposed constraints
(1)
(2)
where:
Pa and Qi are the binary decision variables
J are all the available categories
F are sets of frequent categories
Φ is the total number of selected categories
Constraint (1) actually says that Qi is 1 if category i is included in some itemset A where Pa = 1
Basically, we are trying to use some common open source lp solvers (like joptimizer) but we dont know
how to define those constraints, especially those that define set inclusion rules. Most of those solvers
seem to accept just inequalities.
So, do you have any idea about how to define those constraints? Maybe transform them to inequalities or
something? Any help would be appreciated.
Thank you
A constraint that is written as an equality can be also written as two inequalities.
e.g.
A*x=b is the same as
A*x<=b and A*x>=b
In order to write such a LP there are two ways.
To hardcode it, meaning writing everything in code for example in Java.
Write it the mathematical way in a "language" called AMPL: https://ampl.com/resources/the-ampl-book/ For the second way you don't really need to know a programming language. AMPL transforms magically your LP into code and feeds it to a solver e.g. commercial: CPLEX, Gurobi (academic license available) or open source: GLPK. AMPL provides also an online platform that you can provide your model as .mod file and data as .dat files.
If you still want to hardcode your LP GLPK has nice examples e.g. in JAVA:
public class Lp {
// Minimize z = -.5 * x1 + .5 * x2 - x3 + 1
//
// subject to
// 0.0 <= x1 - .5 * x2 <= 0.2
// -x2 + x3 <= 0.4
// where,
// 0.0 <= x1 <= 0.5
// 0.0 <= x2 <= 0.5
// 0.0 <= x3 <= 0.5
public static void main(String[] arg) {
glp_prob lp;
glp_smcp parm;
SWIGTYPE_p_int ind;
SWIGTYPE_p_double val;
int ret;
try {
// Create problem
lp = GLPK.glp_create_prob();
System.out.println("Problem created");
GLPK.glp_set_prob_name(lp, "myProblem");
// Define columns
GLPK.glp_add_cols(lp, 3);
GLPK.glp_set_col_name(lp, 1, "x1");
GLPK.glp_set_col_kind(lp, 1, GLPKConstants.GLP_CV);
GLPK.glp_set_col_bnds(lp, 1, GLPKConstants.GLP_DB, 0, .5);
GLPK.glp_set_col_name(lp, 2, "x2");
GLPK.glp_set_col_kind(lp, 2, GLPKConstants.GLP_CV);
GLPK.glp_set_col_bnds(lp, 2, GLPKConstants.GLP_DB, 0, .5);
GLPK.glp_set_col_name(lp, 3, "x3");
GLPK.glp_set_col_kind(lp, 3, GLPKConstants.GLP_CV);
GLPK.glp_set_col_bnds(lp, 3, GLPKConstants.GLP_DB, 0, .5);
// Create constraints
// Allocate memory
ind = GLPK.new_intArray(3);
val = GLPK.new_doubleArray(3);
// Create rows
GLPK.glp_add_rows(lp, 2);
// Set row details
GLPK.glp_set_row_name(lp, 1, "c1");
GLPK.glp_set_row_bnds(lp, 1, GLPKConstants.GLP_DB, 0, 0.2);
GLPK.intArray_setitem(ind, 1, 1);
GLPK.intArray_setitem(ind, 2, 2);
GLPK.doubleArray_setitem(val, 1, 1.);
GLPK.doubleArray_setitem(val, 2, -.5);
GLPK.glp_set_mat_row(lp, 1, 2, ind, val);
GLPK.glp_set_row_name(lp, 2, "c2");
GLPK.glp_set_row_bnds(lp, 2, GLPKConstants.GLP_UP, 0, 0.4);
GLPK.intArray_setitem(ind, 1, 2);
GLPK.intArray_setitem(ind, 2, 3);
GLPK.doubleArray_setitem(val, 1, -1.);
GLPK.doubleArray_setitem(val, 2, 1.);
GLPK.glp_set_mat_row(lp, 2, 2, ind, val);
// Free memory
GLPK.delete_intArray(ind);
GLPK.delete_doubleArray(val);
// Define objective
GLPK.glp_set_obj_name(lp, "z");
GLPK.glp_set_obj_dir(lp, GLPKConstants.GLP_MIN);
GLPK.glp_set_obj_coef(lp, 0, 1.);
GLPK.glp_set_obj_coef(lp, 1, -.5);
GLPK.glp_set_obj_coef(lp, 2, .5);
GLPK.glp_set_obj_coef(lp, 3, -1);
// Write model to file
// GLPK.glp_write_lp(lp, null, "lp.lp");
// Solve model
parm = new glp_smcp();
GLPK.glp_init_smcp(parm);
ret = GLPK.glp_simplex(lp, parm);
// Retrieve solution
if (ret == 0) {
write_lp_solution(lp);
} else {
System.out.println("The problem could not be solved");
}
// Free memory
GLPK.glp_delete_prob(lp);
} catch (GlpkException ex) {
ex.printStackTrace();
ret = 1;
}
System.exit(ret);
}
/**
* write simplex solution
* #param lp problem
*/
static void write_lp_solution(glp_prob lp) {
int i;
int n;
String name;
double val;
name = GLPK.glp_get_obj_name(lp);
val = GLPK.glp_get_obj_val(lp);
System.out.print(name);
System.out.print(" = ");
System.out.println(val);
n = GLPK.glp_get_num_cols(lp);
for (i = 1; i <= n; i++) {
name = GLPK.glp_get_col_name(lp, i);
val = GLPK.glp_get_col_prim(lp, i);
System.out.print(name);
System.out.print(" = ");
System.out.println(val);
}
}}
I'd like to check which is the number between 1 to 5 that not occurs in the array group and put this number (or numbers) in an other array.
g=2;
set of int: GROUPS = 1..g;
groups = [{1, 3}, {2,5}];
p=5;
set of int: PEOPLE = 1..p;
I tried in this way but it doesn't work.
int: peopleInGroup= (g*g);
set of int: INGROUP = 1..peopleInGroup;
array [INGROUP] of var int: inGroup;
int: peopleNotGroup= c-(g*g);
set of int: NOTGROUP = 1..peopleNotGroup;
array [NOTGROUP] of var int: notGroup;
constraint forall(i in groups,person in i) (if sum(j in PEOPLE-1) (i==person then inGroup[i]=person else notGroup[i]=person endif));
In case groups is a literal -as in your question-, then you can use set and list comprehensions -described at page 22 of this tutorial- to achieve your goal.
e.g.
set of int: DOM = 1..5;
set of int: population = DOM;
array[1..2] of set of DOM: groups = [{1, 3}, {2, 5}];
% array initialization
array [int] of var DOM: in_array =
[i | i in DOM where exists(g in groups) (i in g)];
array [int] of var DOM: out_array =
[i | i in DOM where not exists(g in groups) (i in g)];
% set initialization
var set of DOM: in_set =
{i | i in DOM where exists(g in groups) (i in g)};
var set of DOM: out_set =
{i | i in DOM where not exists(g in groups) (i in g)};
solve satisfy;
output [
"in_set=", show(in_set), "\n",
"out_set=", show(out_set), "\n",
"in_array=", show(in_array), "\n",
"out_array=", show(out_array), "\n"
];
note: var can be dropped from definition of all variables, here I use it only because flatzinc would otherwise not print their content on standard output.
The output is:
~$ mzn2fzn example.mzn ; flatzinc example.fzn
in_array = array1d(1..4, [1, 2, 3, 5]);
in_set = {1, 2, 3, 5};
out_array = array1d(1..1, [4]);
out_set = {4};
----------
Here is the generated intermediate flatzinc model:
array [1..2] of set of int: groups = [{1, 3}, {2, 5}];
array [1..4] of var 1..5: in_array :: output_array([1..4]) = [1, 2, 3, 5];
var set of 1..5: in_set :: output_var = {1, 2, 3, 5};
array [1..1] of var 4..4: out_array :: output_array([1..1]) = [4];
var set of 1..5: out_set :: output_var = 4..4;
solve satisfy;
I can not find within the documentation of Vec<T> how to retrieve a slice from a specified range.
Is there something like this in the standard library:
let a = vec![1, 2, 3, 4];
let suba = a.subvector(0, 2); // Contains [1, 2];
The documentation for Vec covers this in the section titled "slicing".
You can create a slice of a Vec or array by indexing it with a Range (or RangeInclusive, RangeFrom, RangeTo, RangeToInclusive, or RangeFull), for example:
fn main() {
let a = vec![1, 2, 3, 4, 5];
// With a start and an end
println!("{:?}", &a[1..4]);
// With a start and an end, inclusive
println!("{:?}", &a[1..=3]);
// With just a start
println!("{:?}", &a[2..]);
// With just an end
println!("{:?}", &a[..3]);
// With just an end, inclusive
println!("{:?}", &a[..=2]);
// All elements
println!("{:?}", &a[..]);
}
If you wish to convert the entire Vec to a slice, you can use deref coercion:
fn main() {
let a = vec![1, 2, 3, 4, 5];
let b: &[i32] = &a;
println!("{:?}", b);
}
This coercion is automatically applied when calling a function:
fn print_it(b: &[i32]) {
println!("{:?}", b);
}
fn main() {
let a = vec![1, 2, 3, 4, 5];
print_it(&a);
}
You can also call Vec::as_slice, but it's a bit less common:
fn main() {
let a = vec![1, 2, 3, 4, 5];
let b = a.as_slice();
println!("{:?}", b);
}
See also:
Why is it discouraged to accept a reference to a String (&String), Vec (&Vec), or Box (&Box) as a function argument?