mech_set/operations/
powerset.rs1
2use std::cell::RefCell;
3
4use crate::*;
5
6use indexmap::set::IndexSet;
7use mech_core::set::MechSet;
8
9#[derive(Debug)]
12struct SetPowersetFxn {
13 input: Ref<MechSet>,
14 out: Ref<MechSet>,
15}
16impl MechFunctionFactory for SetPowersetFxn {
17 fn new(args: FunctionArgs) -> MResult<Box<dyn MechFunction>> {
18 match args {
19 FunctionArgs::Unary(out, input) => {
20 let input: Ref<MechSet> = unsafe { input.as_unchecked() }.clone();
21 let out: Ref<MechSet> = unsafe { out.as_unchecked() }.clone();
22 Ok(Box::new(SetPowersetFxn {input, out }))
23 },
24 _ => Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: args.len() }, None).with_compiler_loc()),
25 }
26 }
27}
28
29fn powerset_recursive<T>(set: &Vec<T>) -> Vec<Vec<T>>
30 where T: std::fmt::Debug + Clone,
31{
32 if set.len() == 0
33 {
34 return vec![vec![]];
35 }
36 let mut with_set = powerset_recursive_aux(set, vec![vec![set[0].clone()]], 1);
37 let mut without_set = powerset_recursive_aux(set, vec![vec![]], 1);
38 with_set.append(&mut without_set);
39 with_set.sort_by(|a, b| a.len().cmp(&b.len()));
40 with_set
41}
42
43fn powerset_recursive_aux<T>(set: &Vec<T>, mut unfinished_set: Vec<Vec<T>>, index: usize) -> Vec<Vec<T>>
44 where T: std::fmt::Debug + Clone,
45{
46 if index == set.len()
47 {
48 return unfinished_set;
49 }
50 let mut with_set = powerset_recursive_aux(set, unfinished_set.iter_mut().
51 map(|x| {let mut y = x.clone(); y.push(set[index].clone()); y}).collect(), index + 1);
52 let mut without_set = powerset_recursive_aux(set, unfinished_set, index + 1);
53 with_set.append(&mut without_set);
54 with_set
55}
56
57impl MechFunctionImpl for SetPowersetFxn {
58 fn solve(&self) {
59 unsafe {
60 let out_ptr: &mut MechSet = &mut *(self.out.as_mut_ptr());
62
63 let input_ptr: &MechSet = &*(self.input.as_ptr());
65
66 out_ptr.set.clear();
68
69 let vec_set = powerset_recursive(&(input_ptr.set.clone().into_iter().collect()));
71 for set in vec_set
72 {
73 out_ptr.set.insert(Value::Set(Ref::new(MechSet::from_vec(set))));
74 }
75
76 out_ptr.num_elements = out_ptr.set.len();
78 out_ptr.kind = ValueKind::Set(Box::new(input_ptr.kind.clone()), None);
79 }
80 }
81 fn out(&self) -> Value { Value::Set(self.out.clone()) }
82 fn to_string(&self) -> String { format!("{:#?}", self) }
83}
84#[cfg(feature = "compiler")]
85impl MechFunctionCompiler for SetPowersetFxn {
86 fn compile(&self, ctx: &mut CompileCtx) -> MResult<Register> {
87 let name = format!("SetPowersetFxn");
88 compile_unop!(name, self.out, self.input, ctx, FeatureFlag::Custom(hash_str("set/powerset")));
89 }
90}
91register_descriptor! {
92 FunctionDescriptor {
93 name: "SetPowersetFxn",
94 ptr: SetPowersetFxn::new,
95 }
96}
97
98fn set_powerset_fxn(input: Value) -> MResult<Box<dyn MechFunction>> {
99 match (input) {
100 (Value::Set(input)) => {
101 Ok(Box::new(SetPowersetFxn { input: input.clone(), out: Ref::new(MechSet::new(input.borrow().kind.clone(), 2_u32.pow(input.borrow().num_elements as u32) as usize)) }))
102 },
103 x => Err(MechError2::new(
104 UnhandledFunctionArgumentKind1 { arg: x.kind(), fxn_name: "set/powerset".to_string() },
105 None
106 ).with_compiler_loc()),
107 }
108}
109
110pub struct SetPowerset {}
111impl NativeFunctionCompiler for SetPowerset {
112 fn compile(&self, arguments: &Vec<Value>) -> MResult<Box<dyn MechFunction>> {
113 if arguments.len() != 1 {
114 return Err(MechError2::new(IncorrectNumberOfArguments { expected: 1, found: arguments.len() }, None).with_compiler_loc());
115 }
116 let input = arguments[0].clone();
117 match set_powerset_fxn(input.clone()) {
118 Ok(fxn) => Ok(fxn),
119 Err(x) => {
120 match input {
121 Value::MutableReference(input) => { set_powerset_fxn(input.borrow().clone()) },
122 input => { set_powerset_fxn(input.clone()) },
123 x => Err(MechError2::new(
124 UnhandledFunctionArgumentKind1 { arg: x.kind(), fxn_name: "set/powerset".to_string() },
125 None
126 ).with_compiler_loc()),
127 }
128 }
129 }
130 }
131}
132
133register_descriptor! {
134 FunctionCompilerDescriptor {
135 name: "set/powerset",
136 ptr: &SetPowerset{},
137 }
138}