How to update the weights in WeightedIndex? - rust

I want to update the weights for the key after its drawn, how can I do that.
use rand::distributions::WeightedIndex;
use rand::prelude::*;
fn main() {
let mut rng = thread_rng();
let items = [('a', 0), ('b', 3), ('c', 7)];
let dist2 = WeightedIndex::new(items.iter().map(|item| item.1)).unwrap();
for _ in 0..10 {
// 0% chance to print 'a', 30% chance to print 'b', 70% chance to print 'c'
println!("{}", items[dist2.sample(&mut rng)].0);
// dist2.update_weights(new_weights: &[(usize, &X)])
}
}
That is when "b" is drawn, I want to set the weight for b to zero, so that its no longer drawn, or set it to some other weight.
https://docs.rs/rand/0.7.3/rand/distributions/weighted/struct.WeightedIndex.html

use rand::distributions::WeightedIndex;
use rand::prelude::*;
fn main() {
let mut rng = thread_rng();
let items = [('a', 8), ('b', 5), ('c', 1)];
let mut dist2 = WeightedIndex::new(items.iter().map(|item| item.1)).unwrap();
for _ in 0..3 {
let index = dist2.sample(&mut rng);
println!("{}", index);
println!("{:?}", items[index].0);
dist2.update_weights(&[(index, &0)]).unwrap();
}
}
You just need to call the update_weights function on the same distribution - it will mutate the existing distribution, so there is no need to reassign. Note that the return value of update_weights is just a Result<(), WeightedError>. An Ok(()) indicates that the mutation of the distribution was succesful.

Here is my code:
use rand::distributions::WeightedIndex;
use rand::prelude::*;
fn main() {
let mut rng = thread_rng();
let items = [('a', 8), ('b', 5), ('c', 1)];
let mut dist2 = WeightedIndex::new(items.iter().map(|item| item.1)).unwrap();
for _ in 0..3 {
// 0% chance to print 'a', 30% chance to print 'b', 70% chance to print 'c'
let index = dist2.sample(&mut rng);
println!("{}", index);
println!("{:?}", items[index].0);
let _d = dist2.update_weights(&[(index, &0)]);
}
}

Related

How do I read an .npy file that contains a string?

I have a .npy file which contains tuples of one string (|S8) and 6 float values. I want to read the .npy in Rust as a vector of tuples.
I tried the npyz crate:
use npyz;
fn main() {
read_depl_npy();
}
fn read_depl_npy() -> Result<(), Box<dyn std::error::Error>> {
let bytes = std::fs::read("test-data/test.npy")?;
let npy = npyz::NpyFile::new(&bytes[..])?;
println!("{:?}", npy.into_vec::<Depl>());
Ok(())
}
#[derive(npyz::Deserialize, Debug)]
struct Depl {
name: String,
a: f64,
b: f64,
c: f64,
d: f64,
e: f64,
f: f64,
}
I get this error:
the trait `Deserialize` is not implemented for `String`
Are there any other solutions or modification to this code that I could use?
I tried to open the .npy in Python and send it to Rust using pyo3 by creating a Python module with Rust, but it's too inefficient. I wonder if Calling Python in Rust code would do any better.
Upadte:
I'm not in control of the data in the .npy file. It is given to me as is. Here are the first 8 items in the file :
0000 = {void} (b'N1 ', 1.15423654e-05, nan, -8.63531175e-06, 0.00234345, -1.93959406e-05, nan)
0001 = {void} (b'N10 ', nan, 0.00014046, 9.3921465e-07, nan, -1.36987648e-05, -0.00021798)
0002 = {void} (b'N100 ', -2.95802408e-06, 5.02222077e-05, 5.02908617e-07, 0.00222162, nan, 0.00015162)
0003 = {void} (b'N1000 ', 1.11732508e-06, 0.00018788, nan, 0.00098555, -6.56358132e-06, -0.00021724)
0004 = {void} (b'N1001 ', -1.07967489e-06, 0.0001863, -3.29593367e-07, 0.00098565, nan, -0.00021703)
0005 = {void} (b'N1002 ', nan, 0.00018486, -4.39249772e-07, 0.00098573, -6.54476282e-06, -0.00021686)
0006 = {void} (b'N1003 ', -1.01067021e-06, 0.00018347, 8.16061298e-07, 0.00098576, -6.56198811e-06, -0.00021675)
0007 = {void} (b'N1004 ', 1.03888923e-18, 0.00016245, -2.65077262e-06, 0.0016541, -1.13024989e-05, -0.00022285)
0008 = {void} (b'N1005 ', 2.02031333e-18, 0.00016073, -1.84684389e-06, 0.00165515, -1.13003433e-05, -0.00022227)
And the data type:
[('name', 'S8'), ('a', '<f8'), ('b', '<f8'), ('c', '<f8'), ('d', '<f8'), ('e', '<f8'), ('f', '<f8')]

What type annotations are required for Petgraph's all_simple_paths() function?

I'm trying to use Petgraph's all_simple_paths(), but I'm not sure what type annotations are required, the the docs don't give an example. It returns a impl Iterator<Item = TargetColl> where TargetColl: FromIterator<G::NodeId>, but I don't know what sort of annotation I should make for that.
for path in algo::all_simple_paths(&graph, x, y, 0, None) {}
error[E0282]: type annotations needed
--> lib.rs:10:29
|
10 | for path in algo::all_simple_paths(&graph, x, y, 0, None) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the element type for this iterator is not specified
It should be enough to use
for path in algo::all_simple_paths::<Vec<_>, _>(&graph, x, y, 0, None) {}
Here's a working example:
use petgraph::{algo, prelude::*};
fn main() {
let mut graph = DiGraph::<&str, i32>::new();
let a = graph.add_node("a");
let b = graph.add_node("b");
let c = graph.add_node("c");
let d = graph.add_node("d");
graph.extend_with_edges(&[
(a, b, 1),
(b, c, 1),
(c, d, 1),
(a, b, 1),
(b, d, 1),
]);
let ways = algo::all_simple_paths::<Vec<_>, _>(&graph, a, d, 0, None)
.collect::<Vec<_>>();
assert_eq!(4, ways.len());
}

How to convert a string to entity in kotlin

I have a string like bellow:
str = "Test(a=10, b=100, c=1.0, d=2.0)"
and Test entity is:
data class Test(
val a: int = 0,
val b: Int = 0,
val c: Double = 0.0,
val d: Double = 0.0
)
What should I do to convert string str to Test entity?
Thankyou!!
Regexes seem like an appropriate choice here:
data class Test(val a: Int = 0, val b: Int = 0, val c: Double = 0.0, val d: Double = 0.0)
fun main() {
val str = "Test(a=10, b=100, c=1.0, d=2.0)"
print(getTest(str))
}
fun getTest(str: String): Test {
val regex = """Test\(a=(.+), b=(.+), c=(.+), d=(.+)\)""".toRegex()
val matches = regex.find(str)
return matches?.groupValues?.let { groups ->
Test(groups[1].toInt(), groups[2].toInt(), groups[3].toDouble(), groups[4].toDouble())
} ?: Test()
}
If you're looking at storing objects as strings to re-instantiate them, consider serialization. Have a look here.
It works
data class Test(
val a: Int = 0,
val b: Int = 0,
val c: Double = 0.0,
val d: Double = 0.0
)
fun main() {
val str = "Test(a=10, b=100, c=1.0, d=2.0)"
val numbers = "([\\d.]+)".toRegex().findAll(str).map { it.value }.toList()
val test = Test(
numbers[0].toInt(),
numbers[1].toInt(),
numbers[2].toDouble(),
numbers[3].toDouble())
}

Python: How to convert json comma separated key to a dictionary

I have a JSON in below format:
{
'166, 175': 't2',
'479': 't3'
}
I want to convert this to a map:
166: 't2'
175: 't2'
479: 't3'
src = {
'166, 175': 't2',
'479': 't3'
}
res = {}
for k, v in src.items():
for i in k.split(', '):
res[int(i)] = v
print(res)
You can use some dictionary comprehension here:
{
int(k): v
for ks, v in data.items()
for k in ks.split(',')
}
For the sample data, this gives us:
>>> {
... int(k): v
... for ks, v in data.items()
... for k in ks.split(',')
... }
{166: 't2', 175: 't2', 479: 't3'}
Bit complicated though
src = {
'166, 175': 't2',
'479': 't3'
}
output = dict(reduce(lambda a, b: a + b, map(lambda b:zip(b.split(', '), [a[b]] * len(b.split(', '))), src)))

How do I loop through a list and remove an item in groovy?

I'm trying to figure out how to remove an item from a list in groovy from within a loop.
static main(args) {
def list1 = [1, 2, 3, 4]
for(num in list1){
if(num == 2)
list1.remove(num)
}
println(list1)
}
list = [1, 2, 3, 4]
newList = list.findAll { it != 2 }
Should give you all but the 2
Of course you may have a reason for requiring the loop?
If you want to remove the item with index 2, you can do
list = [1,2,3,4]
list.remove(2)
assert list == [1,2,4]
// or with a loop
list = [1,2,3,4]
i = list.iterator()
2.times {
i.next()
}
i.remove()
assert list == [1,2,4]
If you want to remove the (first) item with value 2, you can do
list = [1,2,3,4]
list.remove(list.indexOf(2))
assert list == [1,3,4]
// or with a loop
list = [1,2,3,4]
i = list.iterator()
while (i.hasNext()) {
if (i.next() == 2) {
i.remove()
break
}
}
assert list == [1,3,4]
As you state in your comment that you do not specifically require a loop .... If you are happy to modify your original list you can use removeAll:
// Remove all negative numbers
list = [1, 2, -4, 8]
list.removeAll { it < 0 }
I think you can do:
list - 2;
or...
list.remove(2)
There's no loop required.
If you want to use a loop I guess you could look at using the iterator to actually remove the item.
import java.util.Iterator;
static main(args) { def list1 = [1, 2, 3, 4]
Iterator i = list1.iterator();
while (i.hasNext()) {
n = i.next();
if (n == 2) i.remove();
}
println(list1)
}​
but I don't see why you'd want to do it that way.

Resources