Serialize a Zipper? - serialization

repl> (-> root zip/down zip/right)
[{:answer-keys [5 6], :id 3} {:l [{:id 2, :answer-keys []}], :pnodes [{:answer-keys [2 3 4], :id 1}], :ppath nil, :r ({:answer-keys [7], :id 4})}]
I see this data when I print out the zipper on the repl. I am thinking that this may be all the data I would need to serialize a zipper? Is it possible to de-serialize a zipper from the provided data?
I am looking for something like the zip/serialize and zip/deserialize function imagined below.
(def s (zip/serialize (-> root zip/down zip/right))) ;; s is a string
(def d (zip/deserialize s)) ;; d is a zipper location
;;And I can go on using the deserialized zipper d without any difficulty.
Does anyone know how to do this?

the magic of zippers is they are a data structure that represents everything needed to produce arbitrarily modified versions of tree structures. zippers print and read just fine because they are proper values and don't require any state
you can "serialize" it with pr-str and "deserialize" it with read
make a zipper:
user> (zip/vector-zip [[1 [2]][3][4]])
[[[1 [2]] [3] [4]] nil]
user> (def s (zip/vector-zip [[1 [2]][3][4]]))
#'user/s
user> s
[[[1 [2]] [3] [4]] nil]
serialize it to a string:
user> (def serialized-s (pr-str (zip/next s)))
#'user/serialized-s
user> serialized-s
"[[1 [2]] {:l [], :pnodes [[[1 [2]] [3] [4]]], :ppath nil, :r ([3] [4])}]"
read it back:
user> (def deserialized-s (read-string "[[1 [2]] {:l [], :pnodes [[[1 [2]] [3] [4]]], :ppath nil, :r ([3] [4])}]"))
#'user/deserialized-s
do something with the result:
user> (zip/root deserialized-s)
[[1 [2]] [3] [4]]

To expand on Arthur's answer:
You probably also need to serialize the metadata that clojure.zip puts on its zippers, since that seems to be where it keeps track of the branch?/children/make-node functions. So something like
(defn serialize [zipper]
(binding [*print-meta* true]
(pr-str zipper)))
(def deserialize read-string)

Related

Is asReversed() essentially reversed() for List in Kotlin?

As stated in the answer https://stackoverflow.com/a/57115894/3286489, the asReversed() will generate a reversed list, that value will be changed if the original list has changed its element within.
val list = mutableListOf(0, 1, 2, 3, 4, 5)
val asReversed = list.asReversed()
val reversed = list.reversed()
println("Original list: $list")
println("asReversed: $asReversed")
println("reversed: $reversed")
list[0] = 10
println("Original list: $list")
println("asReversed: $asReversed")
println("reversed: $reversed")
Outputs
Original list: [0, 1, 2, 3, 4, 5]
asReversed: [5, 4, 3, 2, 1, 0]
reversed: [5, 4, 3, 2, 1, 0]
Original list: [10, 1, 2, 3, 4, 5]
asReversed: [5, 4, 3, 2, 1, 10]
reversed: [5, 4, 3, 2, 1, 0]
To me, that means only if the original list is a MutableList then it can change it's value within.
However, if the original List is an immutable List, it's value cannot be changed, this essentially make asReversed() and reversed() has not distinct difference on it, right?
i.e.
val list = listOf(0, 1, 2, 3, 4, 5)
val asReversed = list.asReversed() // This is the same as below?
val reversed = list.reversed() // This is the same as above?
Did I miss any scenario they are still different?
Updated
I even change what it contains as mutableList
val list = listOf(
mutableListOf(1),
mutableListOf(2),
mutableListOf(3),
mutableListOf(4),
mutableListOf(5),
mutableListOf(6))
val asReversed = list.asReversed()
val reversed = list.reversed()
println("Original list: $list")
println("asReversed: $asReversed")
println("reversed: $reversed")
list[0][0] = 10
println("Original list: $list")
println("asReversed: $asReversed")
println("reversed: $reversed")
Output
Original list: [[1], [2], [3], [4], [5], [6]]
asReversed: [[6], [5], [4], [3], [2], [1]]
reversed: [[6], [5], [4], [3], [2], [1]]
Original list: [[5], [2], [3], [4], [5], [6]]
asReversed: [[6], [5], [4], [3], [2], [10]]
reversed: [[6], [5], [4], [3], [2], [10]]
This will change for both asReversed and reversed result
The most important difference between the two is, that asReversed is always just a view on the original list. That means, if you alter the original list, the result of asReversed will always contain all the updated information. In the end it's just a view.
reversed however always gives you a new disconnected list of the original list. Note however that when you deal with object references within the original list (like lists in a list or other kind of objects that are referenceable) then you will see all the adaptations of the original object of that list also adapted in the reversed ones, regardless of whether you used reversed or asReversed.
Regarding your update it is unfortunate you used such a list that contains references. With your original list however the difference becomes much clearer:
val asReversed = list.asReversed()
val reversed = list.reversed()
fun printAll(msg : String) {
println(msg)
println("Original list: $list")
println("asReversed: $asReversed")
println("reversed: $reversed")
}
printAll("Initial ----")
list as MutableList
list[2] = 1000
printAll("mutating original list ----")
reversed as MutableList
reversed[4] = 3000
printAll("mutating reversed list ----")
As asReversed returns you a ReversedListReadOnly-type, you can't easily cast it to a MutableList, but if it would be possible, the changes in asReversed would be reflected in the original list, but not in the reversed. The output of the above is the following:
Initial ----
Original list: [0, 1, 2, 3, 4, 5]
asReversed: [5, 4, 3, 2, 1, 0]
reversed: [5, 4, 3, 2, 1, 0]
mutating original list ----
Original list: [0, 1, 1000, 3, 4, 5]
asReversed: [5, 4, 3, 1000, 1, 0]
reversed: [5, 4, 3, 2, 1, 0]
mutating reversed list ----
Original list: [0, 1, 1000, 3, 4, 5]
asReversed: [5, 4, 3, 1000, 1, 0]
reversed: [5, 4, 3, 2, 3000, 0]
As you can see: the changes are nicely reflected in the original and the asReversed-list, but changes in the reversed are not reflected and also the reversed one will not contain the original list adaptations.
So, yes, you probably missed that scenario... the lists (reversed and asReversed) aren't equal, not even, if you have a readonly view as input, as noone can guarantee you that the list isn't altered... neither the original nor the asReversed one.
To add to other answers, this is an example of a general method-naming convention in Kotlin (and, to an extent in Java):
toNoun() methods convert an object into a new form that's independent of the original.
asNoun() methods return a view onto the existing object; changes in that will be reflected in the view and (if appropriate) vice versa.
verb() methods mutate the object directly (and don't return anything).
verbed() methods return a mutated copy of the object, leaving the original unchanged.
This question provides examples of two of those cases.
These conventions are very lightweight, read well, and are used fairly consistently.  After you've seen a few, you know almost instinctively how a method will behave!
(It's not universal, though; for example, map() is a verb, but doesn't mutate its receiver.  However, methods like map() and filter() long pre-date Kotlin, and so it's arguably better to stick to well-known existing names like that.)
Their difference actually amazed me!
Okay so by browsing the std-lib this is what I've found.
The reversed function actually creates a copy of whatever the Iterable is as a MutableList and reverses the list "really" and then returns it.
public fun <T> Iterable<T>.reversed(): List<T> {
if (this is Collection && size <= 1) return toList()
val list = toMutableList()
list.reverse()
return list
}
While when you call the asReversed(), it doesn't create a new list "by copying the elements".
It just creates an implementation of an Abstract list with delegation to the real list, and overriding the getter.
public fun <T> List<T>.asReversed(): List<T> = ReversedListReadOnly(this)
private open class ReversedListReadOnly<out T>(private val delegate: List<T>) : AbstractList<T>() {
override val size: Int get() = delegate.size
override fun get(index: Int): T = delegate[reverseElementIndex(index)]
}
So there's no overhead, since the list is immutable there is no need to touch any other part, neither need to copy the list i.e. no need for creating a new one and allocate its memory. It is simplified and just uses the original list.
Found this example here https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/as-reversed.html
val original = mutableListOf('a', 'b', 'c', 'd', 'e')
val originalReadOnly = original as List<Char>
val reversedA = originalReadOnly.asReversed()
val reversedB = originalReadOnly.reversed()
println(original) // [a, b, c, d, e]
println(reversedA) // [e, d, c, b, a]
println(reversedB)
// changing the original list affects its reversed view
original.add('f')
println(original) // [a, b, c, d, e, f]
println(reversedA) // [f, e, d, c, b, a]
println(reversedB) // [e, d, c, b, a]
original[original.lastIndex] = 'z'
println(original) // [a, b, c, d, e, z]
println(reversedA) // [z, e, d, c, b, a]
println(reversedB) // [e, d, c, b, a]
It does show that a List can still be changed if it was originally from a MutableList, where we change the MutableList. Hence that makes asReversed() is still different from reversed() in this case, since there's a way to change the List by changing the original MutableList

Question on the array generating sequence in Raku

I've come across this code at rosettacode
my #pascal = [1], { [0, |$_ Z+ |$_, 0] } ... Inf;
.say for #pascal[^4];
# ==>
# [1]
# [1 1]
# [1 2 1]
# [1 3 3 1]
Inside the explicit generator block, I know how the individual operators like the list flattening | and the zip operator Z+ work but I have difficulty comprehending how they cooperate to generate the next array. Can somebody explain in detail how it works? Thank you.
Note: The code is slightly rearranged for brevity, i.e. it's superficially different than the one in Rosetta.
So let's take a look at what's going on.
First up the Sequence generator ... this takes a list of starting values, a code block itself and and end point.
It uses the starting values to generate each next item in the list so lets start with #pascal[0] that's simple enough : [1]
For #pascal[1] we call the code block with our value in #pascal[0] like so :
sub ( $array ) {
[0, |$array Z+ |$array, 0]
}
You'll note I've made it into a sub, this is just so I can explain things easier. In the anonymous code block $_ is the incoming data and I've called it $array. So what code to we run when $array == [1]?
[0, |[1] Z+ |[1], 0] => [1,1]
So here's a question what happens if we don't use the | ?
[0, [1] Z+ [1], 0] => [1,1]
It's the same! So whys it there? Well what happens if we set $array == [3]?
[0, [3] Z+ [3], 0] => [1,1]
Weird? No, because the Z+ transforms like this :
[0, [3] Z+ [3], 0] => [0 + [3], [3] + 0] => [1,1]
Z makes a new list by zipping the elements with the given operator + between them. + is doing a numerical computation and the Numerical representation of an Array is the number of elements in it, in this case 1 both times.
And this is where the | slip operator comes in, it slips the array it's given open merging into the list context it's in. So lets go back to #pascal[1]
[0, |[1] Z+ |[1], 0] => [0, 1 Z+ 1, 0] => [0 + 1, 1 + 0] => [1,1]
Ok.. So #pascal[2] is calling the same block but now passing in [1,1]
[0, |[1, 1] Z+ |[1, 1], 0] => [0, 1, 1 Z+ 1, 1, 0] => [0 + 1, 1 + 1, 1 + 0] => [1,2,1]
And so on into Infinity!
I hope that's helped to explain what's going on?
This is a somewhat interesting application of the sequence operator, in so far as the values that it produces each time are arrays. So:
[1] is the first array produced at the start of the sequence
The block indicates how to produce the next array in the sequence. It takes one argument, which is the previous sequence value
The Inf will never be matched, so the sequence will go on forever
A simpler example may be helpful: the sequence [1], [1,1], [1,1,1], .... That is, we want to produce an array that is the previous item in the sequence with an extra 1 at the end. We could do this:
my #ones = [1], { [|$_, 1] } ... Inf;
.say for #ones[^4];
Producing:
[1]
[1 1]
[1 1 1]
[1 1 1 1]
The first time the block is called, it gets [1] in $_. We slip that with |, thus producing an array [1, 1]. That is passed to the block the second time, and so forth.
So, breaking down [0, |$_ Z+ |$_, 0]. The outer square brackets are an array composer. The rest can be read as 0, |$_ zipped with |$_, 0, using the + operator to zip the things.
The first call to be block will pass [1], thus we will be zipping 0, 1 and 1, 0. Zipping with an operator applies it pairwise, meaning it will calculate 0 + 1, 1 + 0. The overall result is the array [1,1].
The second call to the block gets that [1,1]. It forms the lists 0, 1, 1 and 1, 1, 0, and then the zip operator forms the pairwise addition again, which is 0 + 1, 1 + 1, 1 + 0. The overall result is the array [1,2,1].
Effectively, then, the result grows an element each time, resulting from the pairwise addition of the previous result padded with a zero at either end.

Clojurescript/Reagent handling errors

We are starting to use Clojuescript/Reagent for our next development phase of our product. Basically we need a way, to do a single operation on the atom and we came up with a method like:
(def app-state (r/atom {}))
(defn select [index]
(swap! app-state
#(-> %
(assoc-in [:storyboard :pages 0 :layers 0 :children 0 :is_selected] true)
(assoc-in (GET ....)) ;; ajax call
(assoc-in [:selected :selected_tab] "tab_properties")
(assoc-in [:selected :page_object_cursor] [0])
)))
Basically the swap gets a function where all needed operations are chained. It is brilliant. However, I am looking at ways to handle errors. I would like to have a separate atom for errors:
(def errors (r/atom []))
and when an error occurs, to capture it and add it to the errors, without having the app-state swapped (the application remains in the last stable state). So we use throw from the chain and a try cactch
(defn change-title [title]
(try
(swap! app-state
#(-> %
(assoc :text title)
((fn [state]
(throw "there is an error")))
))
(catch js/Object e
(swap! errors conj e))))
So I would expect the error to be caught, and #errors to have it. But the reality is:
*Uncaught there is an error
weather_app$core$change_title # core.cljs?rel=1450266738018:59(anonymous function) # core.cljs?rel=1450266738018:108executeDispatch # react-with-addons.inc.js:3311SimpleEventPlugin.executeDispatch # react-with-addons.inc.js:17428forEachEventDispatch # react-with-addons.inc.js:3299executeDispatchesInOrder # react-with-addons.inc.js:3320executeDispatchesAndRelease # react-with-addons.inc.js:2693forEachAccumulated # react-with-addons.inc.js:19430EventPluginHub.processEventQueue # react-with-addons.inc.js:2900runEventQueueInBatch # react-with-addons.inc.js:11217ReactEventEmitterMixin.handleTopLevel # react-with-addons.inc.js:11243handleTopLevelImpl # react-with-addons.inc.js:11329Mixin.perform # react-with-addons.inc.js:18402ReactDefaultBatchingStrategy.batchedUpdates # react-with-addons.inc.js:9669batchedUpdates # react-with-addons.inc.js:16633ReactEventListener.dispatchEvent # react-with-addons.inc.js:11423*
(catch :default e
(swap! errors conj e))))
because the string thrown is not an object, but a string!

Mathematica dynamic to plot matrix data

I am trying to dynamically plot data contained in a matrix with Mathematica 7. The data is contained in it like this, obtained via a chemical model.
[year H He Li C ... C8H14+,Grain- ]
[0 0 0.03 0.009 1E-3 ... 0 ]
[100 .1 0.03 0.009 1E-3 ... 0 ]
[200 .2 0.03 0.009 1E-3 ... 0 ]
[300 .2 0.03 0.009 1E-3 ... 0 ]
[... ... ... ... ... ... ... ]
[1E6 .5 0.03 0.003 1E-8 ... 1E-25 ]
The truth is, the matrix dimensions are 2001*1476 (2000 steps and first line for name, and 1475 compounds + 1 column for year), very heavy.
I am trying to plot any compound with a concentration / year plot. This works
Manipulate[
ListLogLogPlot[data[[All, {1, i}]], PlotLabel -> data[[1, i]] ],
{{i, 2, "Compound"}, 2, compounds, 1}
]
where data is the matrix, and compounds a variable set at the number of modelized compounds (1475 here). "compound" is a label for the slider.
The problem is, the slider moves much to fast as a few centimeters browse through 1400+ items.
I tried to do a drop-down menu with
MenuView[
Table[
ListLogLogPlot[data[[All, {1, i}]],PlotLabel -> data[[1, i]]], {i, 2, compounds}
]
]
It also works, but this is a processor killer process (10+ minutes on a Xeon 16-core server executing 16 kernels), as Mathematica try to graph all plots before displaying any of them. Also the drop-down has no name, just a series of numbers (1 for hydrogen to 1475 for C8H14N+,Grain-), even though the plot has a name.
What I am searching a way to plot a graph only on demand, with a name display in the drop-down list (and if required H by default). OR a field where I can enter the name of the compound. This seems to be possible with Dynamic[ ] command, but I don't manage to make it work properly.
Thanks
Mike's suggestion is a good one but if you don't want to go to the effort of putting it in a database, use the ContinuousAction->False option.
testdata =
Join[{Table[ToString[series[i-1]], {i, 1475}]},
RandomReal[{1., 100.}, {2000, 1476}]];
Manipulate[
ListLogLogPlot[testdata[[All, {1, i}]],
PlotLabel -> testdata[[1, i]]], {{i, 2, "Compound"}, 2, 1475, 1},
ContinuousAction -> False]
To get a popup menu, use the {i,listofvalues} syntax for the controller specification.
Manipulate[
ListLogLogPlot[testdata[[All, {1, i}]],
PlotLabel -> testdata[[1, i]]], {i, Range[2, 1475]},
ContinuousAction -> False]
This works pretty fast on my system. (Two year old MacBook Pro)
A fancier version:
spec = Thread[Range[2, 1476] -> Table[ToString[series[i]], {i, 1475}]];
Manipulate[
ListLogLogPlot[testdata[[All, {1, i}]],
PlotLabel -> testdata[[1, i]]], {{i, 2, "Compound"}, spec},
ContinuousAction -> False]
And if all you want to do is step through the images, click on the little plus next to a slider controller to get more detailed controls.
For entering names in an InputField, you could do something like
compounds = Rest[data[[1]]];
Manipulate[
If[MemberQ[compounds, compound], i = Position[compounds, compound][[1, 1]] + 1];
ListLogLogPlot[data[[All, {1, i}]], PlotLabel -> data[[1, i]]],
{{i, 2}, None},
{{compound, data[[1, 2]], "Compound"}, InputField[#, String] &}]
Here, compounds is a list of all the names of the compounds. The If statement in Manipulate is to check whether the name entered in the InputField is a valid compound or not.
Others have already given you ways to create one big popup list. If you don't want to scroll through a popup list of 1475 compounds, you could consider splitting the popup list into sublists. For example, this would split the whole list of compounds into sublists of n=50 elements which might make it easier to navigate
compounds = Rest[data[[1]]];
With[{n = 50},
Manipulate[
i = 1 + Position[compounds, name][[1, 1]];
ListLogLogPlot[data[[All, {1, i}]], PlotLabel -> data[[1, i]]],
{{i, 2}, None},
{{indexlist, 1, "Indices"},
Table[i -> ToString[(i - 1) n + 1] <> " through " <>
ToString[Min[i n, Length[compounds]]],
{i, Ceiling[Length[compounds]/n]}], PopupMenu},
{{name, compounds[[1]], "Compound"},
compounds[[n (indexlist - 1) + 1 ;;
Min[Length[compounds], n indexlist]]], PopupMenu}
]
]
For example, for
data = Table[Join[{i}, RandomReal[{0, 1}, 1000]], {i, 1000}];
data = Join[{Prepend[Table["list " <> ToString[i], {i, 1000}], "year"]}, data];
this looks like
For data sets of this size I'd recommend (as optimal) storing it all in a database and using DatabaseLink to call stuff as required. Then link your controllers, such as popup menus, to SQLExecute code or other SQL functions. Fragments like this would be the sort of thing that would do the job:
DynamicModule[{x,data, ...},
Column[{
PopupMenu[Dynamic[x], {1 -> "category 1", 2 -> "category 2", 3 -> "category 3", ...}],
Dynamic[
data = SQLExecute[conn, "SELECT * FROM myDatabase.table WHERE my_id = `1`;", {x}];
ListLogLogPlot[data]
]
}]
]
In reality you may want to be adding additional popups and doing joins and so on.
EDIT
Alternative that doesn't use databases but uses input fields as requested:
DynamicModule[{x = "He", rules, y},
rules = Rule ### Transpose[{data[[1, All]], Range[Length[data[[1, All]]]]}];
Column[{
InputField[Dynamic[x], String],
Dynamic[
y = x /. rules;
ListLogLogPlot[data[[All, {1, y}]], PlotLabel -> data[[1, y]]]
]
}]
]
For rules lists of this size you'd probably want to use Dispatch I'd imagine. See how the timing goes for that. It looks like this is some sort of experiment you are running so my first choice remains dumping it into a DB.
FURTHER EDIT
If you're relying on input fields then you will need to account for clumsy typing by inserting a conditional so that Mma only attempts to plot if y is an integer.
If[IntegerQ[y],
ListLogLogPlot,
Spacer[0]
]

NMinimize eats all memory b/c of unnecessary symbolic work

The following code is a naive way to find the least number whose square has n divisors (the minimum should be its log and the x_i the powers in its prime factorization). If I look at the case n=2000 and use ten variables instead of twenty, this uses somewhere around 600MB of memory. With the value of n I'm actually trying to find the answer for, I need around 20 variables to be sure of not missing the actual solution, and it quickly uses up all available memory and then thrashes swap.
n=8*10^6;
a = Table[N[Log[Prime[i]]], {i, 20}];
b = Table[Subscript[x, i], {i, 20}];
cond = Fold[And, Product[2 Subscript[x, i] + 1, {i, 20}] > n,
Table[Subscript[x, i] >= 0, {i, 20}]] && b \[Element] Integers;
NMinimize[{a.b, cond}, b, MaxIterations -> 1000]
It turns out that the problem isn't related to integer programming etc at all (removing the restriction to the integers doesn't help).
My best guess is that the problem is that Mathematica is wasting all that memory expanding Product[2 Subscript[x, i] + 1, {i, 20}]. If I replace the product with just Product[Subscript[x, i],{i,20}] and change the constraints to be >= 1 rather than 0 I get results without a hassle and without the kernel using more than 50MB of memory. (Though that preserves the inequality constraint and doesn't change the task of minimizing the objective function, it does mess up the integrality requirement- I get even results, which correspond to half-integers in the actual problem.)
One person on StackOverflow had a similar problem; in their case, they had an objective function which was getting evaluated symbolically at a huge cost. They were able to remedy it by making the function only accept numeric input, effectively hiding it from Mathematica's "I have the Expand[] hammer, and everything looks like a nail" tendency. But you can't hide the constraint behind such a function (Mathematica will complain it's an invalid constraint).
Any thoughts on how to fix this?
Edit: I know the correct answer- after my Mathematica code didn't work I used AMPL and a dedicated MINLP solver to get it (quite quickly too). I just want to know how I can ever hope to be able to use Mathematica's built-in nonlinear optimization features in the future despite the crazy things it seems to do with my constraints when I enter them in the only way I know how.
Can inhibit that condition from doing anything unless inputs are numeric, as below.
n = 8*10^6;
nvars = 20;
a = Table[N[Log[Prime[i]]], {i, nvars}];
b = Table[Subscript[x, i], {i, nvars}];
c1[xx : {_?NumericQ ..}] := Times ## (2 xx + 1);
c2 = Map[# >= 0 &, b];
c3 = b \[Element] Integers;
cond = Join[{c1[b] > n}, c2, {c3}];
In[29]:= Timing[NMinimize[{a.b, cond}, b, MaxIterations -> 400]]
Out[29]= {43.82100000000008, {36.77416664719056, {Subscript[x, 1] ->
3, Subscript[x, 2] -> 3, Subscript[x, 3] -> 2,
Subscript[x, 4] -> 2, Subscript[x, 5] -> 1, Subscript[x, 6] -> 1,
Subscript[x, 7] -> 1, Subscript[x, 8] -> 1, Subscript[x, 9] -> 1,
Subscript[x, 10] -> 1, Subscript[x, 11] -> 1,
Subscript[x, 12] -> 1, Subscript[x, 13] -> 0,
Subscript[x, 14] -> 0, Subscript[x, 15] -> 0,
Subscript[x, 16] -> 0, Subscript[x, 17] -> 0,
Subscript[x, 18] -> 0, Subscript[x, 19] -> 0,
Subscript[x, 20] -> 0}}}
---edit---
Thought I would point out that this can be set up as an integer linear programming problem. We use 0-1 variables for all possible combinations of primes and powers.
We can limit the number of primes using the fact that the solution cannot involve more primes than the minimum needed assuming all are raised to the first power. The objective is then minimal if they are consecutive starting at 2.
We will assume the max exponent is no more than 20. There is probably a convenient way to show this but it has not come to mind as yet.
The objective and constraints, in this formulation, are as below. We get a fully linear problem by taking logs of the divisor sigma equation.
n = 8*10^6;
nprimes = Ceiling[Log[2, n]];
maxexpon = 20;
vars = Array[x, {maxexpon, nprimes}];
fvars = Flatten[vars];
c1 = Map[0 <= # <= 1 &, fvars];
c2 = {Element[fvars, Integers]};
c3 = Thread[Total[vars] <= 1];
c4 = {Total[N[Log[2*Range[maxexpon] + 1]].vars] >= N#Log[n]};
constraints = Join[c1, c2, c3, c4];
obj = Range[maxexpon].vars.N[Log[Prime[Range[nprimes]]]];
Timing[{min, vals} = NMinimize[{obj, constraints}, fvars];]
Out[118]= {5.521999999999991, Null}
Pick[fvars, fvars /. vals, 1] /. x[j_, k_] :> {Prime[k], j}
Out[119]= {{11, 1}, {13, 1}, {17, 1}, {19, 1}, {23, 1}, {29, 1}, {31,
1}, {37, 1}, {5, 2}, {7, 2}, {2, 3}, {3, 3}}
This approach handles n=10^10 is around 23 seconds.
---end edit ---
Daniel Lichtblau
You can try this code instead:
Catch[Do[If[DivisorSigma[0, k^2] > 2000, Throw[k]], {k, 1000000}]]
which returns 180180.
ADDITION:
Catch[Do[If[Times##(2 FactorInteger[k][[All, 2]] + 1) > 2000, Throw[k]], {k, 1000000}]]
Seems to work faster.
ADDITION 2:
Behold for this ultra-improved version (but not 100% proved):
MinSquareWithDivisors[n_] :=
Min#Select[
Product[Prime[k]^#[[k]], {k, 1, Length[#]}] & /#
Flatten[IntegerPartitions /# Range[Ceiling[Log[2, n]]], 1],
DivisorSigma[0, #^2] > n &]
MinSquareWithDivisors[2000000000] gives 2768774904222066200260800 in ~4 seconds
Explanation:
First of all one needs to prove that the sum of the prime's exponents in this minimum number is at most Log[2, n]. I haven't found a proof yet, but it might be related to the ratio between successive primes.
Flatten[IntegerPartitions /# Range[Ceiling[Log[2, n]]], 1] gives you all the lists with Total <= Log[2, n], conveniently sorted from large to small.
Product[Prime[k]^#[[k]], {k, 1, Length[#]}] & use them as prime's exponents to create integers.
Min#Select[..., DivisorSigma[0, #^2] > n &] choose the minimal of them that agrees with the original condition.